lib: make restarts hitless by adopting the kernel WireGuard dataplane - #14
Merged
Conversation
Co-authored-by: Codesmith Staging <codesmith-bot@users.noreply.github.com>
Co-authored-by: Codesmith Staging <codesmith-bot@users.noreply.github.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b9b5d0d. Configure here.
Co-authored-by: Codesmith Staging <codesmith-bot@users.noreply.github.com>
piob-io
approved these changes
Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Makes a vprox restart (i.e. any deploy) hitless for existing WireGuard peers. Previously, shutdown deleted the
vproxNinterface and startup force-recreated it empty, so every registered VM silently lost its tunnel: its config still looked healthy but the server no longer knew its pubkey, and packets were dropped until GitHub's 10-minute lost-communication timer killed the CI job. The kernel dataplane never needed to be touched; it keeps forwarding on its own and already stores everything needed to rebuild the process's memory.Three changes, all required together:
Start()inlib/server_manager.gono longer defersCleanupWireguard/CleanupIptables, so the interface and iptables rules survive shutdown (the cleanup functions remain for manual decommissioning;StartIptablesusesAppendUniquethroughout, so re-running it over surviving rules is a no-op).StartWireguard()adopts an existingvproxNinterface instead of delete+recreate, falling back to recreation only when the device's address doesn't matchWgCidr. The finishing steps (AddrReplace,LinkSetUp,ConfigureDevicewithoutReplacePeers) are non-destructive to existing peers.RestorePeersFromKernel()rebuildspeerIPs,ipAllocator, andnewPeersfrom the kernel device's peer dump. This is what makes 1+2 safe: without it, a fresh allocator would hand a new VM an IP an existing peer already owns, and the kernel would silently move that IP's routing to the new peer (AllowedIPs are exclusive), blackholing the old one. Restored peers get the usual connect grace period so the idle reaper doesn't instantly reap peers whose last handshake predates the restart.The peers-to-state computation is a pure function so it's testable without a kernel WireGuard device:
IpAllocator.Claim(addr)is the small new allocator API backing this: it marks a specific address as allocated, refusing addresses outside the prefix or already taken. Peers with missing or malformed AllowedIPs are removed from the device during restore to keep state consistent.Safety notes: the server's private key already persists in
/run/vprox/server-key, so an adopted interface keeps handshaking with existing peers. On a host reboot, tmpfs loses the key but the interface is gone too, so both sides reset together like a cold start today. Crashes (SIGKILL/OOM) get the same benefit, since the orphaned interface is adopted on next start. Result: only/connectis unavailable for the ~1s the process is down; existing tunnels never stop forwarding.Unit tests cover
Claimsemantics andrestorePeerState(valid peers, missing/non-/32/out-of-prefix/duplicate AllowedIPs).go vet,gofmt, andgo test ./lib/pass.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is enabled. (Staging)Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.