Self Hosting OpenVPN on Ubuntu Server

A VPN or Virtual Private Network can be a great tool to secure your internet connection by creating an encrypted tunnel between your devices and the Internet. They work by connecting your devices to a remote server via an encrypted connection, and letting you browse …

A VPN or Virtual Private Network can be a great tool to secure your internet connection by creating an encrypted tunnel between your devices and the Internet. They work by connecting your devices to a remote server via an encrypted connection, and letting you browse the internet using that server’s internet connection.

Do note that VPNs cannot magically encrypt data outside the connection between your device and the VPN server, hence won’t add any additional security to non-HTTPS traffic aka websites that don’t use HTTPS. Your VPN server will essentially replace your ISP as the middleman between your devices and the internet.

Don’t want to get your hands dirty? Our private VPN guide has recommendation and everything you need to know.

Let’s look at a few things that you should look for in a VPS provider before self-hosting your own VPN server:

  • Virtualization Technology: I recommend using a VPS provider that uses KVM or Xen instead of OpenVZ. Only KVM & Xen provides true virtualization, OpenVZ is built in a way that lets your VPS provider snoop on your activities and files easily.
  • An IPv4 address: Almost all VPS providers will give you an IPv4 address, unless you are going with an ultra budget VPS provider.
  • Location: Pick a location that suits your needs, if you are looking to watch content of a particular country choose that, If you’re going to torrent Linux ISOs, don’t choose Germany or Austria (they have very strict anti-piracy laws), if you’re looking for privacy, choose a VPS outside the 14 eyes.

We’ll be using OpenVPN in this tutorial to self-host our VPN server, it’s a popular open-source VPN protocol that uses a custom security protocol and SSL/TLS for key exchange. An OpenVPN server can help provide full confidentiality, authentication, and integrity.

OpenVPN has no known major vulnerabilities and is generally considered secure, it’s pretty fast, can be easily configured to run on any port using either UDP or TCP, thereby easily bypassing restrictive firewalls, and has native apps for all platforms that can be configured in less than a minute.

Alright, with all of that out of the way, let’s get into the good stuff.

I’ve used Linode as an example, the steps will be the same for any other cloud provider, be it Azure, Vultr AWS, etc.

Step 1: Creating a Virtual Machine

Any basic virtual machine running Ubuntu 20.04 will suffice:

  • 1 GB RAM
  • 1 vCPU

I’ve used Ubuntu 20.04 in this guide, but, you are free to use Debian, AlmaLinux, Rocky Linux, CentOS and Fedora, it’ll work just fine.

Step 2: Configuring the Virtual Machine for OpenVPN

Now, let’s configure our server:

Step 2.1: Connect to the Server via SSH

Open up the terminal on your device, and run this command:

ssh root@

If you chose a username while creating the virtual machine, use that instead of root, and replace with the IP address of your VM.

You’ll be prompted with “The authenticity of host…”, just type yes, and then enter the password.

Step 2.2: Configure Automatic Updates

Let’s update packages and configure automatic updates so that our server gets patched automatically.

# Update packages
sudo apt update && apt upgrade

# Install unattended-upgrades
sudo apt install unattended-upgrades

# Configure unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

# Test unattended-upgrades
sudo unattended-upgrades --dry-run --debug

Step 2.3: Creating a “sudo” user

If your cloud provider didn’t ask you to choose a username while creating it, you are given root access to your server; it is recommended to not use the “root” user, which has unlimited privileges and can execute any command, even ones that could potentially disrupt your server.

Let’s create a new user on a server that can use “sudo” to do day-to-day administration tasks.

# Create a new user
adduser username

# Add user to the "sudo" group
usermod -aG sudo username

# Check user's group
groups username

# Switching users
su - username
su - root

Step 2.4: Configure SSH Keys

Using SSH keys instead of passwords provides you with better security, as SSH keys are far more long and complex than any password could ever be; you can also add an extra password to the SSH keys, requiring both the SSH key and the password to access the server.

Log out of the server or just open up a new terminal on your computer to create SSH keys:

# Create ssh keys
ssh-keygen -b 4096 

# View ssh keys
ls -l ~/.ssh

# Add public key to server
ssh-copy-id -i ~/.ssh/ username@

# Switch ssh keys on client
ssh-add ~/.ssh/keyname

During the ssh-keygen process, you’ll be prompted for file location, use the default one or give a new location by typing in /home/username/.ssh/keyname, and enter a strong password for the SSH key.

