Files
cc-ci/nix/hosts/cc-ci-hetzner/configuration.nix
T
notplantsandClaude Fable 5.1 9b99f81f5f
continuous-integration/drone/push Build is failing
nix: export the CI server as nixosModules.cc-ci-server
The whole server (every service module, the harness tooling, sops wiring,
acme-dns) becomes one reusable module, nix/modules/default.nix, so another
flake can run cc-ci on a host it defines. First consumer: the
cc-ci-orchestrator repo's `#cc-ci` host, which runs the CI server and the
orchestrator together on one Hetzner machine.

Two things the modules hard-coded become options (nix/modules/options.nix):
- cc-ci.publicIPv4 — acme-dns's listen address and ns-acme glue record.
- cc-ci.sopsFile — the secrets.yaml path; defaults to the secrets/ submodule,
  but a consumer that imports cc-ci as a plain input (no private submodule)
  points it at the deployed --recursive checkout and sops-nix reads it at
  activation (validateSopsFiles off for that case).

The standalone host (nix/hosts/cc-ci-hetzner) now only carries hardware,
networking and identity and imports the module via the flake. Verified: the
`#cc-ci` system derivation is byte-identical before and after
(/nix/store/ckp1244bz86fz3qbx81n5kx60c1lak3m-…531670d.drv on both).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqkQq3CDmFWcQ7u1LzoyRz
2026-09-07 19:56:58 +00:00

58 lines
2.5 KiB
Nix

# cc-ci on Hetzner Cloud — the canonical STANDALONE CI-server host.
# Hardware + networking + host identity only; every cc-ci service comes from the shared
# `nixosModules.cc-ci-server` module (nix/modules/default.nix), which flake.nix adds to this
# host. The same module builds the combined CI-server + orchestrator host declared in
# recipe-maintainers/cc-ci-orchestrator (`#cc-ci`), which is where cc-ci is moving (2026-09).
#
# To apply after `terraform apply` + nixos-infect:
# git clone --recursive https://git.autonomic.zone/recipe-maintainers/cc-ci.git /etc/cc-ci
# install -m600 <age-private-key> /var/lib/sops-nix/key.txt
# nixos-rebuild switch --flake 'git+file:///etc/cc-ci?submodules=1#cc-ci'
{ pkgs, ... }:
{
imports = [
./hardware.nix
./networking.nix
];
# This host's public address: acme-dns listens on it and publishes it as the ns-acme glue.
cc-ci.publicIPv4 = "91.98.47.73";
# Built from a --recursive clone, so the sops file is the default (the secrets/ submodule).
# Tailscale — keeps the orchestrator→cc-ci access path unchanged (direct peer).
# On the Hetzner host the auth key is also seeded via /etc/ts-auth-key.
services.tailscale = {
enable = true;
authKeyFile = "/etc/ts-auth-key";
extraUpFlags = [ "--hostname=cc-ci" ];
};
# SSH — allow root login over tailscale (same as Incus host).
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
# Root SSH authorized keys — preserved across nixos-rebuild switches.
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOk8NaeBdPbS2gfUvbny8h0AkZlVjGYHzx4QPXSJ38gd claude@claude-vm"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJVlfoLBPseQ9fA9534KmRg2KWcksKZGzAJIpHJ2JpsI mfowler.email@protonmail.com"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAcyTGb/wVgdhg5oBCZZvBaR1RuUQRY/3WHnOQpNDCsp claude-cc-ci-sandbox@20260526"
];
# Firewall — Hetzner has a public IP, so open 80+443 for Traefik.
# Tailscale interface is trusted (no port restrictions for orchestrator access).
# Plan §6: v1 keeps the sops wildcard cert; evaluate ACME-on-public-IP as follow-up.
networking.firewall = {
enable = true;
trustedInterfaces = [ "tailscale0" ];
allowedTCPPorts = [ 22 80 443 ];
};
# The recipe-test tool set (ccciRuntimeTools) is installed by the cc-ci-server module; the ssh
# client is a host-only addition (not part of the recipe-test tool set).
environment.systemPackages = [ pkgs.openssh ];
system.stateVersion = "24.11";
}