The ssh process leak, fixed from inside. No init, no entrypoint change — the thing that broke the self-update twice stays exactly as it is.
Fixed
An install with an ssh:// host no longer runs itself out of processes. Docksentry is PID 1 in its container and inherits every orphan; the ssh masters ControlPersist backgrounds are exactly that, and nobody ever waited for them. Measured twice on a live install: 12074 defunct ssh processes on 10.09., 12069 again on 16.09. — five days after the last restart — until every host failed at once.
A small thread now collects them from inside, once a minute. It touches only zombies (already exited, only waiting to be collected), only children of PID 1, and only ones whose command is ssh — a thing Docksentry never starts itself. Each is collected by its own PID, which takes nothing from subprocess.run() waiting for its own children. That last part is the one that matters: a reaper calling waitpid(-1) would race the update path and could make an update report a success it never had.
Zombies of any other name are left alone and counted, so a second leak would show in the log rather than be hidden by this one.
Verified
As PID 1 in the built image: 120 orphans piled up, one pass collected all of them, 20 zombies of another name were left alone and counted, and 40 concurrent subprocess.run children kept every one of their exit codes. 3000 zombies collected in 96 ms.
End to end with real containers: a swap out of the published beta.29 into this build, then a swap out of this build with the reaper thread live — zero restarts, data bit-identical both times, 25 orphans planted in the running container collected on the next pass.
tcp://, context:// and single-host installs never had the leak; for them nothing changes.