Updated June 2026: Rewritten for Easy-RSA 3 (the version shipped by current distros). Updated cipher recommendations, replaced comp-lzo (vulnerable to VORACLE), and switched startup to systemd. The original 2012 article used Easy-RSA 2, which is no longer available in most distributions.

Looking for something simpler? WireGuard is a modern VPN alternative that is easier to configure and faster. See WireGuard — set up a VPN on Linux in minutes.

The scenario

Two locations connected over the Internet through an encrypted tunnel:

  • Server (headquarters) — public IP 12.34.56.78, Debian/Ubuntu
  • Client (branch office) — connects through the VPN tunnel

All client traffic is routed through the server. This is useful when you want to control outbound traffic, enforce a single exit point, or encrypt traffic on an untrusted network.

Install OpenVPN and Easy-RSA

Debian / Ubuntu:

sudo apt install openvpn easy-rsa

RHEL / Fedora / Rocky Linux:

sudo dnf install openvpn easy-rsa

Set up the PKI with Easy-RSA 3

Easy-RSA 3 manages the Certificate Authority (CA) and all keys. Run these commands as a regular user — do not run Easy-RSA as root.

make-cadir ~/openvpn-ca
cd ~/openvpn-ca

Initialize the PKI:

./easyrsa init-pki

Build the CA (you will be prompted for a CA name):

./easyrsa build-ca nopass

Generate the server key and certificate request:

./easyrsa gen-req server nopass

Sign the server certificate:

./easyrsa sign-req server server

Type yes when prompted to confirm.

Generate the Diffie-Hellman parameters (use 2048 minimum; 4096 is safer but slower to generate):

./easyrsa gen-dh

Generate a TLS auth key for extra protection against DoS and port scanning:

openvpn --genkey secret ta.key

Copy files to /etc/openvpn/server/

sudo cp pki/ca.crt              /etc/openvpn/server/
sudo cp pki/issued/server.crt   /etc/openvpn/server/
sudo cp pki/private/server.key  /etc/openvpn/server/
sudo cp pki/dh.pem              /etc/openvpn/server/
sudo cp ta.key                  /etc/openvpn/server/

Server configuration

Create /etc/openvpn/server/server.conf:

port 1194
proto udp
dev tun

ca   ca.crt
cert server.crt
key  server.key
dh   dh.pem

tls-auth ta.key 0
key-direction 0

server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt

push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"

keepalive 10 120

cipher AES-256-GCM
auth SHA256

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn/openvpn-status.log
verb 3

Security notes:

  • cipher AES-256-GCM — current standard; do not use Blowfish (BF-CBC) or DES
  • auth SHA256 — HMAC authentication; do not use MD5 or SHA1
  • comp-lzo is intentionally absent — compression is vulnerable to the VORACLE attack; leave it out

Enable IP forwarding on the server:

echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Start the server with systemd

sudo systemctl enable --now openvpn-server@server
sudo systemctl status openvpn-server@server

Generate a client certificate

Back in ~/openvpn-ca:

./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1

Client configuration

Transfer these files from the server to the client machine:

  • pki/ca.crt
  • pki/issued/client1.crt
  • pki/private/client1.key
  • ta.key

Create client1.conf on the client:

client
dev tun
proto udp

remote 12.34.56.78 1194
resolv-retry infinite
nobind

user nobody
group nogroup

persist-key
persist-tun

ca   ca.crt
cert client1.crt
key  client1.key

tls-auth ta.key 1
key-direction 1

cipher AES-256-GCM
auth SHA256

verb 3

Connect:

sudo openvpn --config client1.conf

Or install it as a systemd service:

sudo cp client1.conf /etc/openvpn/client/
sudo systemctl enable --now openvpn-client@client1

See also