feat(nixos): add neogaia WireGuard client

This commit was merged in pull request #18.
This commit is contained in:
2026-09-07 12:18:52 -04:00
parent aab32198d1
commit 2463b7e787
4 changed files with 152 additions and 3 deletions

View File

@@ -7,6 +7,7 @@
# Waybar: a top status bar reading system state at a glance.
let
cfg = config.modules.desktop.session.waybar;
vpnClient = config.modules.network.vpn-client;
user = config.user.name;
# A Nerd Font Private-Use-Area codepoint as a literal character, decoded
@@ -48,6 +49,23 @@ let
fi
'';
vpnStatus = pkgs.writeShellScript "waybar-vpn-status" ''
interface=${lib.escapeShellArg vpnClient.interface}
if ! ${pkgs.iproute2}/bin/ip link show dev "$interface" >/dev/null 2>&1; then
printf '{"text":"","class":"idle"}\n'
exit 0
fi
ipaddr=$(${pkgs.iproute2}/bin/ip -4 -o addr show dev "$interface" | ${pkgs.gawk}/bin/awk '{ print $4; exit }')
${pkgs.jq}/bin/jq -cn \
--arg text "󰲝" \
--arg tooltip "VPN $interface: ''${ipaddr:-no IPv4}" \
--arg class "active" \
'{ text: $text, tooltip: $tooltip, class: $class }'
'';
networkStatus = pkgs.writeShellScript "waybar-network-status" ''
active=$(
${pkgs.networkmanager}/bin/nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device status \
@@ -118,6 +136,9 @@ in
"custom/idle-lock"
"mpris"
"wireplumber"
]
++ lib.optional vpnClient.enable "custom/vpn"
++ [
"custom/network"
"battery"
"custom/dnd"
@@ -173,6 +194,12 @@ in
on-click = "${pkgs.wireplumber}/bin/wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
};
"custom/vpn" = {
return-type = "json";
exec = "${vpnStatus}";
interval = 5;
};
"custom/network" = {
return-type = "json";
exec = "${networkStatus}";

View File

@@ -0,0 +1,104 @@
{
config,
lib,
...
}:
let
cfg = config.modules.network.vpn-client;
in
{
options.modules.network.vpn-client = {
enable = lib.mkEnableOption "a WireGuard VPN client";
interface = lib.mkOption {
type = lib.types.str;
default = "wg-home";
description = "WireGuard interface name.";
};
address = lib.mkOption {
type = lib.types.str;
example = "10.23.100.3/32";
description = "Client tunnel address in CIDR notation.";
};
privateKeySecret = lib.mkOption {
type = lib.types.str;
default = "wireguard-home-private-key";
description = "SOPS secret containing the WireGuard client private key.";
};
autoStart = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to start the VPN tunnel during boot.";
};
mtu = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = 1280;
description = "Tunnel MTU, or null to use the WireGuard default.";
};
sopsFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = "Encrypted secrets file that contains privateKeySecret.";
};
peer = {
publicKey = lib.mkOption {
type = lib.types.str;
description = "WireGuard public key for the remote peer.";
};
endpoint = lib.mkOption {
type = lib.types.str;
example = "203.0.113.10:51820";
description = "WireGuard endpoint for the remote peer.";
};
allowedIPs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "10.23.0.0/16" ];
description = "Routes to send through the VPN tunnel.";
};
persistentKeepalive = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = 25;
description = "Persistent keepalive interval in seconds, or null to disable it.";
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.sopsFile != null;
message = "modules.network.vpn-client.sopsFile must name the encrypted secrets file containing the WireGuard private key.";
}
];
sops.secrets.${cfg.privateKeySecret}.sopsFile = cfg.sopsFile;
systemd.targets."wireguard-${cfg.interface}" = lib.mkIf (!cfg.autoStart) {
wantedBy = lib.mkForce [ ];
};
networking.wireguard.interfaces.${cfg.interface} = {
ips = [ cfg.address ];
mtu = cfg.mtu;
privateKeyFile = config.sops.secrets.${cfg.privateKeySecret}.path;
peers = [
({
inherit (cfg.peer) publicKey endpoint allowedIPs;
}
// lib.optionalAttrs (cfg.peer.persistentKeepalive != null) {
inherit (cfg.peer) persistentKeepalive;
})
];
};
};
}