Summary
After macOS sleep/wake, the Coder Connect tunnel can stay unusable for several minutes: new SSH dials fail with i/o timeout until magicsock's periodic re-STUN re-homes the path on its own. macOS wake from a short, same-network sleep often produces no netmon link-change event, so the daemon's existing linkChange() recovery (Rebind + ReSTUN) never fires.
Background
coder/coder PR coder/coder#26739 adds the daemon-side hook for this. It introduces a new CoderVPN RPC (WakeRequest / WakeResponse, tunnel protocol 1.3) whose handler calls tailnet.Conn.Rebind() (magicConn.Rebind() + magicConn.ReSTUN("wake")), the same recovery path a major link change triggers.
The daemon side only exposes the hook. Coder Desktop must actually emit it.
What's needed in coder-desktop-macos
- Subscribe to a system wake event,
NSWorkspace.shared.notificationCenter didWakeNotification (or IORegisterForSystemPower for lower-level power events).
- On wake, send a
ManagerMessage with the new WakeRequest over the existing CoderVPN tunnel RPC channel.
- Only send when the negotiated tunnel protocol version is
>= 1.3 (older daemons won't handle the message). Regenerate the Swift protobuf bindings from the updated vpn.proto once the coder/coder PR merges.
- Optionally surface
WakeResponse.success / error_message in debug logs.
This is an event-driven kick on a known OS event, not a health check or poll. It forces path re-discovery and never tears down a live tunnel.
Refs
Summary
After macOS sleep/wake, the Coder Connect tunnel can stay unusable for several minutes: new SSH dials fail with
i/o timeoutuntil magicsock's periodic re-STUN re-homes the path on its own. macOS wake from a short, same-network sleep often produces no netmon link-change event, so the daemon's existinglinkChange()recovery (Rebind+ReSTUN) never fires.Background
coder/coder PR coder/coder#26739 adds the daemon-side hook for this. It introduces a new CoderVPN RPC (
WakeRequest/WakeResponse, tunnel protocol1.3) whose handler callstailnet.Conn.Rebind()(magicConn.Rebind()+magicConn.ReSTUN("wake")), the same recovery path a major link change triggers.The daemon side only exposes the hook. Coder Desktop must actually emit it.
What's needed in coder-desktop-macos
NSWorkspace.shared.notificationCenterdidWakeNotification(orIORegisterForSystemPowerfor lower-level power events).ManagerMessagewith the newWakeRequestover the existing CoderVPN tunnel RPC channel.>= 1.3(older daemons won't handle the message). Regenerate the Swift protobuf bindings from the updatedvpn.protoonce the coder/coder PR merges.WakeResponse.success/error_messagein debug logs.This is an event-driven kick on a known OS event, not a health check or poll. It forces path re-discovery and never tears down a live tunnel.
Refs
Root cause and analysis: Coder Connect tunnel not re-STUN'd on system wake; dead for minutes after macOS sleep coder#26736
Daemon-side implementation: fix: add VPN wake rebind hook coder#26739
Windows counterpart: Send CoderVPN WakeRequest on system wake to recover tunnel paths coder-desktop-windows#172