Files
cc-ci-orchestrator/terraform

terraform — Hetzner cc-ci-orchestrator server

Provisions a Hetzner cpx11 (2 vCPU / 2 GB dedicated AMD / 40 GB NVMe) for the cc-ci loops runtime (Builder + Adversary + Watchdog + Orchestrator sessions), replacing the slow b1 Incus VM. Uses nixos-infect to convert Debian → NixOS, then converges via the cc-ci-orchestrator flake.


Stage 1 — provision the server

# from /srv/cc-ci/terraform/
source /srv/cc-ci/.testenv          # loads HCLOUD_TOKEN
export TF_VAR_ssh_public_key="$(cat /home/loops/.ssh/cc-ci-root-ed25519.pub)"

tofu init
tofu plan
tofu apply

Note the server_ipv4 output. nixos-infect runs on first boot — wait ~5 min, then:

# confirm NixOS is up (may need to retry while infect reboots)
ssh root@<server_ipv4> 'nixos-version'

Stage 2 — converge to cc-ci-orchestrator-hetzner

2a. Capture hardware config

ssh root@<server_ipv4> 'cat /etc/nixos/hardware-configuration.nix'

Copy the output to nix/hosts/cc-ci-orchestrator-hetzner/hardware.nix in this repo, commit, push.

2b. Stage workspace on the new server

ssh root@<server_ipv4>

# Install Tailscale auth key (from .testenv TS_AUTH_KEY)
echo "<TS_AUTH_KEY>" > /etc/ts-auth-key && chmod 600 /etc/ts-auth-key

# Clone this repo as the loops user workspace
git clone --recursive \
  https://autonomic-bot:<token>@git.autonomic.zone/recipe-maintainers/cc-ci-orchestrator.git \
  /srv/cc-ci-orch
ln -sfn /srv/cc-ci-orch /srv/cc-ci   # loops expect /srv/cc-ci

# Place master age key (copied from current VM .sops/master-age.txt)
mkdir -p /srv/cc-ci/.sops
scp loops@<old-vm>:/srv/cc-ci/.sops/master-age.txt /srv/cc-ci/.sops/master-age.txt
chmod 600 /srv/cc-ci/.sops/master-age.txt

2c. Run nixos-rebuild

# on the new server
cd /srv/cc-ci
nixos-rebuild switch --flake .#cc-ci-orchestrator-hetzner

2d. Stage credentials (not in git — placed once)

# SSH key for reaching cc-ci
mkdir -p /home/loops/.ssh && chmod 700 /home/loops/.ssh
# scp cc-ci-root-ed25519 from current VM or copy content
chmod 600 /home/loops/.ssh/cc-ci-root-ed25519

# .testenv (GITEA creds, etc.)
cp /path/to/.testenv /srv/cc-ci/.testenv && chmod 600 /srv/cc-ci/.testenv

2e. Auth claude and start loops

# as loops user on new server
sudo -u loops /home/loops/.local/bin/claude auth login   # device code — operator step

# start the loops
cd /srv/cc-ci && sudo -u loops ./cc-ci-plan/launch.sh start

2f. Verify

tmux ls   # should show cc-ci-builder, cc-ci-adv, cc-ci-watchdog

Cutover

Once the new server is running and the loops are verified:

  1. Update the Host cc-ci entry in the current VM's /home/loops/.ssh/config if needed
  2. Stop the old Incus VM (or just leave it idle — it costs nothing in disk)

Variables

Variable Default Notes
location nbg1 Nuremberg
server_type cpx11 2 vCPU / 2 GB dedicated AMD. Upgrade to cpx21 (4 GB) if OOM.
image debian-12 nixos-infect base
server_name cc-ci-orchestrator
ssh_public_key required Pass via TF_VAR_ssh_public_key

State

terraform.tfstate and terraform.tfstate.backup are gitignored. Keep the state file locally or in a remote backend — losing it means tofu destroy can't find the server (use tofu import to recover, or delete directly via the Hetzner console).