Files
dev/configs/nixos/modules/network/vpn-client.nix

110 lines
2.9 KiB
Nix

{
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;
}
];
};
};
}