Das Problem
Du hostest einen Proxmox-Server bei einem Cloud-Provider (srv-r2d2), der auf dein internes Netzwerk zugreifen muss. Die Lösung: OpenVPN-Client in einer Screen-Session.
# Das fragile Setup
screen -S openvpn
cd /root
openvpn --config gw-deathstar.ovpn
# Passwort eingeben
# Ctrl+A+D zum Detachen
Was schiefgehen kann:
- Screen stirbt: Session crashed, VPN tot, keine Auto-Reconnect
- Reboot: Nach Neustart ist die Session weg
- Jemand killt die Session:
screen -X -S openvpn quit→ Game Over - Passwort-Eingabe: Manuelle Intervention bei jedem Start
- Keine Logs: Debugging via Screen-Scroll? Viel Spaß damit
- Kein Monitoring: Tunnel down? Du merkst es wenn die ersten Tickets reinkommen
Das ist wie den Todesstern ohne Schild in den Kampf zu schicken - funktioniert bis es nicht mehr funktioniert.
TL;DR
Migriere deinen OpenVPN-Client zu einem systemd Service mit:
- ✅ Auto-Reconnect bei Verbindungsabbruch (max 120s)
- ✅ Automatischer Start nach Reboot
- ✅ Credentials in Datei (kein manuelles Tippen)
- ✅ Proper Logging via journalctl
- ✅ Health-Check Cron (alle 5 Min)
- ✅ Monitoring via Zabbix
Die Lösung: systemd Service
Schritt 1: Config + Credentials vorbereiten
OpenVPN-Configs gehören nach /etc/openvpn/client/.
# Config von ~/gw-deathstar.ovpn nach /etc/openvpn/client/ kopieren
cp ~/gw-deathstar.ovpn /etc/openvpn/client/gw-deathstar.conf
# Credentials-Datei erstellen
cat > /etc/openvpn/client/gw-deathstar.auth << EOF
luke.skywalker
your-password
EOF
chmod 600 /etc/openvpn/client/gw-deathstar.auth
# Config anpassen: auth-user-pass mit Datei
echo "auth-user-pass /etc/openvpn/client/gw-deathstar.auth" >> /etc/openvpn/client/gw-deathstar.conf
⚠️ Sicherheit: Die .auth Datei hat sensible Credentials! Permissions 600 (nur root lesbar) sind Pflicht.
Schritt 2: systemd Service aktivieren
OpenVPN kommt mit einem systemd Template openvpn-client@.service. Das @ Teil ist der Name deiner Config (ohne .conf).
# Service aktivieren (startet bei Boot)
systemctl enable openvpn-client@gw-deathstar
# Service starten
systemctl start openvpn-client@gw-deathstar
# Status prüfen
systemctl status openvpn-client@gw-deathstar
Der Service heißt openvpn-client@gw-deathstar weil die Config /etc/openvpn/client/gw-deathstar.conf heißt.
Schritt 3: Verifikation
# 1. Service läuft?
systemctl is-active openvpn-client@gw-deathstar
# Erwartung: active
# 2. tun0 Interface existiert?
ip addr show tun0
# Erwartung: inet 10.99.99.2/24
# 3. Routing zu internem Netz?
ip route | grep tun0
# Erwartung: 192.168.66.0/24 via 10.99.99.1 dev tun0
# 4. VPN-Gateway erreichbar?
ping -c3 10.99.99.1
# Erwartung: 3 packets transmitted, 3 received
# 5. Internes Netzwerk erreichbar?
ping -c3 192.168.66.1
# Erwartung: 3 packets transmitted, 3 received
Schritt 4: Auto-Reconnect testen
Der systemd Service hat eingebautes Auto-Reconnect:
# Kill die Verbindung
pkill -f "openvpn --config.*gw-deathstar"
# Warte 30s
sleep 30
# Service sollte neu gestartet sein
systemctl status openvpn-client@gw-deathstar
# Erwartung: active (running)
Die systemd-Unit hat standardmäßig Restart=on-failure und RestartSec=120s.
Schritt 5: Health-Check Cron (optional aber empfohlen)
Ein Cron-Job prüft regelmäßig ob der Service läuft und ob das Netz erreichbar ist.
# Script erstellen
cat > /usr/local/bin/openvpn-healthcheck.sh << 'EOF'
#!/bin/bash
set -euo pipefail
SERVICE="openvpn-client@gw-deathstar"
TUNNEL_IP="10.99.99.1"
INTERNAL_IP="192.168.66.1"
# 1. Service läuft?
if ! systemctl is-active --quiet "$SERVICE"; then
echo "$(date): $SERVICE not running, starting..."
systemctl start "$SERVICE"
exit 0
fi
# 2. tun0 existiert?
if ! ip link show tun0 &>/dev/null; then
echo "$(date): tun0 missing, restarting $SERVICE..."
systemctl restart "$SERVICE"
exit 0
fi
# 3. VPN-Gateway erreichbar?
if ! ping -c1 -W2 "$TUNNEL_IP" &>/dev/null; then
echo "$(date): $TUNNEL_IP unreachable, restarting $SERVICE..."
systemctl restart "$SERVICE"
exit 0
fi
# 4. Internes Netz erreichbar?
if ! ping -c1 -W2 "$INTERNAL_IP" &>/dev/null; then
echo "$(date): $INTERNAL_IP unreachable, restarting $SERVICE..."
systemctl restart "$SERVICE"
exit 0
fi
# Alles grün
exit 0
EOF
chmod +x /usr/local/bin/openvpn-healthcheck.sh
# Cron-Job (alle 5 Min)
echo "*/5 * * * * root /usr/local/bin/openvpn-healthcheck.sh >> /var/log/openvpn-healthcheck.log 2>&1" > /etc/cron.d/openvpn-healthcheck
Der Health-Check ist dein R2-D2 - er repariert die Verbindung bevor du überhaupt merkst dass sie tot war.
Monitoring mit Zabbix
Für Production-Umgebungen reicht ein Health-Check nicht - du willst sofort benachrichtigt werden wenn die Verbindung stirbt.
Items
| Item | Key | Interval | Beschreibung |
|---|---|---|---|
| Service Status | systemd.unit.info[openvpn-client@gw-deathstar.service,ActiveState] | 1m | Ist der Service active/inactive/failed? |
| Tunnel Gateway | net.tcp.service[icmppingsec,10.99.99.1] | 2m | VPN-Gateway per Ping erreichbar? |
| tun0 Interface | vfs.file.exists[/sys/class/net/tun0] | 1m | Existiert das tun0 Interface? |
Triggers
| Trigger | Severity | Expression |
|---|---|---|
| Service down | Disaster | last(...ActiveState)<>"active" |
| Tunnel unreachable | High | last(...icmppingsec...)=0 |
| tun0 missing | Warning | last(...vfs.file.exists...)=0 |
Trigger Dependencies: “Tunnel unreachable” und “tun0 missing” hängen von “Service down” ab - du willst nicht 3 Alerts für dasselbe Problem.
Troubleshooting: Wenn die Verbindung nicht funktioniert
Diagnose-Befehle
Wenn der Service nicht startet oder die Verbindung abbricht:
# 1. Service-Status prüfen
systemctl status openvpn-client@gw-deathstar
# Achte auf: "Active: failed" oder "Active: activating (auto-restart)"
# 2. Logs der letzten 50 Zeilen
journalctl -u openvpn-client@gw-deathstar -n 50
# 3. Logs in Echtzeit verfolgen
journalctl -u openvpn-client@gw-deathstar -f
# 4. Auth-Fehler prüfen
journalctl -u openvpn-client@gw-deathstar | grep -i "auth\|credential\|tls"
# 5. Netzwerk-Probleme prüfen
journalctl -u openvpn-client@gw-deathstar | grep -i "timeout\|unreachable\|connection"
Log-Beispiele
Healthy (funktioniert):
Feb 16 07:30:42 srv-r2d2 openvpn[1234]: Initialization Sequence Completed
Feb 16 07:30:42 srv-r2d2 openvpn[1234]: /sbin/ip addr add dev tun0 10.99.99.2/24
Feb 16 07:30:42 srv-r2d2 openvpn[1234]: /sbin/ip route add 192.168.66.0/24 via 10.99.99.1
Broken: Auth-Fehler (falsche Credentials):
Feb 16 07:32:15 srv-r2d2 openvpn[1235]: AUTH: Received control message: AUTH_FAILED
Feb 16 07:32:15 srv-r2d2 openvpn[1235]: SIGTERM received, process exiting
Fix: Prüfe /etc/openvpn/client/gw-deathstar.auth - Username/Password korrekt?
Broken: Connection Timeout (Firewall/Route-Problem):
Feb 16 07:33:20 srv-r2d2 openvpn[1236]: Connection reset, restarting
Feb 16 07:33:20 srv-r2d2 openvpn[1236]: TCP/UDP: Closing socket
Feb 16 07:33:25 srv-r2d2 openvpn[1236]: Connection timeout
Fix: Prüfe ob VPN-Server erreichbar ist: ping vpn.deathstar.lan oder telnet vpn.deathstar.lan 1194
Broken: Permissions (Datei nicht lesbar):
Feb 16 07:34:10 srv-r2d2 openvpn[1237]: Options error: --auth-user-pass fails with '/etc/openvpn/client/gw-deathstar.auth': Permission denied (errno=13)
Fix: chmod 600 /etc/openvpn/client/gw-deathstar.auth && chown root:root /etc/openvpn/client/gw-deathstar.auth
Häufige Probleme
| Problem | Symptom | Diagnose | Fix |
|---|---|---|---|
| Auth fehlschlägt | AUTH_FAILED in Logs | cat /etc/openvpn/client/gw-deathstar.auth | Credentials prüfen |
| tun0 nicht erstellt | ip addr show tun0 = not exist | journalctl ... | grep tun | Kernel-Modul tun laden: modprobe tun |
| Service auto-restart Loop | systemctl status zeigt “activating (auto-restart)” | journalctl -n 100 | Credentials/Config/Firewall prüfen |
| Route fehlt | ping 192.168.66.1 = no route | ip route | grep tun0 | In .conf: route 192.168.66.0 255.255.255.0 hinzufügen |
Migration: Step-by-Step
Du hast einen laufenden OpenVPN-Client in einer Screen-Session? So migrierst du:
1. Backup der Screen-Session Config
# Config sichern
cp ~/gw-deathstar.ovpn ~/gw-deathstar.ovpn.backup
# Aktuelles Setup dokumentieren (Route, IP, etc.)
ip addr show tun0 > ~/vpn-migration-state.txt
ip route | grep tun0 >> ~/vpn-migration-state.txt
2. Screen-Session stoppen
# Screen-Session finden
screen -ls
# Session terminieren
screen -X -S openvpn quit
# Verifizieren: tun0 sollte weg sein
ip addr show tun0
# Erwartung: Device "tun0" does not exist
3. systemd Service setup (siehe oben)
# Config + Credentials wie in Schritt 1-2 beschrieben
# ...
# Service starten
systemctl enable --now openvpn-client@gw-deathstar
4. Funktionstest
# Route Check
ip route | grep tun0
# Erwartung: 192.168.66.0/24 via 10.99.99.1 dev tun0
# Internal Network Test
ping -c3 192.168.66.1
ssh c3po@192.168.66.25 # Test SSH zu internem Host
5. Rollback-Plan (falls was schiefgeht)
# Service stoppen
systemctl stop openvpn-client@gw-deathstar
systemctl disable openvpn-client@gw-deathstar
# Alte Screen-Session wiederherstellen
screen -S openvpn
openvpn --config ~/gw-deathstar.ovpn.backup
# Ctrl+A+D
Lessons Learned
✅ Was gut funktioniert
- Auto-Reconnect: systemd startet den Service nach max. 120s neu - kein manueller Eingriff nötig
- Credentials in Datei:
auth-user-pass /path/to/fileeliminiert manuelle Passwort-Eingabe - Logging:
journalctl -u openvpn-client@gw-deathstar -fzeigt alle Events - Health-Check Cron: Fängt Edge-Cases wo systemd nicht greift (z.B. Service läuft aber Tunnel tot)
- Monitoring: Zabbix-Alerts per Telegram - du weißt SOFORT wenn was stirbt
⚠️ Gotchas
- Credentials-Permissions:
chmod 600ist Pflicht, sonst startet OpenVPN nicht - Config-Pfad: Muss
/etc/openvpn/client/NAME.confheißen, sonst findet systemd die Config nicht - Auth-User-Pass Zeile: Alte Config hatte
auth-user-passohne Pfad (für interaktive Eingabe) - das MUSS angepasst werden - DNS/Routing: Wenn der VPN-Server DNS pushed, kann das mit systemd-resolved kollidieren - evtl.
pull-filter ignore "dhcp-option DNS"in die Config
🚀 Bonus: Multi-VPN Setup
Du hast mehrere VPNs? Leg für jeden eine eigene Config an:
/etc/openvpn/client/
├── gw-deathstar.conf
├── gw-deathstar.auth
├── office-vpn.conf
└── office-vpn.auth
Start separate Services:
systemctl enable --now openvpn-client@gw-deathstar
systemctl enable --now openvpn-client@office-vpn
Jeder Service kriegt sein eigenes tun-Device (tun0, tun1, …).
Fazit
Screen-Sessions für Production-VPNs sind wie ein TIE-Fighter ohne Schild - cool, aber riskant. systemd Services mit Auto-Reconnect und Monitoring sind der X-Wing mit vollem Arsenal.
Vorher:
- 😰 Screen stirbt → VPN tot
- 😰 Reboot → manuelle Intervention nötig
- 😰 Tunnel down → du merkst es nach 2h
Nachher:
- ✅ Service stirbt → Auto-Restart nach max. 120s
- ✅ Reboot → Service startet automatisch
- ✅ Tunnel down → Zabbix-Alert nach 2 Min + Health-Check Restart nach 5 Min
May the Service be with you! 🚀
Dieser Artikel entstand nach der Migration von srv-r2d2 - von fragiler Screen-Session zu robustem systemd Service. Zero Downtime seit der Migration.