Infrastructure-as-Code (IaC) from First Commit
Core principle: Every new project, from its first commit, must be fully rebuildable from zero using only git clone + a single, documented bootstrap command. All infrastructure state is declarative, version-controlled, and reproducible without tribal knowledge or manual steps.
Why this matters
- Reproducibility: A new team member (or the original author months later) can spin up the entire environment deterministically.
- Reliability: Infrastructure changes are reviewed in pull requests, tested in CI, and rollback-safe.
- Disaster recovery: Loss of a server or credential requires only re-running the bootstrap process.
- Onboarding: No "run these commands manually" instructions; no "remember to configure this first."
Mental test before scaffolding any project
"If another person or an AI agent needed to rebuild this project from zero right now, would git clone <repo> && ./bootstrap.sh be sufficient? Or are there undocumented, manual steps?"
If the answer is "there are manual steps," the project lacks proper IaC coverage.
Tool selection by context
Use the IaC tool native to your infrastructure platform. There is no one-size-fits-all tool — the platform dictates the choice:
| Context |
Native IaC Tool |
Example |
| VPS / Linux server |
Ansible (configuration) + Terraform (if cloud provisioning) |
ansible-playbook site.yml |
| Frontend SaaS (Next.js, Vite, etc.) |
Platform config-as-code + GitHub Actions |
Vercel/Netlify/Cloudflare Pages deployment config |
| Serverless APIs (AWS Lambda, Cloudflare Workers) |
SST / SAM / CDK / Wrangler |
sst deploy or wrangler deploy |
| Mobile (iOS, Android, Expo) |
Fastlane + EAS/Code Push config |
fastlane build + eas build |
| Kubernetes |
ArgoCD / Flux + Helm charts |
GitOps with declarative manifests in git |
| ML / data pipelines |
DVC + MLflow + Airflow DAGs |
Reproducible training/inference pipelines |
| Browser extension / desktop app |
Build manifest + bundler config + CI/CD |
GitHub Actions release workflow |
| Static docs / sites |
GitHub Actions + hosting provider config |
Build → upload → serve, automated |
Key principle: Choose based on the infrastructure platform, not on what the team prefers. The tool should map 1:1 to the target platform's native declarative model.
Minimum directory structure for any new project
Adapt this template to your context, but all elements should exist by first commit:
project-root/
├── infra/ # Declarative infrastructure code
│ ├── main.tf # (Terraform) or
│ ├── site.yml # (Ansible) or
│ ├── sst.config.ts # (SST) or equivalent
│ └── secrets.sops.yaml # encrypted secrets (NEVER plaintext)
├── .github/workflows/ # CI/CD pipelines
│ ├── deploy.yml
│ └── test.yml
├── scripts/
│ └── bootstrap.sh # Single command to rebuild from zero
├── docs/
│ ├── architecture.md # System design, deployment diagram, key decisions
│ ├── decisions.md # Architecture Decision Records (ADRs)
│ └── runbooks/ # Operations: "how to X" (restart service, add user, etc.)
│ ├── deploy.md
│ ├── troubleshoot.md
│ └── backup-restore.md
├── README.md # Top section: "How to bootstrap from zero"
├── CHANGELOG.md # Version history and deployed changes
└── [project files]
Bootstrap script — the single point of entry
Your scripts/bootstrap.sh (or equivalent for your language/OS) should be the only documentation users need to get from zero to running.
Requirements:
- Idempotent: safe to run multiple times (e.g.,
mkdir -p not mkdir)
- Self-documenting: comments explain what each section does
- Fail-fast: exit on first error (
set -e in bash)
- Secrets handling: load from environment variables or secure vaults, never commit plaintext
- Validation: verify prerequisites (Go version, Docker running, credentials available) before proceeding
Example structure:
#!/bin/bash
set -e
echo "Bootstrap: project-name"
# 1. Check prerequisites
if ! command -v docker &> /dev/null; then
echo "ERROR: docker not found. Install Docker and try again."
exit 1
fi
# 2. Fetch dependencies
go mod download
npm ci
# 3. Set up infrastructure
terraform -chdir=infra/ init
terraform -chdir=infra/ apply -auto-approve
# 4. Configure database
./scripts/migrate-db.sh
# 5. Load secrets from vault (not committed)
source <(sops -d secrets.sops.yaml | envsubst)
# 6. Start services
docker-compose up -d
echo "✓ Bootstrap complete. Services running at http://localhost:8080"
Secrets management
- Never commit plaintext credentials to git — not even in
.env.example.
- Use encrypted files (sops + age, Sealed Secrets, HashiCorp Vault, AWS Secrets Manager).
- Store encryption keys in a secure vault (Bitwarden, 1Password, GitHub Environments).
- Document in bootstrap how to obtain/inject secrets:
source <(vault kv get --json secret/data | envsubst).
- Test bootstrap against a clean environment to ensure it doesn't silently assume pre-configured credentials.
Documentation requirements
- README.md — "How to bootstrap from zero" is the first section, not buried.
- docs/architecture.md — System design, key components, deployment topology, why you made certain choices.
- docs/decisions.md or docs/adrs/ — Why was tool X chosen over Y? Why this database? Decisions should be reviewable in git history.
- docs/runbooks/ — Common operational tasks ("restart the service," "add a user," "inspect logs," "backup the database").
- CHANGELOG.md — Changes by version; helps the team track what shipped when.
Anti-patterns — forbidden
- ✗ "I configured it by hand and I remember what I did" — if you remember, write it down as IaC.
- ✗ README that says "see wiki" or "ask in Slack" for bootstrap steps.
- ✗ Architecture decisions buried in chat history or git commit messages (use an ADR document).
- ✗ Running
npm install or pip install without pinning versions in lockfiles.
- ✗ Mixing secrets plaintext with code; using
.env files committed to git.
- ✗ A bootstrap that works "most of the time" but sometimes requires manual fixes — make it deterministic.
- ✗ Test bootstrap only on "the developer's machine" — test it fresh against a clean environment in CI.
How to test your IaC
- Clean-room test: Spin up a fresh VM, clone your repo, run bootstrap, verify everything works.
- CI integration: Add bootstrap to your CI pipeline so it runs on every commit — catches regressions early.
- Idempotence test: Run bootstrap twice in a row; the second run should be a no-op or safely re-apply the same state.
- Disaster recovery: Simulate failure of a key component (database, service) and verify recovery procedures are documented and work.
Applying this skill to different project types
Web application (Next.js → Vercel):
infra/: Vercel project config (environment variables, domains, build settings) as infrastructure-as-code.
scripts/bootstrap.sh: Clone repo, npm ci, deploy via Vercel CLI or GitHub Actions.
docs/deployment.md: How to promote from staging to production.
Backend service (Go API → Kubernetes):
infra/: Helm chart, kustomize overlays, or plain YAML manifests; stored in git.
scripts/bootstrap.sh: Install kubectl/Helm, apply manifests, wait for rollout, run migrations.
docs/runbooks/scale.md: How to add replicas, upgrade image, perform canary deployments.
Microservices (Docker Compose):
docker-compose.yml: All services, networks, volumes defined.
.env.example: Template for environment variables (never include secrets).
scripts/bootstrap.sh: Build images, run migrations, start containers.
docs/local-development.md: How to develop and test locally.
Terraform-managed cloud infrastructure:
infra/terraform/: Organized by environment (dev/, staging/, prod/).
scripts/bootstrap.sh: terraform init → terraform plan → terraform apply.
docs/decisions.md: Why this VPC design, why this RDS tier, etc.
- State management: Store
.tfstate in a remote backend (S3, Terraform Cloud), never commit locally.
Application
This principle applies to all new projects, regardless of team size, project scope, or platform. An AI agent scaffolding a project should include this structure from the first commit, not retrofit it later.
When to invoke this skill:
- Scaffolding a new project or repository
- Choosing infrastructure tools for a new context
- Planning bootstrap automation for an existing project that lacks it
- Reviewing infrastructure code for reproducibility and idempotence
- Preparing a project for team handoff or long-term maintenance
1---2name: iac-first-commit3description: Infrastructure-as-Code from the first commit — every new project must be rebuildable from git clone + one command, with declarative state in code and idempotent execution. Use when scaffolding new projects, bootstrapping infrastructure, choosing IaC tools (Ansible/Terraform/SST/Fastlane), or setting up infra/, scripts/, or deployment automation.4---56## Infrastructure-as-Code (IaC) from First Commit78**Core principle:** Every new project, from its first commit, must be **fully rebuildable from zero** using only `git clone` + a single, documented bootstrap command. All infrastructure state is declarative, version-controlled, and reproducible without tribal knowledge or manual steps.910### Why this matters1112- **Reproducibility:** A new team member (or the original author months later) can spin up the entire environment deterministically.13- **Reliability:** Infrastructure changes are reviewed in pull requests, tested in CI, and rollback-safe.14- **Disaster recovery:** Loss of a server or credential requires only re-running the bootstrap process.15- **Onboarding:** No "run these commands manually" instructions; no "remember to configure this first."1617### Mental test before scaffolding any project1819*"If another person or an AI agent needed to rebuild this project from zero right now, would `git clone <repo> && ./bootstrap.sh` be sufficient? Or are there undocumented, manual steps?"*2021If the answer is "there are manual steps," the project lacks proper IaC coverage.2223### Tool selection by context2425Use the IaC tool native to your infrastructure platform. There is no one-size-fits-all tool — the platform dictates the choice:2627| Context | Native IaC Tool | Example |28|---|---|---|29| VPS / Linux server | Ansible (configuration) + Terraform (if cloud provisioning) | `ansible-playbook site.yml` |30| Frontend SaaS (Next.js, Vite, etc.) | Platform config-as-code + GitHub Actions | Vercel/Netlify/Cloudflare Pages deployment config |31| Serverless APIs (AWS Lambda, Cloudflare Workers) | SST / SAM / CDK / Wrangler | `sst deploy` or `wrangler deploy` |32| Mobile (iOS, Android, Expo) | Fastlane + EAS/Code Push config | `fastlane build` + `eas build` |33| Kubernetes | ArgoCD / Flux + Helm charts | GitOps with declarative manifests in git |34| ML / data pipelines | DVC + MLflow + Airflow DAGs | Reproducible training/inference pipelines |35| Browser extension / desktop app | Build manifest + bundler config + CI/CD | GitHub Actions release workflow |36| Static docs / sites | GitHub Actions + hosting provider config | Build → upload → serve, automated |3738**Key principle:** Choose based on the infrastructure platform, not on what the team prefers. The tool should map 1:1 to the target platform's native declarative model.3940### Minimum directory structure for any new project4142Adapt this template to your context, but all elements should exist by first commit:4344```45project-root/46├── infra/ # Declarative infrastructure code47│ ├── main.tf # (Terraform) or48│ ├── site.yml # (Ansible) or49│ ├── sst.config.ts # (SST) or equivalent50│ └── secrets.sops.yaml # encrypted secrets (NEVER plaintext)51├── .github/workflows/ # CI/CD pipelines52│ ├── deploy.yml53│ └── test.yml54├── scripts/55│ └── bootstrap.sh # Single command to rebuild from zero56├── docs/57│ ├── architecture.md # System design, deployment diagram, key decisions58│ ├── decisions.md # Architecture Decision Records (ADRs)59│ └── runbooks/ # Operations: "how to X" (restart service, add user, etc.)60│ ├── deploy.md61│ ├── troubleshoot.md62│ └── backup-restore.md63├── README.md # Top section: "How to bootstrap from zero"64├── CHANGELOG.md # Version history and deployed changes65└── [project files]66```6768### Bootstrap script — the single point of entry6970Your `scripts/bootstrap.sh` (or equivalent for your language/OS) should be **the only documentation users need** to get from zero to running.7172**Requirements:**73- Idempotent: safe to run multiple times (e.g., `mkdir -p` not `mkdir`)74- Self-documenting: comments explain what each section does75- Fail-fast: exit on first error (`set -e` in bash)76- Secrets handling: load from environment variables or secure vaults, never commit plaintext77- Validation: verify prerequisites (Go version, Docker running, credentials available) before proceeding7879**Example structure:**8081```bash82#!/bin/bash83set -e8485echo "Bootstrap: project-name"8687# 1. Check prerequisites88if ! command -v docker &> /dev/null; then89 echo "ERROR: docker not found. Install Docker and try again."90 exit 191fi9293# 2. Fetch dependencies94go mod download95npm ci9697# 3. Set up infrastructure98terraform -chdir=infra/ init99terraform -chdir=infra/ apply -auto-approve100101# 4. Configure database102./scripts/migrate-db.sh103104# 5. Load secrets from vault (not committed)105source <(sops -d secrets.sops.yaml | envsubst)106107# 6. Start services108docker-compose up -d109110echo "✓ Bootstrap complete. Services running at http://localhost:8080"111```112113### Secrets management114115- **Never commit plaintext credentials** to git — not even in `.env.example`.116- Use encrypted files (sops + age, Sealed Secrets, HashiCorp Vault, AWS Secrets Manager).117- Store encryption keys in a secure vault (Bitwarden, 1Password, GitHub Environments).118- Document in bootstrap how to obtain/inject secrets: `source <(vault kv get --json secret/data | envsubst)`.119- Test bootstrap against a clean environment to ensure it doesn't silently assume pre-configured credentials.120121### Documentation requirements1221231. **README.md** — "How to bootstrap from zero" is the **first section**, not buried.1242. **docs/architecture.md** — System design, key components, deployment topology, why you made certain choices.1253. **docs/decisions.md** or **docs/adrs/** — Why was tool X chosen over Y? Why this database? Decisions should be reviewable in git history.1264. **docs/runbooks/** — Common operational tasks ("restart the service," "add a user," "inspect logs," "backup the database").1275. **CHANGELOG.md** — Changes by version; helps the team track what shipped when.128129### Anti-patterns — forbidden130131- ✗ "I configured it by hand and I remember what I did" — if you remember, write it down as IaC.132- ✗ README that says "see wiki" or "ask in Slack" for bootstrap steps.133- ✗ Architecture decisions buried in chat history or git commit messages (use an ADR document).134- ✗ Running `npm install` or `pip install` without pinning versions in lockfiles.135- ✗ Mixing secrets plaintext with code; using `.env` files committed to git.136- ✗ A bootstrap that works "most of the time" but sometimes requires manual fixes — make it deterministic.137- ✗ Test bootstrap only on "the developer's machine" — test it fresh against a clean environment in CI.138139### How to test your IaC1401411. **Clean-room test:** Spin up a fresh VM, clone your repo, run bootstrap, verify everything works.1422. **CI integration:** Add bootstrap to your CI pipeline so it runs on every commit — catches regressions early.1433. **Idempotence test:** Run bootstrap twice in a row; the second run should be a no-op or safely re-apply the same state.1444. **Disaster recovery:** Simulate failure of a key component (database, service) and verify recovery procedures are documented and work.145146### Applying this skill to different project types147148**Web application (Next.js → Vercel):**149- `infra/`: Vercel project config (environment variables, domains, build settings) as infrastructure-as-code.150- `scripts/bootstrap.sh`: Clone repo, `npm ci`, deploy via Vercel CLI or GitHub Actions.151- `docs/deployment.md`: How to promote from staging to production.152153**Backend service (Go API → Kubernetes):**154- `infra/`: Helm chart, kustomize overlays, or plain YAML manifests; stored in git.155- `scripts/bootstrap.sh`: Install kubectl/Helm, apply manifests, wait for rollout, run migrations.156- `docs/runbooks/scale.md`: How to add replicas, upgrade image, perform canary deployments.157158**Microservices (Docker Compose):**159- `docker-compose.yml`: All services, networks, volumes defined.160- `.env.example`: Template for environment variables (never include secrets).161- `scripts/bootstrap.sh`: Build images, run migrations, start containers.162- `docs/local-development.md`: How to develop and test locally.163164**Terraform-managed cloud infrastructure:**165- `infra/terraform/`: Organized by environment (dev/, staging/, prod/).166- `scripts/bootstrap.sh`: `terraform init` → `terraform plan` → `terraform apply`.167- `docs/decisions.md`: Why this VPC design, why this RDS tier, etc.168- **State management:** Store `.tfstate` in a remote backend (S3, Terraform Cloud), never commit locally.169170---171172## Application173174This principle applies to **all new projects**, regardless of team size, project scope, or platform. An AI agent scaffolding a project should include this structure from the first commit, not retrofit it later.175176**When to invoke this skill:**177- Scaffolding a new project or repository178- Choosing infrastructure tools for a new context179- Planning bootstrap automation for an existing project that lacks it180- Reviewing infrastructure code for reproducibility and idempotence181- Preparing a project for team handoff or long-term maintenance