{ config, lib, pkgs, util, ... }: let cfg = config.modules.network.vpn-client; vpnIcon = util.glyph [ "db83" "dc9d" ]; vpnStatus = pkgs.writeShellScript "waybar-vpn-status" '' interface=${lib.escapeShellArg cfg.interface} if ! ${lib.getExe' pkgs.iproute2 "ip"} link show dev "$interface" >/dev/null 2>&1; then printf '{"text":"","class":"idle"}\n' exit 0 fi ipaddr=$(${lib.getExe' pkgs.iproute2 "ip"} -4 -o addr show dev "$interface" | ${lib.getExe' pkgs.gawk "awk"} '{ print $4; exit }') ${lib.getExe pkgs.jq} -cn \ --arg text "${vpnIcon}" \ --arg tooltip "VPN $interface: ''${ipaddr:-no IPv4}" \ --arg class "active" \ '{ text: $text, tooltip: $tooltip, class: $class }' ''; 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"; }; registry.waybar.${config.networking.hostName}."custom/vpn" = { order = 50; settings = { return-type = "json"; exec = "${vpnStatus}"; interval = 5; }; }; 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; } ]; }; }; }