Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71e3d0e852 | ||
|
|
ad085efbc4 | ||
|
|
726a4febff | ||
|
|
5c5d194f61 | ||
|
|
ac73f1b63a |
@@ -1238,3 +1238,52 @@ the host: `opencode-go/deepseek-v4-flash` and `opencode-go/glm-5.3-flash` answer
|
|||||||
`upgrader.env` (`LOOP_TIER=go` maps to the `opencode-go` auth entry; `LOOP_MODEL` overrides the
|
`upgrader.env` (`LOOP_TIER=go` maps to the `opencode-go` auth entry; `LOOP_MODEL` overrides the
|
||||||
tier default). Next fire Fri 2026-09-11 02:00 UTC.
|
tier default). Next fire Fri 2026-09-11 02:00 UTC.
|
||||||
- The steering orchestrator agent stays on `opencode-go/glm-5.2` (not asked to change).
|
- The steering orchestrator agent stays on `opencode-go/glm-5.2` (not asked to change).
|
||||||
|
|
||||||
|
## Session 2026-09-21 — domain cutover to ci.autonomic.zone (orchestrator)
|
||||||
|
|
||||||
|
**What happened.** Morning: hourly supervisor resumed the stalled 09-18 weekly run on the GO tier
|
||||||
|
(ZEN endpoint dead server-side — `UnknownError`; run completed 13 green PRs, 0 failed). Published
|
||||||
|
the missing week-2026-09-18 report (PR-finding #4; launcher defaults flipped to `go` in
|
||||||
|
cc-ci-orchestrator PR #23). Then executed the full domain cutover per
|
||||||
|
`cc-ci-plan/plan-domain-migration-ci-autonomic-zone.md` (PR #25).
|
||||||
|
|
||||||
|
**Plan deviation (simplification).** No dual-cert SNI: ONE Let's Encrypt cert carries SANs for
|
||||||
|
BOTH zones (`ci` + `*.ci` of autonomic.zone AND commoninternet.net) — the unchanged single-pair
|
||||||
|
`ssl_cert/ssl_key` traefik reconciler keeps working; Phase 4 reissues without the legacy SANs.
|
||||||
|
The new zone's DNS-01 challenge reuses the SAME acme-dns account: storage re-keyed by
|
||||||
|
`cc-ci-acme-storage-seed.service` (jq clone of the legacy entry under `ci.autonomic.zone`),
|
||||||
|
CNAME already delegated. Proven by a hand lego **staging** run before any production change.
|
||||||
|
|
||||||
|
**Merged:** cc-ci #39 (front doors dual Host rules, bridge/dashboard env URLs, drone abra rename,
|
||||||
|
runner RPC, naming.py → `*.ci.autonomic.zone`, dual-zone name regexes in lifecycle/warm/prune,
|
||||||
|
recipe-report URLs) · cc-ci #40 (seed-unit nesting fix) · cc-ci #41 (have_secret stack-scope —
|
||||||
|
caught live: the old stack's `*_rpc_secret_v1` satisfied the check post-rename) · cc-ci #42 (nix
|
||||||
|
interpolation escape) · orchestrator #27 (oc.ci host + `opencodeUiExtraHosts`, host self-pins,
|
||||||
|
flake bump).
|
||||||
|
|
||||||
|
**Deployed** via `nixos-rebuild test` → verify → `switch` (generation `nn1vwiv7v1k…`, running ==
|
||||||
|
boot). Cert SANs confirmed 4-name; all 5 front doors answer on BOTH zones
|
||||||
|
(200/200/303/401 + traefik 200), TLS verify=0 from outside; zero failed units; disk dropped
|
||||||
|
88%→45% after prune.
|
||||||
|
|
||||||
|
**Drone migration.** New abra app `drone.ci.autonomic.zone`, FRESH DB (module's
|
||||||
|
`DRONE_USER_CREATE` re-injected the sops bridge token). The Gitea OAuth app redirect now has both
|
||||||
|
URIs; the client secret was rotated (each Gitea PATCH regenerates it) and synced through
|
||||||
|
sops → `sops-install-secrets` → swarm secret v1 → drone. Bootstrapped OAuth
|
||||||
|
(`drone login ok (admin=true)`), re-enabled cc-ci + discourse repos, build timeout 60m.
|
||||||
|
Webhooks: ghost + discourse repointed (secrets preserved); cc-ci repo's bridge webhook →
|
||||||
|
`ci.autonomic.zone/hook`, stale drone hook deleted, Drone's auto-created new-zone hook active.
|
||||||
|
Old stack removed + orphaned secrets reaped.
|
||||||
|
|
||||||
|
**E2E proof.** `!testme` on keycloak PR #9 → bridge → drone build #1 (new DB numbering) → runner →
|
||||||
|
harness → `results.json` + PR card `✅ passed` linking `ci.autonomic.zone/runs/1/summary.png`.
|
||||||
|
|
||||||
|
**Deferred / open.**
|
||||||
|
- Warm stacks + backupbot stay on the legacy zone (data-warm volumes / restic password tied to
|
||||||
|
abra app names) — post-bake migration; harness regexes accept both zones meanwhile.
|
||||||
|
- Docs sweep (~60 references: AGENTS.md, README, skills incl. cc-ci-status front-door list,
|
||||||
|
launcher printed URLs).
|
||||||
|
- Phase 4 (after ≥7 clean days): drop legacy SANs (reissue), remove legacy Host arms + host
|
||||||
|
self-pins + Gandi records (`ci`, `*.ci`, `_acme-challenge.ci`), TTLs back to 3600.
|
||||||
|
- Host auto-update was `failed` 2026-09-15 (health check) — `/cc-ci-orchestrator-update` still
|
||||||
|
pending; next auto-attempt Tue 09-22.
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ def render(spec_path, out_path):
|
|||||||
for p in lead.split("\n\n") if p.strip())
|
for p in lead.split("\n\n") if p.strip())
|
||||||
body = (_mast() +
|
body = (_mast() +
|
||||||
f'<div class="dateline"><span>{_esc(sub)}</span>'
|
f'<div class="dateline"><span>{_esc(sub)}</span>'
|
||||||
f'<span>report.ci.commoninternet.net</span><span>{gen}</span></div>'
|
f'<span>report.ci.autonomic.zone</span><span>{gen}</span></div>'
|
||||||
f'<div class="lead">{lead}</div>')
|
f'<div class="lead">{lead}</div>')
|
||||||
# 1) the full wire — every recipe, in the agent's recommended priority order (CVEs first); CVEs column.
|
# 1) the full wire — every recipe, in the agent's recommended priority order (CVEs first); CVEs column.
|
||||||
wire = ("The full wire — every recipe, in priority order" if kind == "week"
|
wire = ("The full wire — every recipe, in priority order" if kind == "week"
|
||||||
@@ -322,7 +322,7 @@ def render(spec_path, out_path):
|
|||||||
if s.get("changes"):
|
if s.get("changes"):
|
||||||
body += f'<h2>What changed</h2>{_changes(s.get("changes"), repo_url)}'
|
body += f'<h2>What changed</h2>{_changes(s.get("changes"), repo_url)}'
|
||||||
body += (f'<footer>{title} · generated {gen} · '
|
body += (f'<footer>{title} · generated {gen} · '
|
||||||
f'<a href="https://ci.commoninternet.net/">dashboard</a> · <a href="./">archive</a></footer>')
|
f'<a href="https://ci.autonomic.zone/">dashboard</a> · <a href="./">archive</a></footer>')
|
||||||
open(out_path, "w").write(_page(f"{title} · " + s["date"], body))
|
open(out_path, "w").write(_page(f"{title} · " + s["date"], body))
|
||||||
print("wrote", out_path)
|
print("wrote", out_path)
|
||||||
|
|
||||||
@@ -347,10 +347,10 @@ def publish(html_path, date, kind="week"):
|
|||||||
for d, k in sorted(set(entries), reverse=True))
|
for d, k in sorted(set(entries), reverse=True))
|
||||||
idx = _page("The Recipe Report — Archive", _mast() +
|
idx = _page("The Recipe Report — Archive", _mast() +
|
||||||
'<div class="dateline"><span>Weekly review of Co-op Cloud recipe upgrades & CI</span>'
|
'<div class="dateline"><span>Weekly review of Co-op Cloud recipe upgrades & CI</span>'
|
||||||
'<span>report.ci.commoninternet.net</span></div>'
|
'<span>report.ci.autonomic.zone</span></div>'
|
||||||
f'<ul class="idx">{lis or "<li><em>No reports yet.</em></li>"}</ul>')
|
f'<ul class="idx">{lis or "<li><em>No reports yet.</em></li>"}</ul>')
|
||||||
subprocess.run(["ssh", "cc-ci", f"cat > {HOST_REPORTS}/index.html"], input=idx.encode(), check=True)
|
subprocess.run(["ssh", "cc-ci", f"cat > {HOST_REPORTS}/index.html"], input=idx.encode(), check=True)
|
||||||
print(f"published https://report.ci.commoninternet.net/{page} (+ index)")
|
print(f"published https://report.ci.autonomic.zone/{page} (+ index)")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
Generated
+4
-4
@@ -10,11 +10,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1789404337,
|
"lastModified": 1790010051,
|
||||||
"narHash": "sha256-FY5oOz/C6i6Ct6Qe6DqN6nOq+TXCyiZq5Am1LKLpDss=",
|
"narHash": "sha256-0dz8fg4zqg54tk+1A7CHZAw+lK9vWxre6Tioi5B0ocU=",
|
||||||
"ref": "refs/heads/main",
|
"ref": "refs/heads/main",
|
||||||
"rev": "eb5fb826114f2b141dffb270fd36f7a22d1bf343",
|
"rev": "2f6787f0433e7ff3053116039f10c00cde34128f",
|
||||||
"revCount": 1550,
|
"revCount": 1558,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.autonomic.zone/recipe-maintainers/cc-ci.git"
|
"url": "https://git.autonomic.zone/recipe-maintainers/cc-ci.git"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,8 +30,10 @@
|
|||||||
# Weekly self-update (Tue 03:00 UTC; skips itself while CI is busy; see nix/modules/auto-update.nix).
|
# Weekly self-update (Tue 03:00 UTC; skips itself while CI is busy; see nix/modules/auto-update.nix).
|
||||||
cc-ci-orchestrator.autoUpdate.enable = true;
|
cc-ci-orchestrator.autoUpdate.enable = true;
|
||||||
|
|
||||||
# The opencode UI: traefik (public 443, the *.ci.commoninternet.net cert) → nginx basic auth.
|
# The opencode UI: traefik (public 443, the dual-zone wildcard cert) → nginx basic auth.
|
||||||
cc-ci-orchestrator.opencodeUiHost = "oc.ci.commoninternet.net";
|
# Domain cutover 2026-09: new name primary; legacy name kept answering during the bake window.
|
||||||
|
cc-ci-orchestrator.opencodeUiHost = "oc.ci.autonomic.zone";
|
||||||
|
cc-ci-orchestrator.opencodeUiExtraHosts = [ "oc.ci.commoninternet.net" ];
|
||||||
cc-ci-orchestrator.opencodeUiTraefikNetwork = "proxy";
|
cc-ci-orchestrator.opencodeUiTraefikNetwork = "proxy";
|
||||||
|
|
||||||
# ---- no tailscale on this host (operator 2026-09-07) --------------------------------------
|
# ---- no tailscale on this host (operator 2026-09-07) --------------------------------------
|
||||||
@@ -124,7 +126,13 @@
|
|||||||
# This host's own public names resolve to itself regardless of external DNS state (host
|
# This host's own public names resolve to itself regardless of external DNS state (host
|
||||||
# processes: the drone runner, the harness, the orchestrator; containers use the resolvers
|
# processes: the drone runner, the harness, the orchestrator; containers use the resolvers
|
||||||
# above). Per-run recipe domains are random and cannot be pinned — those follow public DNS.
|
# above). Per-run recipe domains are random and cannot be pinned — those follow public DNS.
|
||||||
|
# Domain cutover 2026-09: new names pinned; legacy names kept during the bake window.
|
||||||
networking.hosts."195.201.88.249" = [
|
networking.hosts."195.201.88.249" = [
|
||||||
|
"ci.autonomic.zone"
|
||||||
|
"drone.ci.autonomic.zone"
|
||||||
|
"report.ci.autonomic.zone"
|
||||||
|
"traefik.ci.autonomic.zone"
|
||||||
|
"oc.ci.autonomic.zone"
|
||||||
"ci.commoninternet.net"
|
"ci.commoninternet.net"
|
||||||
"drone.ci.commoninternet.net"
|
"drone.ci.commoninternet.net"
|
||||||
"report.ci.commoninternet.net"
|
"report.ci.commoninternet.net"
|
||||||
|
|||||||
@@ -62,6 +62,16 @@ in
|
|||||||
description = "nginx server_name for the opencode web UI (TLS + basic auth).";
|
description = "nginx server_name for the opencode web UI (TLS + basic auth).";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
opencodeUiExtraHosts = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = ''
|
||||||
|
Extra hostnames routed to the opencode UI alongside opencodeUiHost, rendered as
|
||||||
|
`||`-joined Host conditions on the same router. Domain cutover 2026-09: the
|
||||||
|
legacy oc.ci.commoninternet.net keeps answering here during the bake window.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
opencodeUiHtpasswdFile = lib.mkOption {
|
opencodeUiHtpasswdFile = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "/secrets/nginx/oc-htpasswd";
|
default = "/secrets/nginx/oc-htpasswd";
|
||||||
@@ -216,6 +226,7 @@ SSHCFG
|
|||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
virtualHosts.${cfg.opencodeUiHost} = {
|
virtualHosts.${cfg.opencodeUiHost} = {
|
||||||
listen = [ { addr = "0.0.0.0"; port = cfg.opencodeUiBackendPort; } ];
|
listen = [ { addr = "0.0.0.0"; port = cfg.opencodeUiBackendPort; } ];
|
||||||
|
serverAliases = cfg.opencodeUiExtraHosts;
|
||||||
basicAuthFile = cfg.opencodeUiHtpasswdFile;
|
basicAuthFile = cfg.opencodeUiHtpasswdFile;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
# traefik sits on the docker networks (ingress 10.0.0.0/24, gwbridge 172.18.0.0/16)
|
# traefik sits on the docker networks (ingress 10.0.0.0/24, gwbridge 172.18.0.0/16)
|
||||||
@@ -256,7 +267,7 @@ SSHCFG
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.opencode-ui.rule=Host(`${cfg.opencodeUiHost}`)"
|
- "traefik.http.routers.opencode-ui.rule=${lib.concatStringsSep " || " (map (h: "Host(`${h}`)") ([ cfg.opencodeUiHost ] ++ cfg.opencodeUiExtraHosts))}"
|
||||||
- "traefik.http.routers.opencode-ui.entrypoints=web-secure"
|
- "traefik.http.routers.opencode-ui.entrypoints=web-secure"
|
||||||
- "traefik.http.routers.opencode-ui.tls=true"
|
- "traefik.http.routers.opencode-ui.tls=true"
|
||||||
- "traefik.http.services.opencode-ui.loadbalancer.server.port=${toString cfg.opencodeUiBackendPort}"
|
- "traefik.http.services.opencode-ui.loadbalancer.server.port=${toString cfg.opencodeUiBackendPort}"
|
||||||
|
|||||||
Reference in New Issue
Block a user