wireguard-server.nix (3086B)
1 { 2 config, 3 pkgs, 4 lib, 5 ... 6 }: 7 8 let 9 cfg = config.services.local.wireguard-server; 10 in 11 { 12 options.services.local.wireguard-server = { 13 enable = lib.mkEnableOption "WireGuard VPN server"; 14 15 address = lib.mkOption { 16 type = lib.types.str; 17 default = "10.100.0.1/24"; 18 description = "VPN server address with CIDR"; 19 }; 20 21 privateKeySecretName = lib.mkOption { 22 type = lib.types.str; 23 description = "Name of the sops secret containing the private key"; 24 }; 25 26 listenPort = lib.mkOption { 27 type = lib.types.port; 28 default = 51820; 29 description = "WireGuard listen port"; 30 }; 31 32 externalInterface = lib.mkOption { 33 type = lib.types.str; 34 default = "eth0"; 35 description = "External network interface for NAT"; 36 }; 37 38 peers = lib.mkOption { 39 type = lib.types.listOf (lib.types.submodule { 40 options = { 41 name = lib.mkOption { 42 type = lib.types.str; 43 description = "Peer name (for comments)"; 44 }; 45 publicKey = lib.mkOption { 46 type = lib.types.str; 47 description = "Peer's public key"; 48 }; 49 allowedIPs = lib.mkOption { 50 type = lib.types.listOf lib.types.str; 51 description = "Allowed IPs for this peer"; 52 }; 53 }; 54 }); 55 default = []; 56 description = "List of VPN peers"; 57 }; 58 59 enableDnsmasq = lib.mkOption { 60 type = lib.types.bool; 61 default = true; 62 description = "Enable dnsmasq for VPN DNS"; 63 }; 64 }; 65 66 config = lib.mkIf cfg.enable { 67 sops.secrets.${cfg.privateKeySecretName} = { 68 restartUnits = [ "wg-quick-wg0.service" ]; 69 }; 70 71 networking.nat = { 72 enable = true; 73 externalInterface = cfg.externalInterface; 74 internalInterfaces = [ "wg0" ]; 75 }; 76 77 networking.firewall.allowedUDPPorts = [ cfg.listenPort ] ++ lib.optionals cfg.enableDnsmasq [ 53 ]; 78 networking.firewall.allowedTCPPorts = lib.optionals cfg.enableDnsmasq [ 53 ]; 79 80 services.dnsmasq = lib.mkIf cfg.enableDnsmasq { 81 enable = true; 82 settings = { 83 interface = "wg0"; 84 }; 85 }; 86 87 networking.wg-quick.interfaces.wg0 = { 88 address = [ cfg.address ]; 89 listenPort = cfg.listenPort; 90 privateKeyFile = "/run/secrets/${cfg.privateKeySecretName}"; 91 92 postUp = '' 93 ${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -o ${cfg.externalInterface} -j ACCEPT 94 ${pkgs.iptables}/bin/iptables -A FORWARD -o wg0 -i ${cfg.externalInterface} -j ACCEPT 95 ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s ${cfg.address} -j MASQUERADE 96 ''; 97 preDown = '' 98 ${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -o ${cfg.externalInterface} -j ACCEPT 99 ${pkgs.iptables}/bin/iptables -D FORWARD -o wg0 -i ${cfg.externalInterface} -j ACCEPT 100 ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s ${cfg.address} -j MASQUERADE 101 ''; 102 103 peers = map (peer: { 104 publicKey = peer.publicKey; 105 allowedIPs = peer.allowedIPs; 106 }) cfg.peers; 107 }; 108 }; 109 }