Two operational gaps in serve.
Timeouts (#104). The HTTP server had none. It now has a 10 s ReadHeaderTimeout, a 2 min IdleTimeout and a 64 KiB header cap; the ACME HTTP-01 listener gets the same. No write timeout, since archives and upload-pack stream for as long as they take.
Shutdown (#105). serve blocked on the first listener error and a deploy's restart was a plain kill. It now traps SIGINT and SIGTERM, closes the ssh and git listeners, drains the HTTP server and every accepted SSH session (the ssh server gained a Shutdown that waits on a session WaitGroup, so a push in flight completes), for up to 30 s, then exits 0. systemd's default TimeoutStopSec of 90 s covers that.
TestServeStopsOnSIGTERM: the daemon exits cleanly within 15 s and the listener is gone.
Stacked on !192; no code dependency.
retargeted from codeowners-always to main: !192 merged
2026-09-03 17:10 UTC