Self Hosting WireGuard VPN on Ubuntu Server

This guide on installing & configuring a self-hosted VPN uses WireGuard, a new open-source VPN protocol that’s extremely fast with very little overhead and state-of-the-art cryptography. WireGuard uses the UDP protocol, can be configured to use any port, and has been reviewed by a 3rd …

This guide on installing & configuring a self-hosted VPN uses WireGuard, a new open-source VPN protocol that’s extremely fast with very little overhead and state-of-the-art cryptography. WireGuard uses the UDP protocol, can be configured to use any port, and has been reviewed by a 3rd party auditor.

This is part 3 of our VPN self-hosting guide, our last guide covers self-hosting VPN using OpenVPN.

I’m not going to go into the nitty-gritty of what a VPN is, how it works, whether you should use it or not, our guide on private VPN services covers all of that and more.

With all of that out of the way, let’s get with it, choose a VPS that offers:

  • Virtualization via KVM or Xen instead of OpenVZ
  • An IPv4 address
  • Your preferred server location

Setting up a private self-hosted VPN using WireGuard is super easy, and there are native apps for all devices.

WireGuard has no known major vulnerabilities, is in-tree with Linux Kernel 5.6, although, it may succumb to traffic shaping more easily than OpenVPN due to lack of support for TCP. It is extremely stable and robust, as it uses an initial endpoint for connections and can switch servers while maintaining the connection.

Alright, let’s get into the good stuff, I’ve used DigitalOcean in this tutorial, the steps will be the same for any other cloud provider be it Linode, Vultr AWS, etc.

Step 1: Creating a Virtual Machine

Any basic virtual machine running Ubuntu 20.04 will suffice:

  • 1 GB RAM
  • 1 vCPU
  • 20 GB Storage

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 WireGuard

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@123.45.67.89

If you chose a username while creating the virtual machine, use that instead of root, and replace 123.45.67.89 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/keyname.pub username@123.45.67.89

# 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@123.45.67.89 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:

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 WireGuard, let’s get into it.

Step 3: Installing WireGuard

We’ll be using a WireGuard shell script installer by Nyr to install WireGuard, 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 WireGuard 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 https://github.com/Nyr/wireguard-install/raw/master/wireguard-install.sh

Step 3.2: Installing & Configuring WireGuard

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

sudo bash wireguard-install.sh

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

Welcome to this WireGuard road warrior installer!

What port should WireGuard listen to?
Port [51820]: 51820

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

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

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

You can choose any port number, WireGuard uses UDP which by default runs on 51820, as for DNS servers, you can choose any of them, I like Cloudflare’s 1.1.1.1 for its speed and privacy.

You’ll also be asked to name the client, and then the WireGuard installation will begin, if everything goes all right, you’ll be greeted with a QR code and something like this:

↑ That is a QR code containing the client configuration.

Finished!

The client configuration is available in: /root/clientname.conf
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:

WireGuard is already installed.

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

Provide a name for the client:
Name: newclientname

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

Step 4: Retrieving the WireGuard Config 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 .conf file to our user’s directory and give ourselves the correct privileges:

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

# Giving correct privileges
sudo chown username clientname.conf

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

# Establishing a sftp session
sftp username@123.45.67.89

# Downloading file
get clientname.conf

Step 5: Installing and Configuring WireGuard Client

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

Importing WireGuard config files

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