Nuno
Nuno

From 45 Hand-Run Scripts to Terraform for an AI Startup on Bare Metal

Overview

An AI startup ran its SaaS on bare-metal servers in Europe. The platform was built by about 45 shell scripts that had to be run by hand in a set order. In May 2026 Nuno replaced that with 6 Terraform modules and 5 environments, plus CI that checks every change. A fresh server now goes from terraform apply to a validated host in about 17 minutes. The first CI plan against a freshly built server reported no drift. The git and CI platform moved to its own server with its full history, and production moved to a disk-encrypted server in a phased cutover that rolled back once and then completed the same evening.

The problem

About 45 imperative shell scripts built everything: host bootstrap, cluster add-ons, secrets typed into Vault by hand, per-app database setup, DNS, and deploy wrappers. They had to run in the right order, and that order lived in people's heads. The pieces inside the cluster were in decent shape. The glue between Vault, Postgres, Kubernetes and DNS was not, and there was no CI for infrastructure at all.

What Nuno did

Nuno wrote a migration plan in five layers and picked one tool for the job, Terraform with cloud-init, instead of a Terraform and Ansible mix. Six modules now cover the bare-metal server and its bootstrap (private networking, Postgres, Vault, k3s, node monitoring and firewall), Vault policies and Kubernetes auth, Postgres roles and databases, DNS, object storage, and the backup bucket. The git and CI server is built first from a laptop, and CI then builds everything else. CI lints and validates every change, and applies only through a guarded manual pipeline. Before touching production Nuno proved the whole thing on a throwaway environment. Nuno also benchmarked the new hosts, found them much slower on disk, and moved production back onto the fast server, this time with disk encryption rehearsed first on a throwaway box.

What went wrong

The first control-plane cutover attempt, on a Sunday in late May, failed when a script bug wiped the staged snapshot. Nuno rolled back, fixed the script and tried again that evening. The control plane moved, and about 66 minutes after the retry started all app pods were running and every URL was healthy. Nuno had also added a GitOps controller as an upgrade, then removed it on purpose a few days later because it fought the existing manual canary releases. The release flow the client already trusted stayed.

Results

On a smoke test in May 2026, a fresh bare-metal server went from terraform apply to a validated host with all six health checks green in about 17 minutes. The next day the CI pipeline planned against it and reported no changes, so the CI-built and laptop-built state matched. The git and CI platform moved with 693 pipeline runs of history. The production cutover rolled back once and then completed in about 66 minutes the same evening. The documented rebuild from zero is about 90 minutes, with a few manual steps kept on purpose, such as unsealing Vault.

Solutions

Infrastructure as code

  • About 45 hand-run scripts replaced by 6 Terraform modules and 5 environments.
  • Server bootstrap through cloud-init, checked by health checks at the end of every build.
  • The existing production server imported into Terraform, and a retired server later destroyed through Terraform.

CI and platform

  • Lint and validate on every change, with apply behind a manual guard.
  • Git and CI platform moved to its own server with all users, repositories, issues and 693 pipeline runs.
  • Production data on encrypted disks, with nightly versioned backups added later.

More cases

Enhance Your Cloud Experience with Our Expertise

Don't let fears of service unavailability or lack of support hold you back. Trust in our commitment to excellence and guarantee of service.

Contact Us Today