From d29fa655c23ec449ea366e65332bbb108a2c6f99 Mon Sep 17 00:00:00 2001 From: notplants-bot Date: Sat, 1 Aug 2026 21:21:08 +0000 Subject: [PATCH] host: KillMode=process on the agent units so a rebuild stops nuking tmux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One tmux server hosts every agent session on this box and it lives in cc-ci-loops.service's cgroup, so any rebuild touching that unit killed ALL sessions (cc-ci, lichen, PO, pi). With KillMode=process systemd kills only the already-exited launcher, not the cgroup — added to cc-ci-loops, lichen-orchestrator and project-orchestrator. Trade-off: `systemctl stop` no longer tears agents down; do it by hand. Carries an in-flight nginx basicAuth block from the cc-ci agent that was already uncommitted in this file and is now deployed with the 26.05 switch — committed here so it is not lost, not authored by me. Co-Authored-By: Claude --- .../configuration.nix | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix index 3aa5b06..a9568de 100644 --- a/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix +++ b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix @@ -159,6 +159,30 @@ SSHCFG virtualHosts."oc.commoninternet.net" = { # Listen on the tailscale interface only — not the public IP. listen = [{ addr = "100.84.190.30"; port = 80; ssl = false; }]; + + # HTTP basic auth in front of opencode. The opencode web UI has no + # authentication of its own and can drive agent sessions, so since this host + # started serving 80/443 publicly (atproto-likes, 2026-08-01) it is worth a + # second layer even though this vhost is tailnet-only. + # + # basicAuthFile, NOT basicAuth: the `basicAuth` attrset writes the password + # into the nix store, which is world-readable. This file is created out of + # band — same convention as /etc/ts-auth-key — and is not in git: + # + # /etc/nginx/oc-htpasswd root:nginx 0640, `oc:` + # /secrets/files/oc-basic-auth.txt the plaintext, loops-only 0600 + # + # Rotate with: + # P=$(python3 -c "import secrets,string;a=string.ascii_letters+string.digits;print(''.join(secrets.choice(a) for _ in range(32)))") + # printf 'oc:%s\n' "$(mkpasswd -m bcrypt "$P")" | sudo tee /etc/nginx/oc-htpasswd + # sudo chown root:nginx /etc/nginx/oc-htpasswd && sudo chmod 640 /etc/nginx/oc-htpasswd + # sudo systemctl reload nginx + # + # NOTE: if this file goes missing, nginx fails to START — which would take + # the atproto vhost down with it. Recreate it before rebuilding on a fresh + # host. + basicAuthFile = "/etc/nginx/oc-htpasswd"; + locations."/" = { proxyPass = "http://127.0.0.1:4096"; proxyWebsockets = true; @@ -173,6 +197,12 @@ SSHCFG after = [ "network-online.target" "tailscaled.service" "claude-install.service" ]; wants = [ "network-online.target" ]; serviceConfig = { + # KillMode=process: this unit only LAUNCHES the tmux server, it does not own it. With the + # default (control-group) systemd kills every leftover process in the cgroup when the unit + # stops — and since one tmux server hosts every agent session on this host, a rebuild that + # merely touched this unit wiped all of them (operator 2026-08-01). Only the (already + # exited) main process is killed now; `systemctl stop` therefore does NOT tear down agents. + KillMode = "process"; Type = "oneshot"; RemainAfterExit = true; User = "loops"; Group = "users"; WorkingDirectory = "/srv/cc-ci/cc-ci"; @@ -204,6 +234,12 @@ SSHCFG after = [ "network-online.target" "tailscaled.service" "claude-install.service" ]; wants = [ "network-online.target" ]; serviceConfig = { + # KillMode=process: this unit only LAUNCHES the tmux server, it does not own it. With the + # default (control-group) systemd kills every leftover process in the cgroup when the unit + # stops — and since one tmux server hosts every agent session on this host, a rebuild that + # merely touched this unit wiped all of them (operator 2026-08-01). Only the (already + # exited) main process is killed now; `systemctl stop` therefore does NOT tear down agents. + KillMode = "process"; Type = "oneshot"; RemainAfterExit = true; User = "loops"; Group = "users"; WorkingDirectory = "/srv/lichen-orchestrator"; @@ -230,6 +266,12 @@ SSHCFG after = [ "network-online.target" "tailscaled.service" "claude-install.service" ]; wants = [ "network-online.target" ]; serviceConfig = { + # KillMode=process: this unit only LAUNCHES the tmux server, it does not own it. With the + # default (control-group) systemd kills every leftover process in the cgroup when the unit + # stops — and since one tmux server hosts every agent session on this host, a rebuild that + # merely touched this unit wiped all of them (operator 2026-08-01). Only the (already + # exited) main process is killed now; `systemctl stop` therefore does NOT tear down agents. + KillMode = "process"; Type = "oneshot"; RemainAfterExit = true; User = "loops"; Group = "users"; WorkingDirectory = "/srv/project-orchestrator";