wireguard: wg-home / wg-home-full profiles so home VPN coexists with NetBird (#41) #47

Merged
rpickler merged 1 commit from issue-41-wireguard-netbird-profiles into main 2026-11-01 12:16:03 +00:00
Member

What

Implements the plan approved in the thread (comment id 1042: "Looks perfect. Go ahead and push a pr"): two NetworkManager profiles per fully-managed client so wg-home can coexist with the work NetBird VPN.

  • lib/wireguard.nix — adds a wgProfiles table and parameterizes mkNetworkManagerConfig by profile:
    • home — allowed-ips=192.168.97.0/24,192.168.73.0/24, [ipv4] never-default=true, route-metric=40000, dns-priority=500 (low precedence) — coexists with netbird.
    • home-full — byte-for-byte today's full-tunnel behavior (0.0.0.0/0, gateway, VPN DNS precedence).
    • Both keep interface-name=wg-home, so the server still sees one peer per host — zero server-side churn, same keypair.
  • modules/wireguard-client.nix — renders both via sops.templates into /etc/NetworkManager/system-connections/ (wg-home.nmconnection, wg-home-full.nmconnection), same 0600/owner/key handling as before.

Hosts affected: kansas, pumpkin (rpickler.vpn.enable = true). Server module, peer keys/rotation, and the manual app-script configs (mkClientConfig) are untouched.

Verified (nix eval of the flake, both hosts)

$ nix eval … nixosConfigurations.kansas.config.sops.templates."home".content
[connection]
id=wg-home
type=wireguard
interface-name=wg-home
autoconnect=false
…
allowed-ips=192.168.97.0/24,192.168.73.0/24
…
address1=192.168.73.4/24,192.168.73.1
never-default=true
dns=192.168.73.1;
dns-priority=500;
dns-search=vpn;
route-metric=40000;

home-full output is identical to the pre-change config (modulo blank lines between sections, which NM's keyfile parser does not require). kansas, pumpkin and pi4 all still evaluate; template paths render to wg-home.nmconnection and wg-home-full.nmconnection.

One refinement vs. the posted plan

The plan said "no DNS is pushed as default" for home — this PR keeps dns=192.168.73.1 on the link but at dns-priority=500. That's what makes *.vpn work while netbird is up: systemd-resolved merges search domains across links regardless of priority (priority only orders which link handles non-matching names), so *.vpn queries route to home dnsmasq via wg-home while netbird's link stays the default resolver for everything else. Removing DNS entirely (priority -1/empty) would have silently killed *.vpn resolution — the opposite of the goal.

Usage after deploy (kansas)

  • nmcli con up wg-home → internal ranges + *.vpn DNS with netbird still up.
  • nmcli con up wg-home-full → full tunnel; netbird off (two default-route providers never coexist — inherent, not a bug).
  • Both share interface-name=wg-home; if NM complains the device is busy when swapping profiles while the other is active, nmcli con down <other> && nmcli con up <new>.

Caveats/rollback as posted in the issue: a plain revert removes the rendered connections on next switch.

Fixes #41

## What Implements the plan approved in the thread (comment id 1042: "Looks perfect. Go ahead and push a pr"): two NetworkManager profiles per fully-managed client so wg-home can coexist with the work NetBird VPN. - **`lib/wireguard.nix`** — adds a `wgProfiles` table and parameterizes `mkNetworkManagerConfig` by profile: - `home` — `allowed-ips=192.168.97.0/24,192.168.73.0/24`, `[ipv4] never-default=true`, `route-metric=40000`, `dns-priority=500` (low precedence) — coexists with netbird. - `home-full` — byte-for-byte today's full-tunnel behavior (`0.0.0.0/0`, gateway, VPN DNS precedence). - Both keep `interface-name=wg-home`, so the server still sees **one peer per host** — zero server-side churn, same keypair. - **`modules/wireguard-client.nix`** — renders both via `sops.templates` into `/etc/NetworkManager/system-connections/` (`wg-home.nmconnection`, `wg-home-full.nmconnection`), same 0600/owner/key handling as before. Hosts affected: kansas, pumpkin (`rpickler.vpn.enable = true`). Server module, peer keys/rotation, and the manual app-script configs (`mkClientConfig`) are untouched. ## Verified (nix eval of the flake, both hosts) ``` $ nix eval … nixosConfigurations.kansas.config.sops.templates."home".content [connection] id=wg-home type=wireguard interface-name=wg-home autoconnect=false … allowed-ips=192.168.97.0/24,192.168.73.0/24 … address1=192.168.73.4/24,192.168.73.1 never-default=true dns=192.168.73.1; dns-priority=500; dns-search=vpn; route-metric=40000; ``` `home-full` output is identical to the pre-change config (modulo blank lines between sections, which NM's keyfile parser does not require). kansas, pumpkin and pi4 all still evaluate; template paths render to `wg-home.nmconnection` and `wg-home-full.nmconnection`. ## One refinement vs. the posted plan The plan said "no DNS is pushed as default" for `home` — this PR keeps `dns=192.168.73.1` on the link but at `dns-priority=500`. That's what makes `*.vpn` work while netbird is up: systemd-resolved merges **search domains across links regardless of priority** (priority only orders which link handles *non-matching* names), so `*.vpn` queries route to home dnsmasq via wg-home while netbird's link stays the default resolver for everything else. Removing DNS entirely (priority `-1`/empty) would have silently killed `*.vpn` resolution — the opposite of the goal. ## Usage after deploy (kansas) - `nmcli con up wg-home` → internal ranges + `*.vpn` DNS **with netbird still up**. - `nmcli con up wg-home-full` → full tunnel; netbird off (two default-route providers never coexist — inherent, not a bug). - Both share `interface-name=wg-home`; if NM complains the device is busy when swapping profiles while the other is active, `nmcli con down <other> && nmcli con up <new>`. Caveats/rollback as posted in the issue: a plain revert removes the rendered connections on next switch. Fixes #41
Fully-managed clients got a single NetworkManager connection with
0.0.0.0/0, a default-route gateway and VPN-preferred DNS, which made
wg-home and the work NetBird VPN mutually exclusive (kansas: 'nothing
works'). Render two profiles per managed host instead, sharing the
same keypair/interface-name so the server sees one peer:

- wg-home: allowed-ips = internal ranges only, ipv4.never-default,
  high route-metric, dns-priority=500 — coexists with netbird;
  dns-search=vpn still sends *.vpn lookups to home dnsmasq.
- wg-home-full: today's full-tunnel behavior (0.0.0.0/0, gateway,
  VPN DNS precedence) for when netbird is off.

Manual app-script enrollments (mkClientConfig) are unchanged.
rpickler deleted branch issue-41-wireguard-netbird-profiles 2026-11-01 12:16:05 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
richardpickler.com/nixos!47
No description provided.