From ab839ae61d23479d7ebb25e9e9193e3776de2d20 Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Tue, 26 May 2026 21:47:42 +0100 Subject: [PATCH] M1: Docker + single-node swarm via Nix (swarm-init + proxy overlay) Co-Authored-By: Claude Opus 4.7 (1M context) --- BACKLOG.md | 3 ++- JOURNAL.md | 23 ++++++++++++++++++++ STATUS.md | 5 +++-- hosts/cc-ci/configuration.nix | 1 + modules/swarm.nix | 41 +++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 modules/swarm.nix diff --git a/BACKLOG.md b/BACKLOG.md index a2fac85..a7a9d1c 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -14,7 +14,8 @@ Two single-writer sections (§6.1): Builder edits only `## Build backlog`; Adver → CLAIMED 2026-05-26, awaiting Adversary (see STATUS.md) ### M1 — Swarm + abra target -- [ ] Docker + single-node swarm via Nix +- [x] Docker + single-node swarm via Nix (modules/swarm.nix: docker + swarm-init oneshot + `proxy` + overlay net + daily autoprune). Verified: Swarm=active, proxy overlay present. - [ ] Traefik (file provider → /var/lib/ci-certs/live/) + per-run wildcard router - [ ] abra installed; deploy + tear down a trivial recipe by hand over HTTPS - [ ] Gate: M1 — recipe reachable over HTTPS at *.ci.commoninternet.net, torn down clean diff --git a/JOURNAL.md b/JOURNAL.md index 6babd15..2f332ca 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -97,3 +97,26 @@ with M1 (independent infra build), without advancing to M2 until M0 shows PASS. **Next:** M1 — Docker + single-node swarm via Nix (modules/swarm.nix), then Traefik (file provider → /var/lib/ci-certs/live/) + abra, then a by-hand HTTPS deploy/teardown of a trivial recipe. + +## 2026-05-26 — M1: Docker + single-node swarm via Nix + +**modules/swarm.nix:** `virtualisation.docker.enable` + daily autoprune (--all --volumes until=24h +to protect the 28 GiB root), `docker` in systemPackages, and a `swarm-init` oneshot +(`docker swarm init --advertise-addr 127.0.0.1` if not active; `docker network create --driver +overlay --attachable proxy` if absent). Imported into configuration.nix. + +**Build + switch:** `nixos-rebuild build --flake .#cc-ci` → EXIT 0; `systemd-run … switch` → +`Result=success`. + +**Verify (commands + output):** +- `systemctl show swarm-init -p Result` → `Result=success` +- `docker info --format ...` → `Swarm=active Managers=1 Nodes=1` +- `docker network ls --filter name=proxy` → `proxy overlay swarm` +- `systemctl is-system-running` → `running`; `--failed` → none. + +**Next:** Traefik as a swarm stack (Nix-declared compose + `docker stack deploy` oneshot): docker +swarm provider + file provider serving /var/lib/ci-certs/live/{fullchain,privkey}.pem on :443, +attached to `proxy`. Then abra install + by-hand HTTPS deploy/teardown of a trivial recipe (M1 gate). +Rationale for swarm-service Traefik over a host `services.traefik`: a host process isn't on the +`proxy` overlay, so it can't reach swarm service VIPs; coop-cloud recipes assume an on-`proxy` +Traefik watching swarm labels. diff --git a/STATUS.md b/STATUS.md index c5ac297..57992fa 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,8 +1,9 @@ # STATUS — cc-ci Builder **Phase:** M0 → M1. M0 complete & CLAIMED; starting M1 (swarm + Traefik + abra) while awaiting verdict. -**In-flight:** M1 — Docker + single-node swarm via Nix (first M1 task). -**Last updated:** 2026-05-26 (M0 claimed) +**In-flight:** M1 — Traefik next (file provider → /var/lib/ci-certs/live/, docker-swarm provider). +Docker + single-node swarm done. +**Last updated:** 2026-05-26 (M1 swarm up) ## Gates - **Gate: M0 — CLAIMED, awaiting Adversary** (2026-05-26). Evidence: flake rebuilds cc-ci from repo diff --git a/hosts/cc-ci/configuration.nix b/hosts/cc-ci/configuration.nix index caee011..3a98d78 100644 --- a/hosts/cc-ci/configuration.nix +++ b/hosts/cc-ci/configuration.nix @@ -6,6 +6,7 @@ imports = [ ./hardware.nix ../../modules/secrets.nix + ../../modules/swarm.nix ]; # --- Tailscale (ACCESS-CRITICAL: do not break, this is the only route in) --- diff --git a/modules/swarm.nix b/modules/swarm.nix new file mode 100644 index 0000000..6986bd7 --- /dev/null +++ b/modules/swarm.nix @@ -0,0 +1,41 @@ +# Docker + single-node Swarm — the deploy target for recipes under test (M1). +# Traefik (modules/traefik.nix) and abra layer on top; recipes attach to the `proxy` +# overlay network, exactly as a real Co-op Cloud host expects. +{ pkgs, ... }: +{ + virtualisation.docker = { + enable = true; + # Reclaim disk from churning per-run images/volumes (cc-ci root is ~28 GiB). + autoPrune = { + enable = true; + dates = "daily"; + flags = [ "--all" "--volumes" "--filter" "until=24h" ]; + }; + }; + + environment.systemPackages = [ pkgs.docker ]; + + # Bring up a single-node swarm + the shared `proxy` overlay network. Idempotent: + # safe to re-run every boot/rebuild. advertise-addr 127.0.0.1 is fine for a lone node. + systemd.services.swarm-init = { + description = "Initialise single-node Docker Swarm + proxy overlay network"; + after = [ "docker.service" ]; + requires = [ "docker.service" ]; + wantedBy = [ "multi-user.target" ]; + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + set -eu + state="$(docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null || echo error)" + if [ "$state" != "active" ]; then + docker swarm init --advertise-addr 127.0.0.1 + fi + if ! docker network inspect proxy >/dev/null 2>&1; then + docker network create --driver overlay --attachable proxy + fi + ''; + }; +}