Skip to content

Yujilik/pvpnwrapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 

Repository files navigation

ProtonVPN CLI on a Headless VPS (SSH-safe)

ProtonVPN's CLI reroutes all traffic through the VPN tunnel, which kills your SSH session. The pvpn.sh wrapper adds a routing rule that keeps SSH traffic on the real interface so your session survives.

This guide covers a fresh Ubuntu VPS setup.


1. Install ProtonVPN CLI

Add the Proton repo and install:

# Add Proton's apt repository
wget https://repo2.protonvpn.com/debian/dists/stable/main/binary-all/protonvpn-stable-release_1.0.8_all.deb
sudo dpkg -i protonvpn-stable-release_1.0.8_all.deb
sudo apt update

# Install the CLI
sudo apt install proton-vpn-cli

2. Install the patched API core

The stock proton-vpn-api-core has issues on headless servers (kill switch errors, disconnect timeouts). The patched fork fixes these.

cd ~/GitTools  # or wherever you keep repos
git clone https://github.com/Yujilik/python-proton-vpn-api-core
cd python-proton-vpn-api-core
git checkout stable
sudo pip install -e . --break-system-packages

This overrides the apt-installed python3-proton-vpn-api-core with the local editable install. Future git pull updates apply immediately (no reinstall needed).

3. Disable kill switch

The kill switch relies on NetworkManager GUI integration that doesn't exist on a headless server. It must be turned off:

protonvpn config set kill-switch off

4. Sign in

protonvpn signin your@proton.me

You'll be prompted for your password (and 2FA if enabled).

5. Set up the pvpn wrapper

Copy or symlink pvpn.sh and make it available in your shell:

# Option A: alias (add to ~/.zshrc or ~/.bashrc)
alias pvpn="$HOME/GitTools/RandomScripts/Utilities/pvpn.sh"

# Option B: symlink
ln -s ~/GitTools/RandomScripts/Utilities/pvpn.sh ~/bin/pvpn
chmod +x ~/GitTools/RandomScripts/Utilities/pvpn.sh

Reload your shell (source ~/.zshrc) and you're ready.


Usage

pvpn connect [country]    Connect (auto-protects SSH)
pvpn disconnect           Disconnect and restore routing
pvpn reconnect [country]  Disconnect + reconnect (switch servers)
pvpn status               Show connection status + public IP
pvpn list                 List available countries

Short flags:

pvpn -c [country]         Same as connect
pvpn -dc                  Same as disconnect
pvpn -rc [country]        Same as reconnect
pvpn -s                   Same as status

Examples

pvpn -c jp          # Connect to Japan
pvpn -c us          # Connect to US
pvpn -c germany     # Full country names work too
pvpn -rc nl         # Switch to Netherlands without dropping SSH
pvpn -dc            # Disconnect
pvpn -s             # Check status + public IP

How it works

Before calling protonvpn connect, the wrapper:

  1. Detects your SSH client IP from $SSH_CLIENT
  2. Adds a host route for that IP via the real gateway/interface
  3. Adds a policy rule so replies from the VPS IP use the main routing table

This keeps SSH traffic off the VPN tunnel. On disconnect, the routes are cleaned up.

Troubleshooting

TimeoutError on connect -- The CLI's event timeout might be too short. Check /usr/lib/python3/dist-packages/proton/vpn/cli/core/controller.py and look for timeout=10 in the _wait_for_event function. Increase it to 60. Note: this file is owned by the apt package and resets on updates.

Kill switch errors -- Make sure kill switch is off: protonvpn config set kill-switch off

"Server list is outdated" -- Normal on first connect or after a while. The CLI fetches the latest server list from Proton's API. Takes a few seconds.

SSH drops on connect -- You ran protonvpn connect directly instead of using the pvpn wrapper. Reboot the VPS from your provider's console, or wait for the VPN to timeout, then reconnect.

About

A wrapper for headless servers so you don't get dropped every time you switch servers.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages