{ pkgs, lib, config, ... }: with lib; let cfg = config.fudo.vpn; peerOpts = { peer-name, ... }: { options = with types; { public-key = mkOption { type = str; description = "Peer public key."; }; allowed-ips = mkOption { type = listOf str; description = "List of allowed IP ranges from which this peer can connect."; example = [ "10.100.0.0/16" ]; default = []; }; }; }; in { options.fudo.vpn = with types; { enable = mkEnableOption "Enable Fudo VPN"; ips = mkOption { type = str; description = "IP range to assign this interface."; default = "10.100.0.0/16"; }; private-key-file = mkOption { type = str; description = "Path to the secret key (generated with wg [genkey/pubkey])."; example = "/path/to/secret.key"; }; listen-port = mkOption { type = port; description = "Port on which to listen for incoming connections."; default = 51820; }; peers = mkOption { type = loaOf (submodule peerOpts); description = "A list of peers allowed to connect."; default = {}; example = { peer0 = { public-key = "xyz"; allowed-ips = ["10.100.1.0/24"]; }; }; }; }; config = mkIf cfg.enable { networking.wireguard = { enable = true; interfaces.wgtun0 = { generatePrivateKeyFile = false; ips = [ cfg.ips ]; listenPort = cfg.listen-port; peers = mapAttrsToList (peer-name: peer-config: { publicKey = peer-config.public-key; allowedIPs = peer-config.allowed-ips; }) cfg.peers; privateKeyFile = cfg.private-key-file; }; }; }; }