From 3b8c8b05973c6fd219026037d24a0bca8ae031f5 Mon Sep 17 00:00:00 2001 From: majorlinux Date: Sat, 23 May 2026 02:40:04 -0400 Subject: [PATCH] =?UTF-8?q?ssh.socket=20wiki:=20correct=20BindsTo=E2=86=92?= =?UTF-8?q?Requires,=20add=20warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BindsTo=tailscaled.service causes a systemd ordering cycle that prevents ssh.socket from starting on reboot. Updated the recommended fix to use Requires= and added a warning admonition explaining why BindsTo must not be used. Added tttpod-hetzner to affected hosts list and linked the 2026-05-23 dcaprod incident. --- .../networking/ssh-socket-tailscale-race-condition.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/05-troubleshooting/networking/ssh-socket-tailscale-race-condition.md b/05-troubleshooting/networking/ssh-socket-tailscale-race-condition.md index 817958d..656bf0e 100644 --- a/05-troubleshooting/networking/ssh-socket-tailscale-race-condition.md +++ b/05-troubleshooting/networking/ssh-socket-tailscale-race-condition.md @@ -35,7 +35,7 @@ Add Tailscale dependency to the socket override: # /etc/systemd/system/ssh.socket.d/override.conf [Unit] After=tailscaled.service -BindsTo=tailscaled.service +Requires=tailscaled.service [Socket] ListenStream= @@ -51,11 +51,14 @@ systemctl status ssh.socket # verify Listen: shows correct IP ``` - `After=` ensures the socket waits for Tailscale to start -- `BindsTo=` restarts the socket if Tailscale restarts, preventing stale binds +- `Requires=` ensures tailscaled must be running for the socket to activate + +!!! warning "Do NOT use BindsTo" + `BindsTo=tailscaled.service` creates a **systemd ordering cycle** during shutdown: `basic.target → sockets.target → ssh.socket → tailscaled.service → basic.target`. Systemd breaks the cycle by deleting jobs unpredictably, which can prevent `ssh.socket` from starting on the next boot — leaving SSH dead until manual intervention. This was discovered on 2026-05-23 after the original fix (2026-05-19) used `BindsTo` and caused a second outage on dcaprod-hetzner. `Requires` provides the startup dependency without the dangerous bidirectional lifecycle coupling. ### Affected Hosts -Ubuntu hosts using `configure_tailscale_ssh_only.yml`: majorlinux, dcaprod-hetzner. Fedora hosts (majordiscord) use firewall rules for SSH restriction — not affected by this race. +Ubuntu hosts using `configure_tailscale_ssh_only.yml`: majorlinux, dcaprod-hetzner, tttpod-hetzner. Fedora hosts (majordiscord) use firewall rules for SSH restriction — not affected by this race. --- @@ -116,4 +119,5 @@ All hosts where Tailscale is the primary access path. Particularly impactful on - [[dcaprod#2026-05-19 — SSH unreachable due to ssh.socket race condition with Tailscale]] - [[majordiscord#2026-05-19 — Tailscale boot race: unreachable after Ansible reboot]] - [[majorlinux#2026-05-19 — ssh.socket override patched: added Tailscale dependency]] +- [[dcaprod#2026-05-23 — SSH unreachable again: BindsTo ordering cycle in ssh.socket override]] - Ansible: `configure_tailscale_ssh_only.yml`, `configure_tailscale_network_wait.yml`