Small Bash CLI for managing Proton VPN OpenVPN configs with NetworkManager.
protonium-cli is for users who manually download Proton VPN free-tier
.ovpn files and keep them in: ~/.vpns
It imports those configs into NetworkManager, stores the VPN password as a
NetworkManager secret, connects without nmcli --ask, and can rotate servers
on a configurable interval with a user systemd timer. The default is 30 minutes.
This project is not affiliated with Proton AG.
~/.vpns/*.ovpn
|
v
protonium-cli
|
v
NetworkManager profile + VPN secret
|
v
nmcli connection up
|
v
systemd user timer rotates on configured interval
- User-local install.
- No custom daemon.
- Uses Bash,
nmcli, NetworkManager, and user systemd. - Global auto-rotation.
- Country-only auto-rotation.
- Configurable rotation interval.
- Health check with dead-server skip.
- Local connection history.
- Manual country or server lock.
- Manual mode pauses rotation until auto mode is enabled again.
- Startup reconnect support.
- Safe uninstall script.
Required:
bash
coreutils
findutils
util-linux
NetworkManager
nmcli
NetworkManager OpenVPN plugin
systemd user services
Note: package names may differ by distro:
Arch: networkmanager networkmanager-openvpn openvpn
Debian/Ubuntu: network-manager network-manager-openvpn openvpn
Fedora: NetworkManager NetworkManager-openvpn openvpn
./install.shInstalled files:
~/.local/bin/protonium-cli
~/.config/systemd/user/protonium-autoconnect.service
~/.config/systemd/user/protonium-rotate.service
~/.config/systemd/user/protonium-rotate.timer
Make sure ~/.local/bin is in PATH.
Put Proton VPN configs in ~/.vpns.
Expected names:
ca-free-33.protonvpn.udp.ovpn
nl-free-9.protonvpn.udp.ovpn
The filename must follow:
<country>-<server>.protonvpn.<udp|tcp>.ovpn
Invalid filenames fail fast with a message showing the expected format.
Then run:
protonium-cli setupCredentials are saved with 0600 permissions in:
~/.config/protonium-cli
protonium-cli list
protonium-cli autoPreview changes without touching NetworkManager, systemd, or saved state:
protonium-cli --dry-run auto NL
protonium-cli --dry-run --verbose syncRotate only one country:
protonium-cli auto NLChange the rotation interval:
protonium-cli set-interval 45Show recent connections and rotations:
protonium-cli history
protonium-cli history 50Lock one country:
protonium-cli manual CALock one server:
protonium-cli manual ca-free-33Enable startup reconnect and timer:
protonium-cli enableStop the VPN:
protonium-cli stopDisable automation:
protonium-cli disablesetup Save credentials and import profiles.
status Show connection, mode, pool, and systemd state.
list List configs found in ~/.vpns.
history [LIMIT] Show recent connection events.
sync Import all configs and refresh credentials.
auto Rotate across all configs.
auto <COUNTRY_CODE> Rotate only inside one country.
country <CODE> Alias for auto <CODE>.
set-interval <MIN> Set rotation interval in whole minutes.
manual <CODE> Pick one server from a country and pause rotation.
manual <SERVER> Lock to one exact server and pause rotation.
stop Disconnect the active Protonium VPN.
enable Enable startup reconnect and rotation.
disable Disable startup reconnect and rotation.
Global options:
--dry-run Show planned changes without modifying system state.
--verbose, -v Print debug details while running.
auto
Use every config in ~/.vpns.
auto NL
Use only NL configs.
manual CA
Choose one CA server and stay there.
manual ca-free-33
Lock to ca-free-33 and stay there.
Manual mode always pauses rotation. Run protonium-cli auto to rotate again.
Connection events are appended to:
~/.local/state/protonium-cli/history.tsv
protonium-cli history shows the latest 20 entries by default. The log includes
the timestamp, action, mode, pool, country, server, and NetworkManager
connection name. Failed connection attempts and failed health checks are logged
as connect-fail and health-fail.
After NetworkManager reports a VPN connection is up, Protonium runs:
nmcli networking connectivity checkThis uses NetworkManager's built-in unauthenticated connectivity probe. No extra account, token, or third-party API is required.
If the check reports no usable internet, Protonium marks that server as failed
for the current run and tries another server from the same pool. If
NetworkManager reports unknown, Protonium skips the health gate to avoid
blocking systems where connectivity checking is disabled.
./uninstall.shDefault uninstall:
- disables user systemd units
- disconnects active Protonium VPNs
- removes imported Protonium NetworkManager profiles
- removes
~/.local/bin/protonium-cli - removes Protonium config and state
- keeps
~/.vpns
Delete downloaded VPN configs too:
./uninstall.sh --purge-vpnsOther options:
--yes
--keep-nm
--keep-config
protonium-cli status
systemctl --user status protonium-rotate.timer
journalctl --user -u protonium-rotate.service
protonium-cli syncMIT. See LICENSE.
Built with Codex. Designed and maintained by me.