In the .ssh folder, there’ll be two files, the one with “.pub” extension is your public key, the other one is your private key, never share the private key with anyone.

You might get a message like Could not open a connection to your authentication agent when switching SSH keys, you’ll need to start ssh-agent first using:

eval `ssh-agent`

Once done, you can log in to the server by just using the ssh username@ command without entering the user password, although you will need to enter the password of your SSH key.

Step 2.5: Disable root login

Now that we have a new user with limited privileges that can run “sudo” commands and can access the server via SSH keys; let’s lock down our root user, as it is usually the most targeted account by hackers.

To do so, type in sudo nano /etc/ssh/sshd_config, and update PermitRootLogin to no and add AllowUsers username as shown below:

Disable root login via SSH

Optionally, you can also go ahead and disable password-based login via SSH for all users, including the new user account we just created, by updating these values in the same sshd config file:

# Disable password-based login via ssh for all users [optional]
PasswordAuthentication no
ChallengeResponseAuthentication no

Once done, save the file using Ctrl + O & Ctrl + X, and restart the sshd service using this command:

sudo systemctl restart sshd

Now, your server is ready to install OpenVPN, let’s get into it.

Step 3: Installing OpenVPN

We’ll be using an OpenVPN shell script installer by Nyr to install OpenVPN, this scripts takes care of all the configuration, we just need to answer a few simple questions and download the config file at the end.

Needless to say, you shouldn’t go around executing random scripts you downloaded from the internet, so if you know some bash, read the script, it’s open-source and is hosted on GitHub to make sure there’s nothing fishy in there.

Step 3.1 Downloading the OpenVPN script from GitHub

We’ll be using wget to download the script, it usually comes with the OS image already, you can install it using

sudo apt install wget

Once that’s done, download the script using the following command:

sudo wget

Step 3.2: Installing & Configuring OpenVPN

After downloading the OpenVPN script, install it using the following command:

sudo bash

You’ll be prompted with something like this, pick the options as shown below:

Welcome to this OpenVPN road warrior installer!

Which IPv4 address should be used?
IPv4 address [1]: 1

Which protocol should OpenVPN use?
   1) UDP (recommended)
   2) TCP
Protocol [1]: 1

What port should OpenVPN listen to?
Port [1194]: 443

Select a DNS server for the clients:
   1) Current system resolvers
   2) Google
   4) OpenDNS
   5) Quad9
   6) AdGuard
DNS server [1]: 3

Enter a name for the first client:
Name [client]: clientname

OpenVPN installation is ready to begin.
Press any key to continue...

Pick any port you like, I have used 443; you can choose between either TCP or UDP, however, UDP tends to perform a bit faster than TCP, as for DNS servers, you can choose any of them, I like Cloudflare’s for its speed and privacy.

Up next, you’ll be asked to name the client, and then the OpenVPN installation will begin, if everything goes all right, you’ll be greeted with something like this:


The client configuration is available in: /root/clientname.ovpn
New clients can be added by running this script again.

Step 3.3: Adding New Clients

To add a new user, just run the script again and select 1 and type in a client name:

OpenVPN is already installed.

Select an option:
   1) Add a new client
   2) Revoke an existing client
   3) Remove OpenVPN
   4) Exit
Option: 1

Provide a name for the client:
Name: newclientname

Step 3.4: Disabling Logs

With all of that out of the way, there’s only one thing left to be done on the server’s side is to disable the logs:

To disable logs, open the server.conf file, and set verb 3 to verb 0:

sudo nano /etc/openvpn/server/server.conf

Step 4: Retrieving the “.ovpn” configuration file

Now, we need to download the configuration file to our local machine later on. The problem is that the script places the configuration files in the root directory by default.

To download it, we need to move the .ovpn file to our user’s directory and give ourselves the correct privileges:

# Moving the .ovpn file to user directory
sudo mv /root/clientname.ovpn ~

# Giving correct privileges
sudo chown username clientname.ovpn

Once that’s done, we can download the .ovpn configuration file using sftp or scp:

# Establishing a sftp session
sftp username@

# Downloading file
get clientname.ovpn

Step 5: Installing and Configuring OpenVPN Client

Now, all you have to do is install the native OpenVPN client on your device, add the downloaded configuration file to the client, click connect, and you are golden.

Check your IP address, it should match with your server’s IP address, and enjoy your very own private VPN server.

That’s all folks!

I’ll update this tutorial soon with guides on adding 2FA and more.

Leave a Comment