Some checks failed
continuous-integration/drone/push Build is failing
The cc-ci server already runs on Hetzner (migration done; nix/hosts/cc-ci-hetzner landed directly on main 2026-05-31). PR#2's host config was superseded by newer main commits, but its terraform/ provisioning scaffolding (cpx32 + nixos-infect) was never preserved. Add it here as the infrastructure-of-record so the box is reproducible. .gitignore keeps tfstate + secret tfvars out; HCLOUD_TOKEN is an env var at apply time (no secrets committed). PR#2 closed as superseded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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
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:
# 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:
# 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)
tofu destroy # removes server + SSH key; billing stops immediately
Notes
.terraform.lock.hclis committed (pins provider SHAs — analogous to flake.lock).*.tfstate,*.tfvars,.terraform/are gitignored — never commit state or secrets.cpx31is 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 thex86_64-linuxflake.- The Hetzner server has a public IPv4 — future: point
*.ci.commoninternet.netA record directly at it and drop the gateway/MagicDNS path (see plan §6 +DECISIONS.md).