From f7f9148111fefa60549b791254786b4015d44359 Mon Sep 17 00:00:00 2001 From: r-vdp Date: Mon, 13 Apr 2026 19:57:30 +0200 Subject: [PATCH] nixos/network-interfaces: don't write net.ipv4.conf.all.forwarding=0 This key is an alias for net.ipv4.ip_forward. The kernel default is already 0, so emitting `=0` from sysctl.d is at best a no-op. It is actively harmful when systemd-networkd manages forwarding via `networkd.conf [Network] IPv4Forwarding=yes`: on a cold boot systemd-sysctl runs before networkd and networkd's write wins, but on a `nixos-rebuild switch` that restarts both services (any systemd package change does, since kernel.poweroff_cmd in 60-nixos.conf follows the systemd store path) the ordering is undefined and sysctl can run last, silently flipping a router back to ip_forward=0. Only emit the sysctl when at least one interface has proxyARP=true, matching every other in-tree setter of this key (nat, docker, tailscale, netbird, ...) which only ever write `true`. The previous value was already mkDefault, so nothing could have been relying on it to force forwarding off anyway. --- nixos/modules/tasks/network-interfaces.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 83d60ba80e40..2b01843b82dc 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -1780,7 +1780,9 @@ in optionalString hasBonds "options bonding max_bonds=0"; boot.kernel.sysctl = { - "net.ipv4.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces); + # Only set when proxyARP needs it; never write =0 (the kernel default), + # which would race with systemd-networkd's IPv4Forwarding= on switch. + "net.ipv4.conf.all.forwarding" = mkIf (any (i: i.proxyARP) interfaces) (mkDefault true); "net.ipv6.conf.all.disable_ipv6" = mkDefault (!cfg.enableIPv6); "net.ipv6.conf.default.disable_ipv6" = mkDefault (!cfg.enableIPv6); # allow all users to do ICMP echo requests (ping)