Skip to content

How to set up an OpenVPN server on Linux

Due to how long this guide is, despite the fact that I made it as minimalist as possible, I will keep kept my remarks and comments in a separate post, except from the bare minimum.
Here I will just point out that I tried to make this as straight to the point as I could, with the sole objective of getting “something that works”, with, in particular, little to no consideration for security aspects and nothing that isn’t strictly necessary. This guide will (should) get you as fast as possible with a working setup (including connecting your OpenVPN client to it), but leaves a lot of room for post-install improvements.


My objective was to set up an OpenVPN server on a VPS running Debian 12, so obviously having exactly that would be ideal. But any machine or virtual machine with Debian or Ubuntu should do, possibly with some tweaks. Any decent Linux distro should do too, but then with even more modifications.
Have root access on it.
We’ll do everything as root here for the sake of simplicity (again and for the last time, this guide is not security-focused). You’ll have to “sudo” most of the commands if you don’t. And, I guess, work from a different folder.

Installing OpenVPN

apt-get install openvpn

Installing EasyRSA

I didn’t manage to use the one from the package manager, so I just grabbed this 3.1.7 release, extracted just the “easyrsa” file, and uploaded it inside the /root/easyrsa folder (so the file’s full name is /root/easyrsa/easyrsa)
Alternatively, you can just wget a slightly different version.

Assuming you are currently in /root:

mkdir easyrsa
cd easyrsa
chmod 744 easyrsa

Generating keys and certificates

Initialize a new Public Key Infrastructure (PKI), generate a Certificate Authority (CA) keypair, and copy the CA public key to the OpenVPN config folder:

./easyrsa init-pki
./easyrsa build-ca
cp pki/ca.crt /etc/openvpn/server/

Make sure you take note of the password you choose for the CA, as you can’t leave it empty and you’ll need it later. Beside that, you can leave all default values for the rest of the prompts.

Generate the server key and certificate, the Diffie-Hellman (DH) parameters file, the Hash-based Message Authentication Code (HMAC) key

./easyrsa gen-req server01 nopass
openssl dhparam -out /etc/openvpn/server/dh.pem 2048
openvpn --genkey secret /etc/openvpn/server/ta.key

Sign the server certificate, and copy the server key and certificate to the OpenVPN settings folder:

./easyrsa sign-req server server01
cp pki/issued/server01.crt /etc/openvpn/server/
cp pki/private/server01.key /etc/openvpn/server/

Generate the client key and certificate, sign it and copy it (just the certificate) to the OpenVPN settings folder:

./easyrsa gen-req client01 nopass
./easyrsa sign-req client client01
cp pki/issued/client01.crt /etc/openvpn/client/

Generating the client profile

Get ovpngen:

chmod 744 ovpngen

Then generate the profile. Note that we are still working in the /root/easyrsa folder, which we haven’t left since we created it at the beginning of the guide:

./ovpngen [server IP] pki/ca.crt pki/issued/client01.crt pki/private/client01.key /etc/openvpn/server/ta.key > client01.ovpn

I won’t detail how to configure your OpenVPN client, but basically you just need to install an OpenVPN client like the one here, then import that client01.ovpn file in it and you can connect.
Except we’re not done yet, with configuring the server

Configuring and starting OpenVPN

Copy the sample configuration file into the OpenVPN settings folder, then open it with nano:

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/
nano /etc/openvpn/server.conf

In this file, set these values:

port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server01.crt
key /etc/openvpn/server/server01.key
dh /etc/openvpn/server/dh.pem
tls-auth /etc/openvpn/server/ta.key 0

Also uncomment these lines:

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

Finally, start OpenVPN:

systemctl start openvpn@server

First test

You can skip this as we’re not fully done yet, but you now have enough to be able to connect your OpenVPN client to your OpenVPN server. If your are unable to connect, you should probably double-check that you didn’t miss anything.
However, if you check it, you’ll notice that your IP still is your client machine’s IP, not your server’s IP… So on to the next part.

Setting up the server’s networking parameters

Enable IP forwarding:

nano /etc/sysctl.conf

add at the end:


Find the name of your server’s public network interface. It may often be “eth0”, but for me it wasn’t:

ip route | grep default

it will output something like

default via [default gateway IP] dev ens6 proto dhcp src [server IP] metric 100

In this, the value of interest is what’s after “dev”, so in my case, “ens6”

Set up a firewall rule to enable “masquerading”, a network address translation (NAT) setup allowing traffic from the VPN network ( to exit via your server’s public network interface:

iptables -t nat -A POSTROUTING -s -o ens6 -j MASQUERADE

(of course, replace ens6 with the value you found above)

Final test

That’s it, you should now have enough to connect to your OpenVPN server, and then actually use the server’s IP address from your client machine.

Further improvements

As indicated at the start, here I focused on just getting something working as fast as possible, and (some) further improvements will be discussed in the complementary post that is to come in order to keep this post short(-ish).
But I feel that there is still something important missing, even for “something that just works”: making sure the described setup still works… after a reboot.

For this, 2 things which I actually haven’t tested as I’m writing these lines:
1) Save the iptables parameters:

iptables-save > /etc/iptables/rules.v4

2) Make the OpenVPN service run at startup:

systemctl enable openvpn@server

And now, that should be it.

Posted in Internet, privacy, servers.

0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Some HTML is OK

or, reply to this post via trackback.

Sorry about the CAPTCHA that requires JS. If you really don't want to enable JS and still want to comment, you can send me your comment via e-mail and I'll post it for you.

Please solve the CAPTCHA below in order to fight spamWordPress CAPTCHA