From 4d09b1e41e956e760354ca9afa88aae3e069b7ba Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Tue, 26 May 2026 22:41:13 +0100 Subject: [PATCH] M2 start: Drone CI decision; Gitea OAuth app + Drone secrets (sops) Co-Authored-By: Claude Opus 4.7 (1M context) --- DECISIONS.md | 20 +++++++++++++++++++- JOURNAL.md | 23 +++++++++++++++++++++++ secrets/secrets.yaml | 6 ++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/DECISIONS.md b/DECISIONS.md index 71c97a7..cb9d533 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -46,7 +46,25 @@ Architecture decisions and dead-ends. One line of rationale each. (§0, §8) - **nixpkgs pin:** flake pins the exact rev cc-ci already ran (`50ab793…`) so the first rebuild is a true no-op-then-base. Bump deliberately, never drift. - **Webhook scope:** default per-repo via enroll script. -- **Drone runner type:** default exec (must drive host abra). +- **CI engine: Drone (per plan) — kept, with a noted risk.** nixpkgs 24.11 has Drone **server** + 2.24.0 but `drone-runner-exec` is **abandoned (unstable-2020-04-19)** — the only exec runner Drone + ever shipped (upstream archived ~2021). The maintained fork **Woodpecker** (2.7.3, with NixOS + modules) is the alternative. Decision: honor the plan (Drone) because the plan is Drone-specific + (D7 "Drone's native UI", comment-bridge → Drone API). The 2020 exec runner pairs fine with modern + Drone server (RPC protocol stable). **Fallback:** if the exec runner proves incompatible/broken, + pivot to Woodpecker (coop-cloud ships a `woodpecker` recipe too) and record it — like the traefik + pivot. Re-evaluate at the M2 gate. +- **Drone deployment shape — SETTLED (M2):** mirror the traefik pattern. The **server** is the + coop-cloud `drone` recipe (drone/drone:2.26.0) deployed via abra (swarm-native, auto-routed by + traefik at `drone.ci.commoninternet.net`, `LETS_ENCRYPT_ENV` empty → wildcard cert, no ACME), + with Gitea SSO (`compose.gitea.yml`). The **exec runner** runs as a Nix systemd service on the + host (`modules/drone-runner.nix`) so it can drive host abra/swarm (plan §4.2). One generated + `DRONE_RPC_SECRET` is shared: inserted as the server's `rpc_secret` swarm secret AND read by the + runner from sops. Reproducible deploy: `scripts/deploy-drone.sh`. + - Gitea OAuth app `cc-ci-drone` created under the bot (client_id `ab4cdb9d-ee96-4867-875f- + 87384505fc52`, redirect `https://drone.ci.commoninternet.net/login`); client_secret + + rpc_secret stored sops-encrypted in `secrets/secrets.yaml` (A2 internal secrets). +- **Drone runner type:** exec (must drive host abra). - **Secret tool — SETTLED (M0):** sops-nix. cc-ci decrypts at activation using its **ed25519 SSH host key** as the age identity (`sops.age.sshKeyPaths`), so no extra key file to manage on the box. Recipients in `/.sops.yaml`: the host age key (`age1h90ut…`, from ssh-to-age) + an off-box diff --git a/JOURNAL.md b/JOURNAL.md index f476fed..2d89c19 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -186,3 +186,26 @@ Verify: `docker service ls` → app+socket-proxy 1/1; via gateway `curl --resolv **docs/install.md** seeded (flake apply + deploy-proxy + verify). M1 gate CLAIMED in STATUS.md. **Next:** M2 — Drone server + exec runner via Nix, Gitea OAuth app, hello-world .drone.yml green. + +## 2026-05-26 — M2 start: CI engine decision + Gitea OAuth app + Drone secrets + +**Decision (DECISIONS.md):** keep Drone per plan. nixpkgs 24.11 has drone server 2.24.0 but only the +abandoned `drone-runner-exec` (unstable-2020) — accepted (stable RPC), Woodpecker is the documented +fallback. Deploy shape mirrors traefik: server via coop-cloud `drone` recipe (abra, swarm, +traefik-routed at drone.ci.commoninternet.net, no ACME), exec runner as a host Nix systemd service. + +**Recipe recon:** coop-cloud `drone` recipe = drone/drone:2.26.0, secrets `rpc_secret` + +`CLIENT_SECRET` (Gitea OAuth), Gitea SSO via `compose.gitea.yml` (`GITEA_CLIENT_ID`, `GITEA_DOMAIN`). +Server env: DRONE_SERVER_HOST/PROTO, DRONE_USER_CREATE. + +**Done this tick:** +- Created Gitea OAuth app `cc-ci-drone` (bot): client_id `ab4cdb9d-…`, redirect + `https://drone.ci.commoninternet.net/login`. +- Generated `DRONE_RPC_SECRET` (openssl-equivalent /dev/urandom hex32) + stored client_secret; + both added to `secrets/secrets.yaml` via `sops set` (needed `SOPS_AGE_KEY` from the host ssh key: + `ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key`). Verified: decrypt shows keys + test_secret/drone_rpc_secret/drone_gitea_client_secret; file stays encrypted (4× ENC). + +**Next:** scripts/deploy-drone.sh (abra deploy of drone server w/ Gitea SSO + rpc/client secrets), +modules/drone-runner.nix (exec runner systemd unit, rpc secret from sops), wire sops secrets for the +runner, then push a hello-world .drone.yml and confirm a green build (M2 gate). diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 2a36a86..8a4c022 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -1,4 +1,6 @@ test_secret: ENC[AES256_GCM,data:VOxNiRyeSQQPKeF2PUK9AtezhzX+Hdm9ji5ZYm+gNd2NJ+wwXc67En8=,iv:Bn1oQeBN98E2/To1KRAw3wsLUF0/HsQFBm8s28L5aqo=,tag:KPS5Y+25Elf3alSF2H6npw==,type:str] +drone_rpc_secret: ENC[AES256_GCM,data:pE+6nTpFaclRAQDBQZfki5WiMTOC6NkhBMcAkEfma9QjfOyBx9BbfyCyAB3a0ICo8NZj6kMHyw78GbrowU6RAg==,iv:3YgoLsXEQh6bOVMyVpSGopZFTP/Kxi20QdajNX9heVI=,tag:SNhRwTVzkygxZ10bN1yHlQ==,type:str] +drone_gitea_client_secret: ENC[AES256_GCM,data:kBYptCmAdFmAuZNa1moK3o5faYrKFDr5KEjDHzfZOKyrz47awRX9LwNejyWlej1ybE8rvv075Yc=,iv:fESd6OYoHKjoZS4YBajon0dibt0BuHD2f/WqjbljmiY=,tag:f7skoA5fizTXjYGI3u6Uig==,type:str] sops: kms: [] gcp_kms: [] @@ -23,8 +25,8 @@ sops: a2RKRWVaTGhNb0d3TFlnL2NtejZOaEUK2dQaAzlYk4Z7aBej77cO4Ug9Afkka6wg G1SumwxX0wMocpgz4WhDUPkBC66uWlaR3u1AWzwpzRseuwAZ94gAxA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-05-26T20:32:25Z" - mac: ENC[AES256_GCM,data:cfMw8ILys0FXVXiRUbsZ1Jjz+S7X+0Q+DI4oyWNEP8Ka/iZeLkF1NjYbcdOVpqTuiF2gGde2uUjFRy3GtXOUYn8u8Sf2Ve1D1QpJ+8IiDCcaPUjxOxAKd3yGgDi4mm5EWxg+DerlugEj5hwlxWWBdj0I7XDnL2RPANN+yA9Ypko=,iv:hewvYjUmDfEg0PfUMaY0+SZuLy8sAR++d2Dlzm5Yr4w=,tag:nHqjRCHHM98Hzdv1HYHr3A==,type:str] + lastmodified: "2026-05-26T21:39:48Z" + mac: ENC[AES256_GCM,data:+O8ZV1d1csy8XVM+c2+feD/qH35t+qgnqZtQaP1jMCLIVQ6j/o+BT3Oo8bgMePrSml6hVJQ865LPF/sIT/Y3Ap5veGngR9DVzbMkhnqY1vEqjwa3cn+apX9cCarDHL9sY6iwGy4P9s3f8QgMUn0VRqkEJxnQ+dUfaTrlPNiizxc=,iv:ez7zjR+2jzTOdOOAJoA/u99Yh5b1q6RED45VMfZIqlE=,tag:7fF3qQYTTC3iMsxWFYII/w==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.4