1 { pkgs, lib, config, hostName, credentials, ... }:
4 peers = import wg-intra/peers.nix;
5 wg = config.networking.wireguard.interfaces.${wgIface};
8 # Each peer select the other peers allowed to connect to it
9 options.networking.wireguard.${wgIface}.peers =
10 lib.genAttrs (lib.attrNames peers) (peerName: {
11 enable = lib.mkEnableOption "this peer";
14 systemd.services."wireguard-${wgIface}".serviceConfig.LoadCredentialEncrypted = "privateKey:${credentials}/wireguard/${wgIface}/privateKey.secret";
15 networking.wireguard.interfaces.${wgIface} = lib.recursiveUpdate
16 (removeAttrs peers.${hostName} ["ipv4" "persistentKeepalive" "peer"])
19 lib.mapAttrsToList (peerName: peer:
23 peer.persistentKeepalive # Useful if this peer is behind a NAT
24 or peers.${hostName}.persistentKeepalive # Useful if this host is behind a NAT
29 (lib.filterAttrs (peerName: _: config.networking.wireguard.${wgIface}.peers.${peerName}.enable) peers)
31 privateKeyFile = "$CREDENTIALS_DIRECTORY/privateKey";
33 # Set the MTU to a minimum
34 # (IPv4 requires at least 68 but it's 1280 for IPv6).
35 # This prevents connections to stall on huge packets,
36 # or delaying their initializing due to TCP PMTU probing.
38 ip link set dev ${wgIface} mtu 1280
41 networking.hosts = lib.mkMerge [
42 (lib.mapAttrs' (hostName: host:
43 lib.nameValuePair host.ipv4 [ "${hostName}.wg" ]) peers)
45 "${peers.losurdo.ipv4}" = [
46 "nix-extracache.losurdo.wg"
47 "nix-localcache.losurdo.wg"
52 networking.firewall.extraCommands = lib.optionalString (wg.listenPort != null) ''
53 ip46tables -A nixos-fw -i any -p udp -m udp --dport ${toString wg.listenPort} -j ACCEPT
56 networking.nftables.ruleset = lib.optionalString (wg.listenPort != null) ''
59 udp dport ${toString wg.listenPort} counter accept \
60 comment "Wireguard ${wgIface} input from peers"
63 udp dport ${toString wg.listenPort} counter accept \
64 comment "Wireguard ${wgIface} input from peers"
67 ${lib.optionalString (peers.${hostName}.peer.endpointsUpdater.enable or false) ''
68 tcp dport ${toString peers.${hostName}.listenPort} ip daddr ${peers.${hostName}.ipv4} counter accept comment "Wireguard ${wgIface} from peers to endpointUpdater"
73 iifname ${wgIface} jump input-intra
74 iifname ${wgIface} log level warn prefix "input-intra: " counter drop
78 udp sport ${toString wg.listenPort} counter accept \
79 comment "Wireguard ${wgIface} output to peers"
82 udp sport ${toString wg.listenPort} counter accept \
83 comment "Wireguard ${wgIface} output to peers"
86 ${lib.concatStringsSep "\n"
87 (lib.mapAttrsToList (peerName: peer: ''
88 ip daddr ${peer.ipv4} \
89 tcp dport ${toString peer.listenPort} \
91 comment "Wireguard ${wgIface} to endpointUpdater ${peerName}"
93 (lib.filterAttrs (peerName: peer:
94 config.networking.wireguard.${wgIface}.peers.${peerName}.enable &&
95 (peers.${peerName}.peer.endpointsUpdater.enable or false))
100 oifname ${wgIface} jump output-intra
101 oifname ${wgIface} log level warn prefix "output-intra: " counter drop
106 services.fail2ban.ignoreIP = lib.concatMap
107 (host: host.peer.allowedIPs)
108 (lib.attrValues peers);
109 networking.networkmanager.unmanaged = [ wgIface ];
110 systemd.services.sshd.after = ["wireguard-${wgIface}.service"];