# Proton VPN pe un VPS fără interfață grafică

**URL:** <https://forum.linuxromania.ro/t/proton-vpn-pe-un-vps-fara-interfata-grafica/91>\
**Category:** Wiki (experiment)\
**Tags:** tutorial, server, vps, vpn, protonvpn\
**Created:** [septembrie 22, 2026, 6:39am UTC](https://forum.linuxromania.ro/t/proton-vpn-pe-un-vps-fara-interfata-grafica/91 "2026-09-22T06:39:51Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![ThinkRoot](https://forum.linuxromania.ro/user_avatar/forum.linuxromania.ro/thinkroot/32/8_2.png) [@ThinkRoot](https://forum.linuxromania.ro/u/ThinkRoot)\
**Post date:** [septembrie 22, 2026, 6:39am UTC](https://forum.linuxromania.ro/t/proton-vpn-pe-un-vps-fara-interfata-grafica/91/1 "2026-09-22T06:39:51Z")

</div>

Dacă ai încercat vreodată să instalezi un VPN pe un server Linux fără interfață grafică și ai urmat un tutorial care îți arăta o fereastră cu buton de connect, știi deja că ceva nu se potrivește. Aplicațiile GUI pentru VPN sunt construite cu un utilizator în față: cineva care se uită la o iconiță în system tray, care dă click pe reconect când tunelul cade, care e prezent. Un VPS nu are nimic din astea. Pornește singur, rulează nesupravegheat, și dacă VPN-ul cade la 3 noaptea, nimeni nu apasă nimic.

Articolul ăsta acoperă tot ce ai nevoie ca tunelul VPN să fie fiabil pe un server headless: de ce CLI-ul e singura alegere logică, cum îl integrezi cu systemd, cum verifici că traficul chiar trece prin tunel (nu doar că serviciul rulează), cum adaugi un watchdog care îl repornește dacă cade, cum configurezi killswitch-ul, și ce faci când rulezi containere Docker alături de VPN.

## De ce nu funcționează GUI-ul pe un server headless

O aplicație grafică pentru VPN pornește un proces care se atașează la o sesiune de display. Pe un server fără X11 sau Wayland, sesiunea aia nu există. Unele aplicații GUI încearcă să pornească oricum și eșuează în tăcere, altele cer explicit un display și refuză să ruleze. Nici una dintre variante nu e utilă.

Dar problema mai profundă nu e că „nu pornește” - e că chiar dacă ai reuși cumva să o pornești, GUI-ul e proiectat greșit pentru cazul de utilizare al unui server. Iată de ce:

Un client GUI gestionează starea conexiunii vizual. Când tunelul cade, îți afișează un mesaj și așteptă să dai click. Nu există un mecanism standard prin care un script extern să detecteze starea și să reacționeze. Exit code-ul procesului nu reflectă starea conexiunii VPN, ci doar dacă aplicația rulează sau nu - două lucruri complet diferite.

CLI-ul funcționează opus: fiecare comandă returnează un exit code care spune exact ce s-a întâmplat, logurile merg la journald și pot fi parsate, iar starea conexiunii poate fi interogată programatic. Asta e tot ce ai nevoie ca să construiești ceva fiabil.

## Ce ai nevoie înainte să începi

Ai nevoie de un cont Proton VPN. Planul gratuit funcționează pentru teste, dar pentru un server în producție care rulează continuu vei ajunge repede la limitele lui: serverele gratuite sunt partajate și limitate ca lățime de bandă, și nu ai acces la Secure Core sau la serverele dedicate. Pentru infrastructură serioasă, Proton Plus e practic obligatoriu.

Distribuția nu contează foarte mult - tutorialul funcționează pe orice distribuție bazată pe Debian sau Red Hat. Comenzile de instalare diferă puțin, dar restul e identic.

Ai nevoie de acces root sau sudo pe server, și de conexiune SSH activă.

## Instalarea Proton VPN CLI

Proton oferă un script oficial de instalare și pachete pentru distribuțiile principale. Nu instala din pip sau din alte surse terțe - versiunile neoficiale rămân în urmă cu actualizările de securitate.

**Pe distribuții bazate pe Debian/Ubuntu:**

```auto
wget https://repo.protonvpn.com/debian/dists/stable/main/binary-all/protonvpn-stable-release_1.0.3-3_all.deb
sudo dpkg -i protonvpn-stable-release_1.0.3-3_all.deb
sudo apt update
sudo apt install proton-vpn-gnome-desktop

```

Numele pachetului conține „gnome” dar nu instalează interfața grafică pe un sistem headless - instalează doar clientul și dependențele necesare. Poți verifica ce se instalează cu `apt-cache show proton-vpn-gnome-desktop` înainte.

**Pe distribuții bazate pe Red Hat/Fedora:**

```auto
sudo dnf install https://repo.protonvpn.com/fedora-$(rpm -E %fedora)/devel/noarch/protonvpn-stable-release-1.0.1-1.noarch.rpm
sudo dnf install proton-vpn-gnome-desktop

```

După instalare, verifici că ai comanda disponibilă:

```auto
protonvpn-cli --version

```

## Autentificarea

Autentificarea se face o singură dată și credențialele sunt salvate local. Rulezi:

```auto
protonvpn-cli login <username>

```

Unde `<username>` e username-ul contului tău Proton VPN, nu adresa de email. Ți se va cere parola. Credențialele sunt stocate în `~/.local/share/protonvpn/` cu permisiuni restrictive.

Un punct important pe care puțini tutoriale îl menționează: dacă rulezi CLI-ul ca root (ceea ce vei face pentru integrarea cu systemd), autentificarea trebuie făcută și ca root:

```auto
sudo protonvpn-cli login <username>

```

Credențialele pentru root și pentru userul tău normal sunt separate. Dacă te autentifici ca user normal și apoi încerci să conectezi ca root, vei primi o eroare despre credențiale lipsă.

## Prima conexiune manuală

Înainte să automatizezi orice, testezi că funcționează manual:

```auto
sudo protonvpn-cli connect --fastest

```

Flag-ul `--fastest` selectează automat serverul cu cea mai bună latență din lista disponibilă. Alte opțiuni utile:

```auto
sudo protonvpn-cli connect --cc RO # server în România
sudo protonvpn-cli connect --cc DE # server în Germania
sudo protonvpn-cli connect -p WireGuard # forțează protocolul WireGuard
sudo protonvpn-cli connect -p OpenVPN-UDP # forțează OpenVPN pe UDP

```

WireGuard e în general mai rapid și mai stabil pe servere - are overhead mai mic și reconectarea după pierderi de rețea e mai rapidă decât OpenVPN.

Verifici starea conexiunii:

```auto
sudo protonvpn-cli status

```

Ar trebui să vezi ceva de genul:

```auto
Status: Connected
Server: DE#123
Country: Germany
Protocol: WireGuard
IP: 185.xxx.xxx.xxx

```

Deconectezi cu:

```auto
sudo protonvpn-cli disconnect

```

## Integrarea cu systemd

Rularea manuală nu e ce vrei pe un server. Vrei ca tunelul să pornească automat la boot, înainte de orice alt serviciu care depinde de el, și să fie gestionat de systemd la fel ca orice alt serviciu.

Creezi fișierul de serviciu:

```auto
sudo nano /etc/systemd/system/protonvpn.service

```

Conținutul:

```auto
[Unit]
Description=Proton VPN
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/protonvpn-cli connect --fastest -p WireGuard
ExecStop=/usr/bin/protonvpn-cli disconnect
RemainAfterExit=true
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

```

Câteva explicații pentru că fiecare linie contează:

`Type=oneshot` înseamnă că systemd consideră serviciul pornit după ce comanda din `ExecStart` termină execuția, nu în timpul ei. E corect pentru CLI-ul Proton VPN, care se conectează și iese - nu rămâne ca proces în background. Dacă ai folosi `Type=simple`, systemd ar considera serviciul căzut imediat ce comanda se termină.

`RemainAfterExit=true` îi spune lui systemd să considere serviciul activ chiar după ce procesul din `ExecStart` a terminat. Fără asta, `systemctl status protonvpn` ar raporta „inactive” imediat după conectare, chiar dacă tunelul e activ.

`After=network-online.target` și `Wants=network-online.target` se asigură că serviciul pornește doar după ce rețeaua e funcțională, nu imediat la boot când interfețele s-ar putea să nu fie încă ridicate. Diferența dintre `Wants` și `Requires`: `Wants` înseamnă că încearcă să pornească `network-online.target` dacă nu e deja activ, dar nu eșuează dacă nu reușește. `Requires` ar bloca pornirea dacă `network-online.target` eșuează.

Activezi și pornești serviciul:

```auto
sudo systemctl daemon-reload
sudo systemctl enable protonvpn
sudo systemctl start protonvpn

```

Verifici starea:

```auto
sudo systemctl status protonvpn

```

Și te uiți la log-uri:

```auto
sudo journalctl -u protonvpn -f

```

Flag-ul `-f` urmărește log-urile în timp real, util pentru debugging.

## Verificarea că traficul chiar trece prin tunel

Asta e partea pe care aproape nimeni nu o explică și care cauzează cele mai multe probleme silențioase. `systemctl status protonvpn` îți spune că serviciul e activ. Nu îți spune dacă traficul tău efectiv iese prin tunelul VPN.

Cele două întrebări sunt diferite. Tunelul poate fi „activ” din perspectiva systemd, dar traficul poate trece pe lângă el dacă ceva e greșit cu rutarea.

Verifici cu:

```auto
curl --interface tun0 https://api.ipify.org

```

`--interface tun0` forțează curl să folosească interfața de rețea a tunelului VPN. Dacă comanda returnează un IP, compari cu IP-ul real al serverului tău:

```auto
curl https://api.ipify.org

```

Dacă cele două IP-uri sunt diferite, traficul trece prin VPN. Dacă sunt identice, ai o problemă de rutare.

`tun0` e numele implicit al interfeței pentru OpenVPN. Pentru WireGuard, interfața se numește de obicei `proton0` sau `wg0`. Verifici cu:

```auto
ip link show

```

Și cauți interfața care nu existau înainte de conectare.

O altă verificare utilă e să te uiți la tabelul de rutare:

```auto
ip route show

```

Ar trebui să vezi o rută default sau specific routes care trimit traficul prin interfața tunelului. Dacă ruta default (`0.0.0.0/0`) indică spre interfața originală a serverului (de obicei `eth0` sau `ens3`), nu spre tunel, traficul nu trece prin VPN.

## Killswitch: ce e și cum îl configurezi

Killswitch-ul e o funcție de securitate care blochează tot traficul de rețea dacă VPN-ul se deconectează. Fără killswitch, dacă tunelul cade, conexiunile tale continuă să meargă direct - cu IP-ul real al serverului, fără protecție. Dacă rulezi ceva care necesită ca traficul să treacă obligatoriu prin VPN (scraping, acces la resurse geo-restricționate, sau pur și simplu nu vrei să expui IP-ul real), killswitch-ul e esențial.

CLI-ul Proton VPN are killswitch integrat. Îl activezi cu:

```auto
sudo protonvpn-cli config --killswitch on

```

Și verifici că e activ:

```auto
sudo protonvpn-cli config --list

```

Când killswitch-ul e activ și VPN-ul cade, sistemul nu mai are acces la rețea până la reconectare. Asta înseamnă că și accesul SSH poate fi blocat dacă VPN-ul cade - sau mai precis, sesiunile SSH existente rămân active (TCP e stabilit), dar nu poți deschide sesiuni noi.

**Atenție importantă:** Înainte să activezi killswitch-ul pe un server de producție la care accesul SSH e singurul mod de a-l administra, asigură-te că ai un mecanism de recuperare. Unii provideri de VPS oferă consolă de acces din panoul de control, independentă de rețea. Verifici că ai acces la ea înainte.

O alternativă mai controlată decât killswitch-ul integrat e să implementezi regulile de firewall manual cu iptables sau nftables, unde ai mai mult control:

```auto
# Permite trafic pe interfața de loopback
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT

# Permite trafic pe interfața VPN (WireGuard)
sudo iptables -A INPUT -i proton0 -j ACCEPT
sudo iptables -A OUTPUT -o proton0 -j ACCEPT

# Permite traficul de autentificare VPN (portul 51820 pentru WireGuard)
sudo iptables -A OUTPUT -p udp --dport 51820 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 51820 -j ACCEPT

# Permite SSH pe interfața reală (ca să nu te blochezi)
sudo iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
sudo iptables -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT

# Blochează tot restul
sudo iptables -A INPUT -j DROP
sudo iptables -A OUTPUT -j DROP

```

Salvezi regulile cu `iptables-save > /etc/iptables/rules.v4` și le incarci la boot cu pachetul `iptables-persistent`.

## Watchdog: ce se întâmplă când tunelul cade

Chiar cu systemd și `Restart=on-failure`, există scenarii în care tunelul cade și systemd nu știe că a căzut. `Type=oneshot` cu `RemainAfterExit=true` înseamnă că din perspectiva systemd serviciul e „activ” atâta timp cât nu i-ai spus explicit că nu e. Dacă procesul de tunel se închide neașteptat fără să treacă printr-un exit code detectabil, systemd rămâne cu impresia că totul e bine.

Un watchdog simplu rezolvă asta: un script care rulează periodic, verifică dacă tunelul e funcțional, și dacă nu e, îl repornește.

Creezi scriptul:

```auto
sudo nano /usr/local/bin/protonvpn-watchdog.sh

```

Conținutul:

```auto
#!/bin/bash

LOG_TAG="protonvpn-watchdog"

# Verifică dacă interfața tunelului există
if ! ip link show tun0 &>/dev/null && ! ip link show proton0 &>/dev/null; then
    logger -t "$LOG_TAG" "Interfata VPN nu gasita. Incerc reconectarea..."
    systemctl restart protonvpn
    sleep 10

    # Verifică din nou după reconectare
    if ! ip link show tun0 &>/dev/null && ! ip link show proton0 &>/dev/null; then
        logger -t "$LOG_TAG" "Reconectarea a esuat."
    else
        logger -t "$LOG_TAG" "Reconectare reusita."
    fi
else
    # Interfața există, verifică dacă traficul chiar trece
    REAL_IP=$(curl -s --max-time 5 https://api.ipify.org)
    VPN_IP=$(curl -s --max-time 5 --interface tun0 https://api.ipify.org 2>/dev/null || \
             curl -s --max-time 5 --interface proton0 https://api.ipify.org 2>/dev/null)

    if [-z "$VPN_IP"]; then
        logger -t "$LOG_TAG" "Nu pot obtine IP prin tunel. Incerc reconectarea..."
        systemctl restart protonvpn
    elif ["$REAL_IP" = "$VPN_IP"]; then
        logger -t "$LOG_TAG" "IP real ($REAL_IP) = IP VPN ($VPN_IP). Traficul nu trece prin tunel. Reconect..."
        systemctl restart protonvpn
    fi
fi

```

Îi dai permisiuni de execuție:

```auto
sudo chmod +x /usr/local/bin/protonvpn-watchdog.sh

```

Adaugi un cron job care rulează la fiecare 5 minute:

```auto
sudo crontab -e

```

Adaugi linia:

```auto
*/5 * * * * /usr/local/bin/protonvpn-watchdog.sh

```

Log-urile watchdog-ului merg în syslog și le poți vedea cu:

```auto
sudo journalctl -t protonvpn-watchdog

```

O variantă mai elegantă decât cron e să creezi un timer systemd, dar pentru un watchdog simplu ca ăsta cron e suficient și mai ușor de înțeles.

## Proton VPN și Docker: ce trebuie să știi

Containerele Docker au propria stivă de rețea și implicit nu moștenesc rutarea VPN a hostului. Asta înseamnă că dacă ai containere care fac request-uri HTTP, acele request-uri ies direct pe interfața reală a serverului, nu prin VPN - chiar dacă VPN-ul e activ pe host.

Există două abordări principale, fiecare cu trade-off-urile ei:

### Varianta 1: Rulezi containerele în network mode host

```auto
# docker-compose.yml
services:
  aplicatia-mea:
    image: imaginea-mea
    network_mode: host

```

Cu `network_mode: host`, containerul folosește direct stiva de rețea a hostului, inclusiv rutarea VPN. E simplu, dar pierde izolarea de rețea pe care Docker o oferă în mod normal - containerul vede și poate accesa toate interfețele hostului.

### Varianta 2: Forțezi traficul containerelor prin interfața VPN

Adaugi o regulă iptables care marchează și reroutează traficul din subnet-ul Docker:

```auto
# Subnet-ul implicit Docker e 172.17.0.0/16
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o tun0 -j MASQUERADE

```

Sau pentru WireGuard:

```auto
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o proton0 -j MASQUERADE

```

Asta face ca tot traficul care iese din containere să fie mascaradat prin interfața VPN. Dezavantajul e că dacă VPN-ul cade și nu ai killswitch, traficul containerelor revine pe interfața reală.

### Varianta 3: Un container dedicat VPN pentru alte containere

Există imagini Docker care rulează Proton VPN (sau orice alt VPN cu OpenVPN/WireGuard) și pot acționa ca gateway pentru alte containere. Containerele care au nevoie de VPN se conectează la containerul VPN prin `network_mode: container:vpn-container`.

```auto
services:
  vpn:
    image: qmcgaw/gluetun
    cap_add:
      - NET_ADMIN
    environment:
      - VPN_SERVICE_PROVIDER=protonvpn
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=<cheia-ta>
      - SERVER_COUNTRIES=Germany

  aplicatia-mea:
    image: imaginea-mea
    network_mode: "container:vpn"
    depends_on:
      - vpn

```

Această abordare e cea mai curată pentru izolarea containerelor care necesită VPN față de cele care nu au nevoie.

Verifici că un container trimite trafic prin VPN:

```auto
docker exec -it <container-name> curl https://api.ipify.org

```

Și compari rezultatul cu IP-ul real al serverului.

## Probleme comune și cum le rezolvi

**„protonvpn-cli: command not found” când rulezi ca root**

CLI-ul poate fi instalat în `/usr/local/bin/` care e în PATH pentru userul normal dar nu pentru root. Verifici cu `which protonvpn-cli` ca user normal, și folosești calea completă în fișierul de serviciu systemd.

**Serviciul pornește dar `systemctl status` arată „failed”**

Cel mai probabil cauza e că CLI-ul nu găsește credențialele. Asigură-te că ai rulat `sudo protonvpn-cli login` (cu sudo, nu ca user normal). Verifici log-urile cu `sudo journalctl -u protonvpn -n 50`.

**Tunelul cade des și watchdog-ul reconectează frecvent**

Poate fi o problemă cu serverul ales sau cu protocolul. Încearcă să forțezi WireGuard în loc de OpenVPN cu `-p WireGuard` în ExecStart. WireGuard e semnificativ mai stabil pe conexiuni instabile.

**SSH se blochează după activarea killswitch-ului**

Dacă killswitch-ul blochează SSH, ai nevoie de acces la consola VPS-ului din panoul de control al providerului. Dezactivezi killswitch-ul din consolă cu `sudo protonvpn-cli config --killswitch off` și te reconectezi prin SSH. Pe viitor, folosești varianta cu iptables manuală care permite explicit SSH.

**Containerele Docker nu trec prin VPN**

Verifici interfața VPN cu `ip link show` și te asiguri că folosești numele corect (`tun0` vs `proton0`) în regulile iptables. Dacă ai folosit o imagine gluetun sau similară, verifici că variabilele de mediu sunt corecte.

## Cum arată o configurare completă

Ca să rezum, pe un server corect configurat ai:

- **`/etc/systemd/system/protonvpn.service`** - pornește tunelul la boot, înainte de alte servicii
- **`/usr/local/bin/protonvpn-watchdog.sh`** - verifică la fiecare 5 minute că traficul chiar trece prin tunel
- **Killswitch activ** (sau reguli iptables echivalente) - asigură că nu există scurgeri de trafic dacă VPN-ul cade
- **Regulile iptables pentru Docker** - dacă rulezi containere care au nevoie de VPN

Testul final: repornești serverul, aștepți 30 de secunde și verifici `curl ``https://api.ipify.org`. Dacă returnează un IP diferit față de IP-ul real al serverului, totul funcționează corect.

Un VPN pe un server headless nu e complicat dacă înțelegi că e o problemă de process management, nu de interfață. Odată ce ai pus piesele la locul lor - CLI autentificat ca root, serviciu systemd cu dependențele corecte, watchdog care verifică traficul real nu doar starea serviciului - rulează singur fără să mai ai nevoie să te gândești la el.
