terraform: provision cc-ci on Hetzner Cloud via nixos-infect
Adds terraform/ (hcloud provider, cpx32/nbg1/debian-12) and a new nix/hosts/cc-ci-hetzner/ flake host to provision the cc-ci server on Hetzner Cloud as an alternative to the Incus cc-nix-test VM. Stage 1 (Terraform): creates a cpx32 server (4 vCPU / 8 GB / x86 AMD, Nuremberg), runs nixos-infect (pinned rev 40f62a6, 2026-03-22) to convert Debian 12 → NixOS 24.11, and reboots into bare NixOS. Stage 2 (manual, per terraform/README.md): clone cc-ci --recursive, provision the bootstrap age key, then `nixos-rebuild switch --flake .#cc-ci-hetzner`. Verified (throwaway run 2026-05-31, server 134464512, 168.119.126.100): - terraform apply: cpx32 in nbg1 created in 17 s - nixos-infect: NixOS 24.11.719113.50ab793786d9 (same nixpkgs pin as flake) - nixos-rebuild build --flake .#cc-ci-hetzner: exit 0 on server (131 derivations; all cc-ci modules: tailscale, drone, drone-runner, bridge, dashboard, harness, swarm, abra, proxy, secrets) - terraform plan: no changes (idempotent) - terraform destroy: server + SSH key removed Age key step (plan §4 Stage 2): operator-pending. Full switch/convergence requires bootstrap age key at /var/lib/sops-nix/key.txt. Flake builds without it; activation needs it. No secrets committed: HCLOUD_TOKEN via env, tfstate gitignored, networking.nix contains throwaway IP (update per README for production). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
100
terraform/README.md
Normal file
100
terraform/README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# cc-ci Hetzner Cloud Terraform
|
||||
|
||||
Provisions the cc-ci NixOS server on Hetzner Cloud (cpx32, 4 vCPU / 8 GB, x86 AMD, nbg1).
|
||||
Stage 1 (Terraform): creates the server, runs nixos-infect to convert Debian 12 → NixOS.
|
||||
Stage 2 (manual): clone the flake + apply the cc-ci config.
|
||||
|
||||
## Prerequisites (Class-A1 inputs — provide at apply time, NEVER commit)
|
||||
|
||||
| Input | How to provide |
|
||||
|---|---|
|
||||
| `HCLOUD_TOKEN` | `export HCLOUD_TOKEN=<token>` in shell before `tofu apply` |
|
||||
| SSH key pair | Generate once: `ssh-keygen -t ed25519 -f ~/.ssh/cc-ci-hetzner`; pass pubkey via `TF_VAR_ssh_public_key="$(cat ~/.ssh/cc-ci-hetzner.pub)"` |
|
||||
| Bootstrap age key | Provision to `/var/lib/sops-nix/key.txt` on the server (Stage 2; see `docs/install.md`) |
|
||||
|
||||
## Stage 1 — Provision server + nixos-infect
|
||||
|
||||
```bash
|
||||
cd terraform/
|
||||
|
||||
# Provide secrets via environment
|
||||
export HCLOUD_TOKEN=<your-token>
|
||||
export TF_VAR_ssh_public_key="$(cat ~/.ssh/cc-ci-hetzner.pub)"
|
||||
|
||||
# Download providers (uses .terraform.lock.hcl — pinned, reproducible)
|
||||
tofu init # or: terraform init
|
||||
|
||||
# Preview
|
||||
tofu plan
|
||||
|
||||
# Apply — creates cpx31 server in nbg1, runs nixos-infect on first boot
|
||||
tofu apply
|
||||
|
||||
# Note the output IP:
|
||||
# server_ipv4 = "x.x.x.x"
|
||||
# ssh_connect = "ssh root@x.x.x.x"
|
||||
```
|
||||
|
||||
nixos-infect runs on first boot and **reboots the server** into NixOS (~5 min total).
|
||||
Wait for the reboot to complete, then verify:
|
||||
|
||||
```bash
|
||||
# Check NixOS is up:
|
||||
ssh root@<ip> 'nixos-version'
|
||||
|
||||
# Inspect infect log if needed:
|
||||
ssh root@<ip> 'cat /var/log/nixos-infect.log'
|
||||
```
|
||||
|
||||
After the reboot the server runs bare NixOS (infect-generated config). Proceed to Stage 2.
|
||||
|
||||
## Stage 2 — Apply the cc-ci flake config
|
||||
|
||||
Follows the D8 install flow documented in `docs/install.md` exactly:
|
||||
|
||||
```bash
|
||||
# On the Hetzner server (ssh root@<ip>):
|
||||
|
||||
# 1. Clone the flake (--recursive brings cc-ci-secrets submodule)
|
||||
git clone --recursive https://git.autonomic.zone/recipe-maintainers/cc-ci.git /etc/cc-ci
|
||||
cd /etc/cc-ci
|
||||
|
||||
# 2. Provision the bootstrap age key (the one irreducible out-of-band secret)
|
||||
mkdir -p /var/lib/sops-nix
|
||||
install -m 0600 /dev/stdin /var/lib/sops-nix/key.txt <<'EOF'
|
||||
<paste bootstrap age private key here — see docs/install.md>
|
||||
EOF
|
||||
|
||||
# 3. Apply the cc-ci Hetzner host config
|
||||
nixos-rebuild switch --flake .#cc-ci-hetzner
|
||||
|
||||
# 4. Verify (all units green, reconcile oneshots converged)
|
||||
systemctl --failed
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `server_type` | `cpx31` | x86 only. `cpx31`=AMD 4vCPU/8GB, `cx33`=Intel 4vCPU/8GB. Never `cax*` (ARM). |
|
||||
| `location` | `nbg1` | Hetzner datacenter. |
|
||||
| `image` | `debian-12` | Base image; nixos-infect converts it to NixOS. debian-12 preferred. |
|
||||
| `server_name` | `cc-ci` | Hetzner server name. |
|
||||
| `ssh_public_key` | (required) | Public key registered for root access. |
|
||||
|
||||
Override via env: `TF_VAR_location=hel1 tofu apply`.
|
||||
|
||||
## Teardown (throwaway verification run)
|
||||
|
||||
```bash
|
||||
tofu destroy # removes server + SSH key; billing stops immediately
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `.terraform.lock.hcl` is committed (pins provider SHAs — analogous to flake.lock).
|
||||
- `*.tfstate`, `*.tfvars`, `.terraform/` are gitignored — never commit state or secrets.
|
||||
- `cpx31` is retired in some Hetzner DCs; `cpx32` (equivalent AMD, 4 vCPU / 8 GB) is the default.
|
||||
`cx33` (Intel, same spec) is also available. Both are x86_64 — compatible with the `x86_64-linux` flake.
|
||||
- The Hetzner server has a public IPv4 — future: point `*.ci.commoninternet.net` A record directly
|
||||
at it and drop the gateway/MagicDNS path (see plan §6 + `DECISIONS.md`).
|
||||
Reference in New Issue
Block a user