host: KillMode=process on the agent units so a rebuild stops nuking tmux

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 21:21:08 +00:00
co-authored by Claude
parent 6edea124fb
commit d29fa655c2
@@ -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:<bcrypt hash>`
# /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";