feat: add wireguard watchdog

This commit is contained in:
danny 2025-12-30 15:11:46 +08:00
parent b3c5ad2880
commit 27482b20d7
7 changed files with 137 additions and 30 deletions

View file

@ -1,12 +1,130 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) getExe;
notifyUser = pkgs.writeShellScriptBin "wg0-watchdog-notify-user" ''
is_wg_active() {
systemctl is-active wg-quick-wg0.service >/dev/null 2>&1
return $?
}
if is_wg_active; then
notify-send -u critical -a Wireguard "Endpoint up, wireguard resumed."
else
notify-send -u critical -a Wireguard "Endpoint down, wireguard stopped."
fi
'';
watchDog = pkgs.writeShellScriptBin "wg0-watchdog" ''
TARGET_CONF="$1"
PING_INTERVAL=1
PING_TIMEOUT=1
PING_COUNT=1
set -euo pipefail
error_with_msg() {
echo "$1"
echo "Exiting"
exit 1
}
notify() {
users=$(loginctl list-users --json=short | jq -r '.[].user')
for user in $users; do
systemctl --machine=danny@.host --user start wg0-notify-user
done
}
get_ip_from_conf() {
sed -n "s/Endpoint[[:space:]]*=[[:space:]]*\(.*\):[0-9]*/\\1/p" "$1"
}
check_health() {
ping -c "$PING_COUNT" -W "$PING_TIMEOUT" $1 >/dev/null 2>&1
return $?
}
is_wg_active() {
systemctl is-active wg-quick-wg0.service >/dev/null 2>&1
return $?
}
start_wg() {
systemctl start wg-quick-wg0.service >/dev/null
}
stop_wg() {
systemctl stop wg-quick-wg0.service >/dev/null
}
if [ ! -e "$TARGET_CONF" ]; then
error_with_msg "Target wireguard configuration not exist: $TARGET_CONF"
fi
TARGET_IP=$(get_ip_from_conf "$TARGET_CONF")
if [ -z "$TARGET_IP" ]; then
error_with_msg "IP not found"
fi
echo "Start detecting..."
while true; do
if check_health "$TARGET_IP"; then
if ! is_wg_active; then
start_wg
echo "Endpoint up, wireguard resumed."
notify
fi
else
if is_wg_active; then
stop_wg
echo "Endpoint down, wireguard stopped."
notify
fi
fi
sleep $PING_INTERVAL
done
'';
in
{
sops.secrets."wireguard/wg0.conf" = { };
networking = {
firewall = {
allowedUDPPorts = [ 51820 ];
};
wg-quick.interfaces.wg0.configFile = config.sops.secrets."wireguard/wg0.conf".path;
};
systemd.services.wg0-watchdog = {
wantedBy = [ "wg-quick-wg0.service" ];
after = [ "wg-quick-wg0.service" ];
path = with pkgs; [
jq
];
serviceConfig = {
ExecStart = "${getExe watchDog} \"${config.sops.secrets."wireguard/wg0.conf".path}\"";
RestartSec = 5;
TimeoutStopSec = 0;
};
};
systemd.user.services.wg0-notify-user = {
wantedBy = [ "graphical-session.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${getExe notifyUser}";
};
path = with pkgs; [
libnotify
];
};
}