How to Install and Configure OpenVPN on RHEL 7

OpenVPN is one of the most widely deployed VPN solutions in the enterprise, valued for its flexibility, strong encryption, and compatibility across nearly every operating system. On RHEL 7, OpenVPN is not included in the base repositories but is available from EPEL. Building a proper PKI (Public Key Infrastructure) with Easy-RSA ensures every client has its own signed certificate, giving you fine-grained revocation control — something simpler VPN solutions lack. This guide covers installing OpenVPN and Easy-RSA, building a full certificate authority, generating server and client certificates, writing the server configuration, enabling IP forwarding and firewall masquerade, generating a client .ovpn file, and making a successful connection.

Prerequisites

  • RHEL 7 server with a registered subscription or CentOS 7 equivalent
  • Root or sudo access
  • EPEL repository enabled
  • A public IP address and UDP port 1194 accessible (or TCP 443 for firewalled environments)
  • SELinux in enforcing mode — we will handle context labeling
  • A client machine to test the finished configuration

Step 1: Install OpenVPN and Easy-RSA

Enable EPEL if not already done, then install OpenVPN and Easy-RSA:

sudo yum install -y epel-release
sudo yum install -y openvpn easy-rsa

Verify the installed versions:

openvpn --version | head -1
ls /usr/share/easy-rsa/

On RHEL 7 with Easy-RSA 3.x, the scripts live in /usr/share/easy-rsa/3/. Copy the Easy-RSA directory to a working location so your PKI persists independently of package updates:

sudo mkdir -p /etc/openvpn/easy-rsa
sudo cp -r /usr/share/easy-rsa/3/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa

Step 2: Initialize the PKI and Build the Certificate Authority

Initialize the PKI directory structure:

sudo ./easyrsa init-pki

Build the Certificate Authority. You will be prompted for a CA passphrase and a Common Name. The passphrase protects the CA private key — use something strong and store it securely:

sudo ./easyrsa build-ca

This creates pki/ca.crt (the CA certificate, distributed to all clients) and pki/private/ca.key (the CA private key, kept only on the server). Also generate the Diffie-Hellman parameters (this takes several minutes on RHEL 7):

sudo ./easyrsa gen-dh

Generate a TLS Authentication (TA) key for an additional HMAC layer that blocks unauthenticated packets before they reach the OpenVPN daemon:

sudo openvpn --genkey --secret /etc/openvpn/ta.key

Step 3: Generate the Server Certificate

Create a server certificate and key pair. The argument nopass means the server key is not passphrase-protected — necessary because OpenVPN starts unattended at boot:

sudo ./easyrsa build-server-full server nopass

Copy the required files to /etc/openvpn/:

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

Restrict permissions on the private key:

sudo chmod 600 /etc/openvpn/server.key
sudo chmod 600 /etc/openvpn/ta.key

Step 4: Generate a Client Certificate

Generate a certificate for each VPN client. Replace client1 with a meaningful identifier for the user or device:

sudo ./easyrsa build-client-full client1 nopass

To require a passphrase on the client key (recommended for user-facing certificates), omit nopass:

sudo ./easyrsa build-client-full client1

The client files are now at:

  • pki/ca.crt — CA certificate (shared)
  • pki/issued/client1.crt — client certificate
  • pki/private/client1.key — client private key

Step 5: Write the Server Configuration

Copy the sample server configuration as a starting point:

sudo cp /usr/share/doc/openvpn-*/sample/sample-config-files/server.conf /etc/openvpn/
sudo vi /etc/openvpn/server.conf

The key directives you must set or confirm:

# Protocol and port
port 1194
proto udp
dev tun

# Certificate and key files
ca   /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key  /etc/openvpn/server.key
dh   /etc/openvpn/dh.pem

# TLS authentication — direction 0 on server
tls-auth /etc/openvpn/ta.key 0
cipher AES-256-CBC
auth SHA256

# VPN subnet — clients get IPs from this range
server 10.8.0.0 255.255.255.0

# Push default gateway so ALL client traffic routes through VPN
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# Keep connections alive
keepalive 10 120

# Persist keys and tunnel across restarts
persist-key
persist-tun

