{ config, lib, ... }: let cfg = config.modules.network.vpn-client; # NOLINT(let_order) in { options.modules.network.vpn-client = { enable = lib.mkEnableOption "a WireGuard VPN client"; interface = lib.mkOption { type = lib.types.str; default = "wg-home"; description = "Names the WireGuard interface."; }; address = lib.mkOption { type = lib.types.str; example = "10.23.100.3/32"; description = "Sets the client tunnel address in CIDR notation."; }; sopsFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = "Names the encrypted file that contains the WireGuard private key."; }; peer = { publicKey = lib.mkOption { type = lib.types.str; description = "Sets the WireGuard public key for the remote peer."; }; endpoint = lib.mkOption { type = lib.types.str; example = "203.0.113.10:51820"; description = "Sets the WireGuard endpoint for the remote peer."; }; }; }; config = lib.mkIf cfg.enable { assertions = [ { assertion = cfg.sopsFile != null; message = "Set modules.network.vpn-client.sopsFile when the VPN client is enabled."; } ]; sops.secrets.wireguard-home-private-key.sopsFile = cfg.sopsFile; registry.shell-shortcut.${config.networking.hostName} = { vpn-on = "sudo systemctl start wireguard-${cfg.interface}.target"; vpn-off = "sudo systemctl stop 'wireguard-${cfg.interface}*.service' wireguard-${cfg.interface}.target"; }; systemd.targets."wireguard-${cfg.interface}".wantedBy = lib.mkForce [ ]; networking.wireguard.interfaces.${cfg.interface} = { ips = [ cfg.address ]; mtu = 1280; privateKeyFile = config.sops.secrets.wireguard-home-private-key.path; peers = [ { inherit (cfg.peer) publicKey endpoint; allowedIPs = [ "10.23.0.0/16" ]; persistentKeepalive = 25; } ]; }; }; }