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:
If you chose a username while creating the virtual machine, use that instead of root, and replace 22.214.171.124 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 email@example.com # 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.
.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:
Once done, you can log in to the server by just using the
ssh firstname.lastname@example.org 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
no and add
AllowUsers username as shown below:
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 Enter a name for the first client: Name [client]: clientname Select a DNS server for the client: 1) Current system resolvers 2) Google 3) 126.96.36.199 4) OpenDNS 5) Quad9 6) AdGuard DNS server : 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 188.8.131.52 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) 184.108.40.206 4) OpenDNS 5) Quad9 6) AdGuard DNS server : 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 email@example.com # 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.
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.