# Drop privileges after startup
user nobody
group nobody

# Logging
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3

Step 6: Enable IP Forwarding

Clients need the server to forward their traffic to the internet. Enable forwarding persistently:

sudo vi /etc/sysctl.d/99-openvpn.conf
net.ipv4.ip_forward = 1
sudo sysctl -p /etc/sysctl.d/99-openvpn.conf
sysctl net.ipv4.ip_forward
# Expected: 1

Step 7: Configure Firewall NAT Masquerade

Add masquerade so client VPN traffic appears to come from the server’s public IP:

sudo firewall-cmd --permanent --add-service=openvpn
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --permanent --add-port=1194/udp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Verify masquerade is active:

sudo firewall-cmd --query-masquerade
# Expected: yes

Step 8: Handle SELinux for OpenVPN

On RHEL 7 with SELinux enforcing, OpenVPN needs the correct context for its log files and may need a boolean set if using a non-default port:

# Allow OpenVPN to write logs
sudo semanage fcontext -a -t openvpn_var_log_t "/var/log/openvpn(/.*)?"
sudo restorecon -Rv /var/log/openvpn.log

# If using a non-standard port, label it
sudo semanage port -a -t openvpn_port_t -p udp 1194

If you encounter AVC denials, use audit2why to diagnose:

sudo ausearch -m avc -ts recent | audit2why

Step 9: Start and Enable OpenVPN

sudo systemctl start openvpn@server
sudo systemctl enable openvpn@server
sudo systemctl status openvpn@server

Confirm the tun0 interface is up:

ip addr show tun0

Check the log for errors:

sudo tail -f /var/log/openvpn.log

Step 10: Generate a Client .ovpn File

Bundle all required files into a single portable .ovpn file for easy client distribution. Create a script or build it manually:

sudo bash -c "cat > /tmp/client1.ovpn" <<'OVPN'
client
dev tun
proto udp
remote YOUR_SERVER_PUBLIC_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
auth SHA256
# TLS auth direction 1 on client
key-direction 1
verb 3
OVPN

echo "<ca>"                                        | sudo tee -a /tmp/client1.ovpn
sudo cat /etc/openvpn/easy-rsa/pki/ca.crt          | sudo tee -a /tmp/client1.ovpn
echo "</ca>"                                       | sudo tee -a /tmp/client1.ovpn
echo "<cert>"                                      | sudo tee -a /tmp/client1.ovpn
sudo cat /etc/openvpn/easy-rsa/pki/issued/client1.crt | sudo tee -a /tmp/client1.ovpn
echo "</cert>"                                     | sudo tee -a /tmp/client1.ovpn
echo "<key>"                                       | sudo tee -a /tmp/client1.ovpn
sudo cat /etc/openvpn/easy-rsa/pki/private/client1.key | sudo tee -a /tmp/client1.ovpn
echo "</key>"                                      | sudo tee -a /tmp/client1.ovpn
echo "<tls-auth>"                                  | sudo tee -a /tmp/client1.ovpn
sudo cat /etc/openvpn/ta.key                       | sudo tee -a /tmp/client1.ovpn
echo "</tls-auth>"                                 | sudo tee -a /tmp/client1.ovpn

Securely transfer /tmp/client1.ovpn to the client machine (use scp over an encrypted channel, never email).

Step 11: Connect from the Client

On a Linux client with OpenVPN installed:

sudo openvpn --config client1.ovpn

A successful connection ends with a line like Initialization Sequence Completed. Verify the tunnel:

ip addr show tun0
curl https://ifconfig.me   # Should return the server's public IP
ping 10.8.0.1              # Ping the VPN server internal address

You now have a fully functional OpenVPN server on RHEL 7 backed by a proper certificate authority. Every new user requires their own signed certificate, revocable at any time with ./easyrsa revoke client1 followed by regenerating the CRL and adding crl-verify /etc/openvpn/easy-rsa/pki/crl.pem to the server config. This certificate-per-client model is what sets OpenVPN apart for enterprise deployments requiring accountability and access control. Regularly update OpenVPN from EPEL (yum update openvpn) and rotate your DH parameters and TA key annually.