Commit 08a4f18bb69e

Vincent Demeester <vincent@sbr.pm>
2026-08-11 19:23:12
feat(wireguard): made server interface configurable
The server module hardcoded wg0, port 51820, the private key path and the masqueraded subnet, so a host could not run a client and a server side by side. Defaults are unchanged, leaving carthage untouched.
1 parent f320374
Changed files (1)
modules
wireguard
modules/wireguard/server.nix
@@ -31,6 +31,39 @@ in
         description = "Peers linked to the interface.";
         type = with types; listOf anything;
       };
+      interface = mkOption {
+        type = types.str;
+        default = "wg0";
+        description = ''
+          Name of the wireguard interface. Override when a host already uses
+          wg0 as a client (e.g. lutece, which is a mesh client on wg0 and a
+          travel exit server on wg1).
+        '';
+      };
+      listenPort = mkOption {
+        type = types.int;
+        default = 51820;
+        description = ''
+          UDP port the server listens on. Opened in the firewall.
+        '';
+      };
+      privateKeyFile = mkOption {
+        type = types.str;
+        default = "/etc/wireguard/private.key";
+        description = ''
+          Path to the interface private key. Must differ from the client key
+          when a host runs both roles.
+        '';
+      };
+      natSource = mkOption {
+        type = types.str;
+        default = "10.100.0.0/24";
+        description = ''
+          Source subnet to masquerade. Applied on POSTROUTING without an output
+          interface, so it covers both internet egress and traffic forwarded
+          into another wireguard interface.
+        '';
+      };
       mtu = mkOption {
         type = with types; nullOr int;
         default = 1420;
@@ -48,12 +81,12 @@ in
 
     # Firewall configuration - supports both iptables and nftables
     networking.firewall = {
-      allowedUDPPorts = [ 51820 ];
-      trustedInterfaces = [ "wg0" ];
+      allowedUDPPorts = [ cfg.listenPort ];
+      trustedInterfaces = [ cfg.interface ];
 
       # iptables rules (used when nftables is disabled)
       extraCommands = mkIf (!usingNftables) ''
-        iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -j MASQUERADE
+        iptables -t nat -A POSTROUTING -s ${cfg.natSource} -j MASQUERADE
         iptables -A FORWARD -i wg+ -j ACCEPT
       '';
     };
@@ -65,7 +98,7 @@ in
         content = ''
           chain postrouting {
             type nat hook postrouting priority srcnat; policy accept;
-            ip saddr 10.100.0.0/24 masquerade
+            ip saddr ${cfg.natSource} masquerade
           }
 
           chain forward {
@@ -78,10 +111,13 @@ in
 
     networking.wireguard.enable = true;
     networking.wireguard.interfaces = {
-      "wg0" = {
-        inherit (cfg) ips peers;
-        listenPort = 51820;
-        privateKeyFile = "/etc/wireguard/private.key";
+      "${cfg.interface}" = {
+        inherit (cfg)
+          ips
+          peers
+          listenPort
+          privateKeyFile
+          ;
       }
       // lib.optionalAttrs (cfg.mtu != null) { inherit (cfg) mtu; };
     };