You are not logged in.

#1 2026-01-27 12:52:32

virgilggx
Member
Registered: 2024-05-12
Posts: 32

[SOLVED] Unable to automatically activate a VPN connection

Hello,

I would like to automatically connect when connected to network.
In Wi-Fi & Networking settings I see a checkbox for enabling "Automatically connect to VPN" but I can't check it (same for "Connect automatically with priority").

With nmcli I can see autoconnect enabled:

❯ nmcli c edit VPN
nmcli> print connection.autoconnect
connection.autoconnect: yes

I'm using 6.17.13-hardened1-2-hardened kernel (and KDE Plasma 6 / Wayland) with theses packages:

❯ yay -Qs networkmanager

local/lib32-libnm 1.54.3-1
    NetworkManager client library (32-bit)
local/libnm 1.54.3-1
    NetworkManager client library
local/libnma-common 1.10.6-3
    NetworkManager GUI client library (common files)
local/libnma-gtk4 1.10.6-3
    NetworkManager GUI client library (GTK4)
local/networkmanager 1.54.3-1
    Network connection manager and user applications
local/networkmanager-openvpn 1.12.5-1
    NetworkManager VPN plugin for OpenVPN (with GUI)
local/networkmanager-qt 6.22.0-1 (kf6)
    Qt wrapper for NetworkManager API
local/networkmanager-vpn-plugin-openvpn 1.12.5-1
    NetworkManager VPN plugin for OpenVPN (VPN plugin only)

I'm using systemd-resolv for DNS.
I disabled IPv6 via the kernel parameter ipv6.disable=1.
When configuring the connection, I selected the option Store password for this user only (encrypted).

[EDIT]

I used  NetworkManager-dispatcher.

1. Need to create a script:

❯ sudo cat /etc/NetworkManager/dispatcher.d/90-autovpn

#!/usr/bin/env zsh
set -euo pipefail

VPN_NAME="VPN" # My connection is named "VPN"
LOGTAG="nm-autovpn"

log() { logger -t "$LOGTAG" -- "$*"; }

vpn_is_active() {
  nmcli -t -f NAME con show --active | grep -Fxq "$VPN_NAME"
}

nm_connectivity() {
  nmcli -t -f CONNECTIVITY general 2>/dev/null | head -n1
}

has_uplink() {
  nmcli -t -f NAME,TYPE,DEVICE con show --active \
    | awk -F: '($2!="vpn" && $2!="loopback" && $2!="bridge" && $3!="" && $3!="--"){found=1}
              END{exit(found?0:1)}'
}

LOCKFILE="/run/nm-autovpn.lock"
if command -v flock >/dev/null 2>&1; then
  exec {lockfd}>|"$LOCKFILE" || exit 0
  flock -n $lockfd || exit 0
else
  log "WARN: flock not found; running without lock."
fi

UP_STATEFILE="/run/nm-autovpn.last_up"
UP_COOLDOWN=20  # seconds

should_cooldown_up() {
  local now last
  now=$(date +%s)
  last=0
  if [[ -r "$UP_STATEFILE" ]]; then
    last=$(<"$UP_STATEFILE") || last=0
  fi
  if (( now - last < UP_COOLDOWN )); then
    return 0
  fi
  print -r -- "$now" >| "$UP_STATEFILE"
  return 1
}

vpn_up() {
  if vpn_is_active; then
    log "VPN already active ($VPN_NAME)."
    return 0
  fi

  if should_cooldown_up; then
    log "SKIP: cooldown active for VPN up."
    return 0
  fi

  log "Bringing VPN up ($VPN_NAME)…"
  nmcli -w 10 con up id "$VPN_NAME" >/dev/null 2>&1 || {
    log "FAILED to bring VPN up ($VPN_NAME)."
    return 0
  }
  log "VPN is up ($VPN_NAME)."
}

vpn_down() {
  if ! vpn_is_active; then
    log "VPN already down ($VPN_NAME)."
    return 0
  fi
  log "Bringing VPN down ($VPN_NAME)…"
  nmcli -w 10 con down id "$VPN_NAME" >/dev/null 2>&1 || true
  log "VPN is down ($VPN_NAME)."
}

IFACE="${1:-}"
ACTION="${2:-}"

case "$ACTION" in
  vpn-*) exit 0 ;;
esac

case "$ACTION" in
  up)
    sleep 2
    c="$(nm_connectivity)"
    log "ACTION=up IFACE=$IFACE connectivity=$c"
    if [[ "$c" == "full" ]] && has_uplink; then
      vpn_up
    else
      log "SKIP: strict up not satisfied (connectivity=$c, uplink=$(has_uplink && echo yes || echo no))."
    fi
    ;;

  down)
    c="$(nm_connectivity)"
    log "ACTION=down IFACE=$IFACE connectivity=$c"
    if [[ "$c" == "none" ]] || ! has_uplink; then
      vpn_down
    else
      log "SKIP: down ignored (uplink still present, connectivity=$c)."
    fi
    ;;

  connectivity-change)
    state="${CONNECTIVITY_STATE:-unknown}"
    log "ACTION=connectivity-change state=$state"
    case "$state" in
      NONE)
        vpn_down
        ;;
      FULL)
        if has_uplink; then
          vpn_up
        else
          log "SKIP: connectivity FULL but no uplink connection."
        fi
        ;;
      LIMITED|PORTAL|UNKNOWN)
        ;;
    esac
    ;;

  *)
    exit 0
    ;;
esac

2. Switch to unencrypted for all users and move .cert .pem and related file from my user to /etc/NetworkManager/openvpn

3. Edit /etc/NetworkManager/system-connections/NAME.nmconnection to match new filepath

4. Restart services

sudo systemctl enable --now NetworkManager-dispatcher.service
sudo systemctl restart NetworkManager

5. Disconnect / connect and it worked!

Last edited by virgilggx (2026-01-28 04:09:58)

Offline

#2 2026-01-27 14:49:20

llamas
Member
Registered: 2024-07-28
Posts: 3
Website

Re: [SOLVED] Unable to automatically activate a VPN connection

I'm by no means an expert on this, but the way I've always connected to VPNs is by running sudo openvpn [config file]. You could just make a systemd service (put in /etc/systemd/system) that automatically starts openvpn or another VPN client "manually" (independent of network manager), something like.

[Unit]
Description=Starts Openvpn
StartLimitIntervalSec=0
Requisite=network.target
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=1
User=root
ExecStart=/usr/local/bin/start-openvpn.sh

[Install]
WantedBy=multi-user.target

This is not tested, it's just based on another similar unit file I wrote, with added lines to make this unit start after the network initializes. I suppose you could replace network.target with [networkmanagerservice].service. I personally use iwd, so I don't know what the network manager service is called.

There's probably a better, network manager specific way to do this, I see something outlined on the wiki in section 5.2.6, "Use dispatcher to connect to a VPN after a network connection is established"

Last edited by llamas (2026-01-27 14:50:41)

Offline

Board footer

Powered by FluxBB