VPS Tutorials
Set Up an OpenVPN Server on a VPS (2026): Ubuntu 24.04, Easy-RSA, UFW and Client Configuration
Set up an OpenVPN server on an Ubuntu VPS: Easy-RSA certificates, UFW, NAT, client .ovpn configuration, connection verification and certificate revocation.

OpenVPN suits remote access scenarios that need compatibility with Windows, macOS, Linux, Android, iOS and routers. It is not necessarily faster than WireGuard, but its clients are mature and certificate permissions are clear, so it remains common for corporate intranet access, remote maintenance of home devices and public Wi-Fi encryption.
This article uses Ubuntu 22.04/24.04 as an example and sets up a certificate-authenticated server with OpenVPN and Easy-RSA from the system repositories. In the end you will have a .ovpn file that can be imported directly into OpenVPN Connect, and you will handle IP forwarding, UFW, NAT and client revocation.
| Number of users | Recommended configuration | Suitable scenarios |
|---|---|---|
| 1-5 users | 1 core / 1GB / 20GB SSD | SSH, intranet panels and light browsing |
| 5-20 users | 2 cores / 2GB / 40GB SSD | Office access, file services and everyday browsing |
| 20+ users | 4 cores / 4GB and up | Many concurrent clients; monitor bandwidth and connection counts |
OpenVPN encryption relies fairly heavily on single-core performance. The VPS also needs a public IPv4 address, and the virtualization environment must allow creating TUN devices. Before deploying, run:
test -c /dev/net/tun && echo "TUN available" || echo "TUN unavailable"
ip route show default
If /dev/net/tun does not exist, enable TUN/TAP in the VPS control panel or contact your provider.
First update the system and install the required software:
sudo apt update
sudo apt install -y openvpn easy-rsa ufw
openvpn --version | head -n 1
The official Ubuntu documentation uses Easy-RSA to create a private CA and issue separate certificates for the server and each client. Copy the working directory:
sudo make-cadir /etc/openvpn/easy-rsa
sudo -i
cd /etc/openvpn/easy-rsa
./easyrsa init-pki
./easyrsa build-ca
build-ca will ask you to set a CA password. This password is only used when issuing or revoking certificates; do not download pki/private/ca.key to ordinary clients.
The service cannot wait for a private key password at startup, so the server key uses nopass:
cd /etc/openvpn/easy-rsa
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
openvpn --genkey secret /etc/openvpn/ta.key
Copy the files the server needs and restrict private key permissions:
cp pki/ca.crt /etc/openvpn/
cp pki/issued/server.crt /etc/openvpn/
cp pki/private/server.key /etc/openvpn/
cp pki/dh.pem /etc/openvpn/
chmod 600 /etc/openvpn/server.key /etc/openvpn/ta.key
Create /etc/openvpn/server.conf:
port 1194
proto udp4
dev tun
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn-ipp.txt
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh.pem
tls-crypt /etc/openvpn/ta.key
remote-cert-tls client
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 1.0.0.1"
keepalive 10 120
persist-key
persist-tun
user nobody
group nogroup
explicit-exit-notify 1
verb 3
redirect-gateway means all client traffic goes through the VPS. If you only want to access the server or a home intranet, delete this line and push specific subnets instead, for example:
push "route 192.168.10.0 255.255.255.0"
Enable IPv4 forwarding:
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/50-enable-ipv4-forwarding.conf
sysctl -p /etc/sysctl.d/50-enable-ipv4-forwarding.conf
First check the name of the public network interface; do not simply assume it is eth0:
WAN_IF=$(ip route show default | awk '/default/ {print $5; exit}')
echo "$WAN_IF"
If UFW is already enabled on the VPS, allow SSH and OpenVPN first. If SSH uses a port other than 22, replace the rule accordingly:
ufw allow OpenSSH
ufw allow 1194/udp
Edit /etc/default/ufw and change the forwarding policy to:
DEFAULT_FORWARD_POLICY="ACCEPT"
Add the NAT block at the very top of the /etc/ufw/before.rules file, where eth0 must be replaced with the public network interface you just found:
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT
Confirm that the cloud platform security group also allows UDP 1194, then reload UFW:
ufw enable
ufw reload
ufw status verbose
Before enabling the firewall, be sure to keep your current SSH session open and confirm the SSH rules are correct. If you lock yourself out, see Self-rescue checklist when SSH is unreachable after enabling UFW on a VPS.
The official Ubuntu documentation uses the template service openvpn@配置文件名. Because the configuration file is /etc/openvpn/server.conf, the start command is:
systemctl enable --now openvpn@server
systemctl status openvpn@server --no-pager
ip addr show tun0
When all is well, the log shows Initialization Sequence Completed and creates 10.8.0.1:
journalctl -u openvpn@server -n 100 --no-pager
ss -lunp | grep 1194
Some Debian/Ubuntu packages place the server configuration in /etc/openvpn/server/server.conf, with the corresponding service name openvpn-server@server. If openvpn@server reports that the configuration cannot be found, run systemctl list-unit-files | grep openvpn to confirm which directory layout the current package uses.
Each device uses its own certificate; do not let a phone, computer and router share a single client private key:
cd /etc/openvpn/easy-rsa
./easyrsa gen-req phone nopass
./easyrsa sign-req client phone
Generate the single-file configuration /root/phone.ovpn, replacing YOUR_VPS_IP with the server's public IP or domain name:
cat > /root/phone.ovpn <<EOF
client
dev tun
proto udp4
remote YOUR_VPS_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
verb 3
<ca>
$(cat pki/ca.crt)
</ca>
<cert>
$(sed -ne '/BEGIN CERTIFICATE/,$p' pki/issued/phone.crt)
</cert>
<key>
$(cat pki/private/phone.key)
</key>
<tls-crypt>
$(cat /etc/openvpn/ta.key)
</tls-crypt>
EOF
chmod 600 /root/phone.ovpn
Download this file securely via SFTP and import it into OpenVPN Connect. Do not forward it through public cloud drives or chat groups, because .ovpn contains the client private key.
After the client connects, check in order:
ping 10.8.0.1
curl https://ifconfig.me
In full-tunnel mode, the second command should return the VPS public IP. On the server side, view client connections:
ip addr show tun0
journalctl -u openvpn@server -f
The main differences between OpenVPN and WireGuard are as follows:
| Comparison | OpenVPN | WireGuard |
|---|---|---|
| Client compatibility | Very broad, common in enterprise environments | Good support on new systems |
| Configuration method | CA and client certificates | Public/private keys and Peers |
| Performance | Higher encryption and userspace overhead | Usually lower latency and higher throughput |
| Permission revocation | Revoke an individual certificate | Delete the corresponding Peer |
If you value speed and simple configuration more, see Tutorial: Set Up a WireGuard VPN on a VPS.
If a phone or computer is lost, revoke the corresponding certificate immediately:
cd /etc/openvpn/easy-rsa
./easyrsa revoke phone
./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn/crl.pem
chmod 644 /etc/openvpn/crl.pem
Add the following to the server configuration:
crl-verify /etc/openvpn/crl.pem
Then restart the service:
systemctl restart openvpn@server
Confirm that UDP 1194 is allowed in both the system firewall and the cloud security group, and check whether the client's IP, port and proto match the server:
ss -lunp | grep 1194
journalctl -u openvpn@server -n 100 --no-pager
This is usually caused by IP forwarding, the NAT interface name or the UFW forwarding policy being wrong:
sysctl net.ipv4.ip_forward
ip route show default
grep DEFAULT_FORWARD_POLICY /etc/default/ufw
iptables -t nat -L POSTROUTING -n -v
Restart the service first, then look at the specific error:
systemctl restart openvpn@server
journalctl -u openvpn@server -xe --no-pager
Focus on certificate paths, file permissions and whether tls-crypt matches on both ends. Do not casually enable BF-CBC or disable certificate verification for compatibility with old clients; upgrade the client instead.
- TUN/TAP is available, the VPS public IP is stable, and UDP 1194 is allowed in the security group.
- The CA private key is stored only on the server or in an offline backup, and each device has its own certificate.
net.ipv4.ip_forward=1is in effect, and NAT uses the correct public network interface.- The client configuration was not transmitted through public channels, and file permissions are
600. - The service is set to start on boot, and the logs show no persistent TLS or routing errors.
- The certificate revocation steps are documented, and
/etc/openvpn/easy-rsa/pkiis backed up regularly.
The most error-prone part of an OpenVPN deployment is not certificate generation but the port, firewall and forwarding chain. First get the client able to reach 10.8.0.1, then troubleshoot the public egress; this quickly distinguishes TLS problems from NAT problems.