Virtual Private Networks (VPNs) are a cornerstone of modern cybersecurity, letting remote users tunnel safely through public networks. OpenVPN remains a favorite because it is open‑source, highly configurable, and works on almost any platform. In this guide we’ll walk through every step required to set up a hardened OpenVPN server on a fresh Linux box, generate client certificates, and verify that the tunnel is truly secure. By the end you’ll have a production‑ready VPN that you can trust for remote work, site‑to‑site links, or private browsing.
What You’ll Need
- A Linux server (Ubuntu 22.04, Debian 12, or CentOS 9) with a static public IP address.
- Root or sudo privileges on the server.
- Basic familiarity with Linux command line and networking concepts.
- A client device (Windows, macOS, Linux, iOS, or Android) for testing.
- Port 1194 UDP open in your firewall and forwarded if the server sits behind a NAT.
Step 1: Install OpenVPN and Easy‑RSA
First, update the package index and install the OpenVPN daemon together with Easy‑RSA, the tool we’ll use to build our own Public Key Infrastructure (PKI). On Ubuntu/Debian run:
sudo apt update && sudo apt install -y openvpn easy-rsa
On CentOS/RHEL the equivalents are:
sudo dnf install -y epel-release sudo dnf install -y openvpn easy-rsa
After installation, verify the binaries are present:
which openvpn easy-rsa --version
If you see the paths printed, you’re ready to move on.
Step 2: Set Up the PKI Directory
Easy‑RSA works out of a dedicated folder. Create one in /etc/openvpn and initialise the PKI:
sudo make-cadir /etc/openvpn/easy-rsa cd /etc/openvpn/easy-rsa sudo ./easyrsa init-pki
Next, edit the vars file (optional but recommended) to set default values for your certificates, such as country, organization, and email. Use your favourite editor:
sudo nano vars
Look for lines like set_var EASYRSA_REQ_COUNTRY "US" and adjust them to reflect your environment. Save and exit.
Step 3: Build the Certificate Authority and Server Keys
Generate the root CA. This will sign all server and client certificates, so keep the private key secure.
sudo ./easyrsa build-ca nopass
You’ll be prompted for a Common Name; use something like MyVPN-CA. Next, create the server certificate, key, and Diffie‑Hellman parameters in a single step:
sudo ./easyrsa build-server-full server nopass
OpenVPN also needs a TLS‑auth key to protect against port‑scanning attacks. Create it with:
openvpn --genkey --secret ta.key
Move the generated files to the OpenVPN directory:
sudo cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key ta.key /etc/openvpn/
At this point you have a CA, a server certificate, a server private key, and a shared TLS‑auth key.
Step 4: Configure the OpenVPN Server
Copy the example server configuration to /etc/openvpn/server.conf and edit it to match our security goals.
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/ gunzip /etc/openvpn/server.conf.gz sudo nano /etc/openvpn/server.conf
Key changes to make:
- Uncomment
port 1194and setproto udp(UDP is faster for most traffic). - Set
dev tunfor a routed VPN. - Point to the certificate files we just copied:
ca ca.crt cert server.crt key server.key tls-auth ta.key 0
Enable strong encryption and forward traffic:
cipher AES-256-CBC auth SHA256 user nobody group nogroup persist-key persist-tun
Enable client‑to‑client communication if you need devices to see each other:
client-to-client
Finally, push a DNS server and a default route to clients:
push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 1.1.1.1" push "dhcp-option DNS 8.8.8.8"
Save the file. The configuration now tells OpenVPN to use our keys, encrypt with AES‑256, and hand out IP addresses from the 10.8.0.0/24 pool (default).
Step 5: Adjust the Firewall and Enable IP Forwarding
Linux must forward packets between the VPN tunnel and the external network. Enable it permanently:
sudo sysctl -w net.ipv4.ip_forward=1 sudo bash -c "echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf"
Now configure the firewall. If you use ufw (Ubuntu default):
sudo ufw allow 1194/udp sudo ufw enable
Set up NAT so VPN client traffic appears to come from the server’s public IP:
sudo ufw route allow in on tun0 out on eth0 sudo ufw route allow in on eth0 out on tun0 sudo ufw after routing allow in on tun0 out on eth0
For firewalld (CentOS/RHEL) use:
sudo firewall-cmd --add-service=openvpn --permanent sudo firewall-cmd --add-masquerade --permanent sudo firewall-cmd --reload
If you rely on iptables directly, the NAT rule looks like:
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
Replace eth0 with the name of your external interface (check with ip a).
Step 6: Create Client Certificates and Configuration Files
Return to the Easy‑RSA directory and generate a client certificate. You can repeat this step for each user or device.
cd /etc/openvpn/easy-rsa sudo ./easyrsa build-client-full client1 nopass
Now bundle the client files into a single .ovpn profile. Create a temporary folder and copy the needed items:
mkdir -p ~/client-configs/files cp pki/ca.crt pki/issued/client1.crt pki/private/client1.key ta.key ~/client-configs/files/
Generate the base client config (you can copy the example from /usr/share/doc/openvpn/examples/sample-config-files/client.conf) and then embed the certificates inline for convenience:
cat > ~/client-configs/files/client1.ovpn <<'EOF' client dev tun proto udp remote YOUR_SERVER_IP 1194 resolv-retry infinite nobind persist-key persist-tun remote-cert-tls server cipher AES-256-CBC auth SHA256 key-direction 1 $(cat ca.crt) $(cat client1.crt) $(cat client1.key) $(cat ta.key) verb 3 EOF
Replace YOUR_SERVER_IP with the public address of your VPN server. The resulting client1.ovpn file can be transferred securely to the user’s device.
Step 7: Start and Enable the OpenVPN Service
Launch the server and verify that it starts without errors:
sudo systemctl start openvpn@server sudo systemctl status openvpn@server
If the status shows active (running), enable it to start on boot:
sudo systemctl enable openvpn@server
Check the log for any misconfiguration:
sudo journalctl -u openvpn@server -f
Typical messages include “Initialization Sequence Completed”, which indicates the server is ready.
Step 8: Test the VPN Connection
On a client machine, import the .ovpn profile into the OpenVPN GUI (Windows) or run the command line client (Linux/macOS):
sudo openvpn --config client1.ovpn
If everything is correct, you’ll see the handshake, TLS authentication, and finally a line that says “Initialization Sequence Completed”. Verify that your public IP has changed by visiting ifconfig.me or similar service. Also, ping a private address inside the VPN network, e.g., ping 10.8.0.1, to confirm routing.
Common Mistakes to Avoid
1. Forgetting to open UDP port 1194. The server will start, but clients cannot reach it. Double‑check firewall rules and any external router NAT settings.
2. Mismatched tls-auth direction. The server uses 0, the client must use 1. A wrong direction results in “TLS Error: TLS key negotiation failed to occur”.
3. Using the same certificate for multiple clients. This defeats the purpose of individual revocation. Generate a unique certificate per device.
4. Neglecting IP forwarding. Without net.ipv4.ip_forward=1, traffic never leaves the tunnel.
5. Leaving the default Diffie‑Hellman parameters. Modern OpenVPN can use --dh none with elliptic‑curve keys; older defaults are slower and may be vulnerable.
Tips and Tricks
• Use elliptic‑curve cryptography. Replace the RSA CA with an ECDSA CA for smaller keys and faster handshakes: ./easyrsa --curve secp384r1 build-ca.
• Enable client‑specific routing. Add client-config-dir ccd to server.conf and place per‑client files in /etc/openvpn/ccd/ to push static routes.
• Implement certificate revocation. Run ./easyrsa revoke client1 and generate an updated CRL with ./easyrsa gen-crl. Point OpenVPN to the CRL using crl-verify crl.pem.
• Compress traffic. Add compress lz4 (or compress lz4-v2) on both server and client for faster performance on low‑bandwidth links.
• Monitor connections. The status /var/log/openvpn-status.log directive gives you a real‑time view of connected clients.
Frequently Asked Questions
Can I run OpenVPN on a non‑standard port?
Yes. Change the port line in server.conf and adjust the client remote line accordingly. Using TCP (e.g., port 443) can help bypass restrictive firewalls, but expect higher latency.
Do I need to regenerate all certificates after changing the encryption cipher?
No. The cipher is negotiated at the TLS layer, not baked into the certificates. Just update cipher and auth lines on both server and client, then restart the service.
How do I revoke a compromised client certificate?
Run ./easyrsa revoke CLIENT_NAME, then generate a new CRL with ./easyrsa gen-crl. Copy the updated crl.pem to /etc/openvpn/ and ensure crl-verify crl.pem is present in server.conf. OpenVPN will reject the revoked certificate on the next handshake.
Conclusion
Setting up a secure OpenVPN server on Linux is a rewarding exercise that strengthens your organization’s remote‑access posture. By following the steps above—installing the software, building a robust PKI, hardening the server configuration, and testing thoroughly—you’ll have a production‑grade VPN that balances performance with strong encryption. Remember to keep your certificates under lock‑and‑key, rotate keys periodically, and stay vigilant for the common pitfalls outlined. With these practices in place, your users can enjoy private, reliable connectivity from anywhere on the globe.
Photo by Petter Lagson on Unsplash





