opencode UI stack is ccci-opencode-ui, on the weekly sweep's keep-list; journal: first weekly run on the new host
The 2026-09-07 weekly run's step-0 orphan sweep removed the `opencode-ui` swarm stack (the traefik route to the opencode web UI) because it was not on sweep-orphans.sh's keep-list. Renamed to ccci-opencode-ui alongside the other control-plane stacks and added to KEEP_RE. Journal: the run itself (lasuite-docs #8, n8n #7 GREEN on the new Drone, report week-2026-09-07 published) ran entirely on the new host. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FqkQq3CDmFWcQ7u1LzoyRz
This commit is contained in:
@@ -9,14 +9,16 @@
|
|||||||
# SAFE BY ALLOWLIST. It removes ONLY things NOT on the keep-list, so it can never take down infra or
|
# SAFE BY ALLOWLIST. It removes ONLY things NOT on the keep-list, so it can never take down infra or
|
||||||
# the warm canonicals. The keep-list (leading name prefix) is:
|
# the warm canonicals. The keep-list (leading name prefix) is:
|
||||||
# - traefik, drone, backups : Swarm + CI infra
|
# - traefik, drone, backups : Swarm + CI infra
|
||||||
# - ccci-bridge / -dashboard / -reports: the cc-ci control plane
|
# - ccci-bridge / -dashboard / -reports / -opencode-ui: the cc-ci control plane (opencode-ui is
|
||||||
|
# the traefik route to the orchestrator's opencode web UI, deployed by the host's nix config —
|
||||||
|
# the 2026-09-07 run reaped it as an "orphan" before it was on this list)
|
||||||
# - warm-* : warm canonicals (idle persistent deps reused across runs;
|
# - warm-* : warm canonicals (idle persistent deps reused across runs;
|
||||||
# their retained volumes are spared too)
|
# their retained volumes are spared too)
|
||||||
# Everything else deployed on the Swarm is a per-run test stack and is fair game.
|
# Everything else deployed on the Swarm is a per-run test stack and is fair game.
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
export PATH=/run/current-system/sw/bin:$PATH
|
export PATH=/run/current-system/sw/bin:$PATH
|
||||||
|
|
||||||
KEEP_RE='^(traefik|drone|backups|ccci-(bridge|dashboard|reports)|warm-)'
|
KEEP_RE='^(traefik|drone|backups|ccci-(bridge|dashboard|reports|opencode-ui)|warm-)'
|
||||||
removed=0
|
removed=0
|
||||||
|
|
||||||
echo "== orphan sweep: scanning (keep-list: infra + warm-* canonicals) =="
|
echo "== orphan sweep: scanning (keep-list: infra + warm-* canonicals) =="
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ Everything in this section is **outside git**. Do it as root over SSH, in this o
|
|||||||
The combined host is NOT on the tailnet (operator decision 2026-09-07): ssh is key-only on the
|
The combined host is NOT on the tailnet (operator decision 2026-09-07): ssh is key-only on the
|
||||||
public IP, the CI front doors are public via traefik, and the opencode UI is public on the same
|
public IP, the CI front doors are public via traefik, and the opencode UI is public on the same
|
||||||
443 — traefik routes `oc.ci.commoninternet.net` to an nginx vhost on the docker bridge that
|
443 — traefik routes `oc.ci.commoninternet.net` to an nginx vhost on the docker bridge that
|
||||||
enforces basic auth, via traefik labels on a tiny swarm relay stack (`opencode-ui`) that
|
enforces basic auth, via traefik labels on a tiny swarm relay stack (`ccci-opencode-ui`, on the weekly sweep's keep-list) that
|
||||||
`opencode-ui-route.service` deploys. (Not via traefik's file *directory* provider: enabling
|
`opencode-ui-route.service` deploys. (Not via traefik's file *directory* provider: enabling
|
||||||
that in the coop-cloud traefik recipe REPLACES its provider file, which holds the wildcard cert
|
that in the coop-cloud traefik recipe REPLACES its provider file, which holds the wildcard cert
|
||||||
and the `security` middleware, and every front door goes down — it did, for two minutes, on
|
and the `security` middleware, and every front door goes down — it did, for two minutes, on
|
||||||
|
|||||||
+10
-29
@@ -1062,33 +1062,14 @@ Plan + live log: `cc-ci-plan/plan-cc-ci-combined-host.md` (on the branch; copy h
|
|||||||
- Open: tailscale auth key revoked (`invalid key: API key does not exist`) → operator issues a
|
- Open: tailscale auth key revoked (`invalid key: API key does not exist`) → operator issues a
|
||||||
new one. DNS cutover at Gandi (ci, *.ci, ns-acme → 195.201.88.249) → operator.
|
new one. DNS cutover at Gandi (ci, *.ci, ns-acme → 195.201.88.249) → operator.
|
||||||
|
|
||||||
## Session 2026-09-07 21:10 UTC — CUTOVER DONE; orchestrator now on the new host
|
## 2026-09-07 22:15 UTC — first weekly upgrade run on the new host: GREEN, report published
|
||||||
|
|
||||||
CI is served from 195.201.88.249 (DNS repointed by the operator, no tailscale on the new box,
|
Started by hand 21:23 UTC (`systemctl start cc-ci-upgrade-all` on 195.201.88.249, opencode /
|
||||||
opencode UI on 443 via traefik + basic auth, fail2ban on). `!testme` → Drone build 1326 on the
|
deepseek-v4-flash); `UPGRADE RUN COMPLETE` 22:02 (39 min). Everything ran on the new host — old
|
||||||
new box. This session (on the old shared host) is the last one here: cc-ci units runtime-masked
|
server's Drone/bridge at 0/0, no new run dirs or report there. 20 recipes surveyed, 2 upgrade PRs
|
||||||
on the old host; a fresh orchestrator session is up on the new box (`ssh root@195.201.88.249`,
|
extended and `!testme` GREEN on the new Drone (lasuite-docs #8 → v5.6.1, build 1338; n8n #7 →
|
||||||
`sudo -iu loops tmux attach -t cc-ci-orchestrator`). Details + the two incidents:
|
2.38.4, build 1339), 1 PR closed as merged upstream (custom-html #7), 18 skipped as up-to-date or
|
||||||
`cc-ci-plan/plan-cc-ci-combined-host.md` (log) and README §2a/§7. Operator to merge
|
covered. Summary: `.cc-ci-logs/upgrades/upgrade-all-2026-09-07.md`. Report agent published
|
||||||
notplants-nix `chore/drop-cc-ci`, delete the old CI server in a week, revoke the Hetzner token.
|
https://report.ci.commoninternet.net/week-2026-09-07.html (200, 42 KB, indexed) at 22:11.
|
||||||
|
One side effect: the run's orphan sweep removed the `opencode-ui` swarm stack (traefik route to
|
||||||
## Session 2026-09-07 21:35 UTC — evening changes on the cc-ci host (from Claude on notplants-orchestrator)
|
the opencode web UI) — redeployed, renamed `ccci-opencode-ui`, added to the sweep keep-list.
|
||||||
|
|
||||||
- notplants-nix `chore/drop-cc-ci` merged + applied on the old box (gen 57). cc-ci push self-test
|
|
||||||
green again (#33 ruff format, #34 statix). cc-ci input relocked on the host (NAR-hash note in
|
|
||||||
README day-2).
|
|
||||||
- Operator: NO Claude on the cc-ci host. The orchestrator there is an opencode agent
|
|
||||||
(agents.toml: opencode/glm-5.2) steered from https://oc.ci.commoninternet.net; claude-install,
|
|
||||||
CLAUDE_BIN and all Claude state removed from the host. Claude sessions stay on
|
|
||||||
notplants-orchestrator, whose loops `ssh cc-ci` now points at 195.201.88.249.
|
|
||||||
- Operator: only strictly necessary secrets on the cc-ci host, none of this machine's keys.
|
|
||||||
`/secrets/files` there now holds exactly: cc-ci.testenv (GITEA_PASSWORD, DOCKERHUB_*),
|
|
||||||
cc-ci-local-ed25519 (loops→root loopback, generated there, pub in nix/hosts/cc-ci/ssh-keys),
|
|
||||||
autonomic-bot-cc-ci-ed25519 (generated there, Gitea key id 156, root uses it for cc-ci-secrets),
|
|
||||||
opencode-auth.json. Gone: tailscale key, tangled key, copied cc-ci-root + bot keys, htpasswd
|
|
||||||
plaintext, TINFOIL/OPENAI keys, the master age key (cc-ci-secrets re-keyed to the host's ssh
|
|
||||||
host key age1tmvg…, cc-ci PR #35; /var/lib/sops-nix/key.txt = host-derived identity). /old-root
|
|
||||||
deleted. Inventory: /secrets/README.txt on the host.
|
|
||||||
- Weekly upgrade run started by hand on the new host at 21:23 UTC (`systemctl start
|
|
||||||
cc-ci-upgrade-all`; opencode/deepseek-v4-flash, session ses_f823e7a18ffejcu0) as the post-move
|
|
||||||
proof; result + report recorded below when done.
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ in
|
|||||||
example = "proxy";
|
example = "proxy";
|
||||||
description = ''
|
description = ''
|
||||||
Name of the swarm overlay network the cc-ci traefik watches (cc-ci's swarm.nix creates
|
Name of the swarm overlay network the cc-ci traefik watches (cc-ci's swarm.nix creates
|
||||||
`proxy`). When set, a one-container swarm stack `opencode-ui` (a socat TCP relay to
|
`proxy`). When set, a one-container swarm stack `ccci-opencode-ui` (a socat TCP relay to
|
||||||
nginx on the docker bridge) is deployed with traefik labels routing opencodeUiHost on
|
nginx on the docker bridge) is deployed with traefik labels routing opencodeUiHost on
|
||||||
the `web-secure` entrypoint — the same label mechanism every cc-ci service and recipe
|
the `web-secure` entrypoint — the same label mechanism every cc-ci service and recipe
|
||||||
uses, so it coexists with the traefik recipe's own file provider (the wildcard cert and
|
uses, so it coexists with the traefik recipe's own file provider (the wildcard cert and
|
||||||
@@ -208,11 +208,12 @@ SSHCFG
|
|||||||
# Only docker's bridge may reach the plain-HTTP backend; the public interface stays closed.
|
# Only docker's bridge may reach the plain-HTTP backend; the public interface stays closed.
|
||||||
networking.firewall.interfaces.docker_gwbridge.allowedTCPPorts = [ cfg.opencodeUiBackendPort ];
|
networking.firewall.interfaces.docker_gwbridge.allowedTCPPorts = [ cfg.opencodeUiBackendPort ];
|
||||||
|
|
||||||
# The traefik side of the route: a swarm service carrying the router labels. It is a plain
|
# The traefik side of the route: a swarm service carrying the router labels. Named ccci-* so
|
||||||
|
# the weekly run's orphan sweep (skills/upgrade-all/sweep-orphans.sh keep-list) leaves it be. A plain
|
||||||
# TCP relay (socat) from the overlay network to nginx on the docker bridge; traefik's
|
# TCP relay (socat) from the overlay network to nginx on the docker bridge; traefik's
|
||||||
# X-Forwarded-For passes through untouched, which is what nginx's real_ip reads.
|
# X-Forwarded-For passes through untouched, which is what nginx's real_ip reads.
|
||||||
systemd.services.opencode-ui-route = lib.mkIf (cfg.opencodeUiTraefikNetwork != null) {
|
systemd.services.opencode-ui-route = lib.mkIf (cfg.opencodeUiTraefikNetwork != null) {
|
||||||
description = "swarm stack opencode-ui: traefik labels ${cfg.opencodeUiHost} -> nginx basic auth";
|
description = "swarm stack ccci-opencode-ui: traefik labels ${cfg.opencodeUiHost} -> nginx basic auth";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "deploy-proxy.service" "docker.service" "nginx.service" ];
|
after = [ "deploy-proxy.service" "docker.service" "nginx.service" ];
|
||||||
wants = [ "deploy-proxy.service" ];
|
wants = [ "deploy-proxy.service" ];
|
||||||
@@ -238,7 +239,7 @@ SSHCFG
|
|||||||
networks:
|
networks:
|
||||||
${cfg.opencodeUiTraefikNetwork}:
|
${cfg.opencodeUiTraefikNetwork}:
|
||||||
external: true
|
external: true
|
||||||
''} opencode-ui
|
''} ccci-opencode-ui
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user