Skip to content

VPN notifications

VPN clients usually “silently” lose the connection and simply try to reconnect. It’s important to notice this immediately: sometimes traffic starts going over the regular network, which must not happen.

NetworkManager can call scripts when an interface goes up or down — from the directory /etc/NetworkManager/dispatcher.d/.

/etc/NetworkManager/dispatcher.d/90-notifly-vpn:

#!/usr/bin/env bash
set -eu
set -a; source /etc/notifly.env; set +a
INTERFACE=$1
ACTION=$2
# React only to VPN interfaces (tun*/wg*/ppp*).
case "$INTERFACE" in
tun*|wg*|ppp*) ;;
*) exit 0 ;;
esac
send() {
curl -fsS -X POST "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" \
-H "Content-Type: application/json" \
--data "$(jq -n --arg t "$1" --arg m "$2" --argjson p "$3" \
'{title:$t, message:$m, priority:$p}')" >/dev/null
}
case "$ACTION" in
vpn-up)
IP=$(ip -4 addr show "$INTERFACE" | awk '/inet /{print $2}')
send "🟢 VPN $INTERFACE up" "IP: $IP" 3
;;
vpn-down)
send "🔴 VPN $INTERFACE down" "Туннель закрыт. Проверьте подключение." 7
;;
esac
Окно терминала
sudo chmod 755 /etc/NetworkManager/dispatcher.d/90-notifly-vpn
sudo chown root:root /etc/NetworkManager/dispatcher.d/90-notifly-vpn

If you use wg-quick without NetworkManager, add to the config /etc/wireguard/wg0.conf:

[Interface]
PostUp = curl -fsS -X POST "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" -H "Content-Type: application/json" -d '{"title":"🟢 wg0 up","priority":3}'
PostDown = curl -fsS -X POST "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" -H "Content-Type: application/json" -d '{"title":"🔴 wg0 down","priority":7}'

(подставьте переменные через EnvironmentFile= в systemd-юните wg-quick@).

Watchdog: check that the tunnel is actually alive

Section titled “Watchdog: check that the tunnel is actually alive”

A tunnel can appear “up” but traffic may not flow. Set up a check:

/usr/local/bin/notifly-vpn-check
#!/usr/bin/env bash
set -eu
set -a; source /etc/notifly.env; set +a
CHECK_HOST=10.10.0.1 # IP inside the VPN network
STATE=/var/lib/notifly-vpn.state
PREV=$(cat "$STATE" 2>/dev/null || echo OK)
if ping -c1 -W2 "$CHECK_HOST" >/dev/null 2>&1; then
NOW=OK
else
NOW=FAIL
fi
if [[ "$NOW" != "$PREV" ]]; then
if [[ "$NOW" == "FAIL" ]]; then
curl -fsS -X POST "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"⚠️ VPN не отвечает","message":"Пинг до '"$CHECK_HOST"' не проходит.","priority":7}' >/dev/null
else
curl -fsS -X POST "$NOTIFLY_URL/message?token=$NOTIFLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"✅ VPN восстановлен","priority":3}' >/dev/null
fi
fi
echo "$NOW" > "$STATE"

In cron, every minute:

* * * * * /usr/local/bin/notifly-vpn-check
  • No “leaks” to the regular network. You can immediately see that the VPN went down — you’ll have time to close Slack/IDE.
  • Control over IP changes. If the IP inside the VPN changed (a different server) — you get a message as well.
  • In corporate environments: push notifications to the VPN server owner about client reconnects.
  • Attach the traceroute to the monitoring host in the message.
  • Use priority 9 with a custom sound — a distinct tone for “VPN down”.