M1: Docker + single-node swarm via Nix (swarm-init + proxy overlay)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 21:47:42 +01:00
parent b0ce69029b
commit ab839ae61d
5 changed files with 70 additions and 3 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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) ---

41
modules/swarm.nix Normal file
View File

@ -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
'';
};
}