Skip to content

Running as a Service

Set up rVPN server to start automatically on boot and restart on failure.


Create the service file:

Terminal window
sudo nano /etc/systemd/system/rvpn-server.service
[Unit]
Description=rVPN Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/rvpn-server -c /etc/rvpn/server.toml
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
# Redirect logs to journal
StandardOutput=journal
StandardError=journal
SyslogIdentifier=rvpn-server
[Install]
WantedBy=multi-user.target

Enable and start:

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable rvpn-server
sudo systemctl start rvpn-server

Check status:

Terminal window
sudo systemctl status rvpn-server

View logs:

Terminal window
sudo journalctl -u rvpn-server -f

ActionCommand
Startsudo systemctl start rvpn-server
Stopsudo systemctl stop rvpn-server
Restartsudo systemctl restart rvpn-server
View logssudo journalctl -u rvpn-server -f
Disable autostartsudo systemctl disable rvpn-server

The server does not support systemctl reload — the process has to restart to pick up config or certificate changes. Use restart where you might reach for reload elsewhere.


If you’re using the built-in [server.acme] block (Server Quick Start step 3), there is nothing to configure here — renewal is driven by a background task inside rvpn-server, uses the same :443 listener for the challenge, and hot-swaps the fresh cert into the in-memory resolver without dropping connections. Skip this section.

If instead you’re pointing tls_cert_file / tls_key_file at a certbot-issued cert (BYO cert mode), add a deploy hook to restart rVPN when the certificate renews — the server can’t reload a new cert without restarting:

Terminal window
sudo nano /etc/letsencrypt/renewal-hooks/deploy/rvpn-reload.sh
#!/bin/bash
systemctl restart rvpn-server
Terminal window
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/rvpn-reload.sh

Test the renewal process:

Terminal window
sudo certbot renew --dry-run

Create /usr/local/etc/rc.d/rvpn_server:

#!/bin/sh
# PROVIDE: rvpn_server
# REQUIRE: NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="rvpn_server"
rcvar="rvpn_server_enable"
command="/usr/local/bin/rvpn-server"
command_args="-c /usr/local/etc/rvpn/server.toml"
pidfile="/var/run/rvpn-server.pid"
load_rc_config $name
run_rc_command "$1"
Terminal window
chmod +x /usr/local/etc/rc.d/rvpn_server
echo 'rvpn_server_enable="YES"' >> /etc/rc.conf
service rvpn_server start

If running in TUN mode (full-tunnel VPN), the server must be configured as a NAT gateway before starting the service.

Terminal window
# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
# Configure NAT (replace eth0 with your public interface; -s should match [server.network].dhcp_range)
sudo iptables -t nat -A POSTROUTING -s 10.200.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT

Make these persistent across reboots:

Terminal window
# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save
# RHEL/CentOS
sudo service iptables save

Add to /etc/rc.conf:

Terminal window
gateway_enable="YES"
firewall_enable="YES"
firewall_type="OPEN"
natd_enable="YES"
natd_interface="vtnet0" # your public interface

macOS does not support server-side TUN NAT. Use SOCKS5 mode or a Linux VM for TUN mode servers.


AspectTUN ModeSOCKS5 Mode
NAT requiredYes (server-side)No (client-side relay)
Traffic routingAll apps, full tunnelPer-application
Server setupIP forwarding + NAT rulesStandard VPN server

See TUN Mode for complete TUN mode setup documentation.