Setting up a Home Server Connection via VPN (Wireguard) and a Cloud VPS

Mahdi BagheriMahdi Bagheri
6 min read

Motivation

I wanted to setup a home server where I could run applications and access them when I am not at home. But I also wanted to avoid opening ports directly to my home network to access the services running on the home server. Another issue is that the global IP address received by my ISP changes every few days and I also didn’t want to work with something like DynDNS.

Therefore as a workaround I purchased a cheap Cloud VPS which has its own static IPv4 address through which I built a tunnel via a VPN connection to my home server for accessing the services.

Initial Setup

At first I went through the initial setup for both the home server and the VPS.

  1. Installing the Server Software (Ubuntu Server)

  2. Creating a dedicated user and granting it sudo access

  3. Providing root and user with strong passwords

  4. Upgrading all available packages

  5. Removing SSH permission for root user

  6. Allowing only SSH access via SSH key

  7. Changing default SSH port to reduce Bot noises

  8. Installing and activating unattended-upgrades

  9. Installing and enabling fail2ban

  10. Installing and running the web application

I won’t be going into details for these steps in this article since the focus is on the VPN connection between home server and the VPS.

VPN Connection Setup

After setting up the application on our home server, we need to setup the VPN connection between our home server and the VPS. For this I have been using Wireguard since it was far more easy to setup than any other VPN software.

The following steps are similar for both the home server and the VPS.

Wireguard Installation

The installation process is as easy as executing following commands in Ubuntu.

sudo apt update
sudo apt install wireguard

Private Key and Public Key Generation

Next we need to generate our private and public keys that we will provide to our Wireguard interface configuration files.

Private Key

umask 077
wg genkey > privatekey

Public Key

wg pubkey < privatekey > publickey

Wireguard Configuration File

After the installation of Wireguard a directory with the name wireguard will be available inside /etc.

Here we will create a .conf file and name it whatever we want. For simplicity I will name it the same as found in many other tutorials wg0.conf.

sudo touch /etc/wireguard/wg0.conf

VPS

On the VPS we will add the following lines to the configuration file.

# VPS
[Interface]
PrivateKey = <VPS Private Key>
Address = 10.0.0.1/24
ListenPort = 51820

# Home Server
[Peer]
PublicKey = <Home Server Public Key>
AllowedIPs = 10.0.0.2/32

Home Server

One the home server we will add the following lines to the configuration file.

# Home Server
[Interface]
PrivateKey = <Home Server Private Key>
Address = 10.0.0.2/24
ListenPort = 51820

# VPS
[Peer]
PublicKey = <VPS Public Key>
Endpoint = <Static IPv4 Address of VPS>
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 25

You can add whatever private IP addresses you want to the Endpoints for the VPN connection. But they must be in the same subnet so they will be able to reach each other. In this case I decided to go with a 10.0.0.X/24 Subnet. The VPN subnet should also not overlap with the subnets of either endpoint.

It is also possible to assign a different Port, which becomes useful if you want to use multiple interfaces to establish different connections in order to separate different endpoints. In that case you would create an additional .conf file (e.g. wg1.conf) and start this interface similarly to the following steps shown for the wg0.conf example. Additionally this port must also be opened in the firewall, as shown later.

Enabling and Starting the Wireguard Interface

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

If you named your .conf file something else you would use the that name instead of wg0.

Allow Port 51820 on Firewall

In case UFW (Uncomplicated Firewall) is not installed and enabled yet, do it with the following commands.

sudo apt install ufw
sudo ufw enable

For the communication to work we will also need to open port 51820 on the home server. This is as easy as executing the following UFW command. This has to be done on both machines.

sudo ufw allow 51820/udp

We might also go a step further and permit connection to only IP address 10.0.0.1 for the application.

sudo ufw allow from 10.0.0.1 to any port <APPLICATION_PORT>
sudo ufw deny <APPLICATION_PORT>

Check VPN Connectivity

Now test the connectivity by trying to ping the other device.

ping 10.0.0.1 # From Home Server
ping 10.0.0.2 # From VPS

If the ping worked, we might also try to access the application with a curl command.

curl http://10.0.0.2:<APPLICATION_PORT>

Setting up a Reverse Proxy Connection to the Home Server Application

Now that we know that we are able to reach the application through our VPN connection, we need to configure the access from our VPS to the application.

This is fairly easy with Caddy as a Reverse Proxy. If you own a domain create an A record to the IP address of your VPS for the domain or subdomain of your choosing.

Next we will install Caddy on our VPS.

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Firewall Adjustments

Before we continue with configuring Caddy we need to open the ports 80 and 443 both on our VPS as well as the firewall rules in our administration panel for our VPS provided by the cloud provider.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Caddy(file) Configuration

Now that Caddy is installed we need to configure the Caddyfile which is located under /etc/caddy.

https://<Your-Domain>{
    reverse_proxy 10.0.0.2:<APPLICATION_PORT>{
        header_up X-Real-IP {remote_host} 
        header_up X-Forwarded-For {remote_host} 
        header_up X-Forwarded-Proto {scheme} 
        header_up X-Forwarded-Port {server_port} 
    }
    header {
        -Server
    }
    log {
        output file /var/log/caddy/access.log
        format json
    }
}

This basic setup should work fine for the start and can be easily adjusted depending on the needs and how the application is installed and served on the home server (native or container).

It might be necessary to format the file correctly for it to work with. Run this following command when your are in the /etc/caddy directory where the Caddyfile resides.

sudo caddy fmt --overwrite

Enabling and Starting Caddy

sudo systemctl enable caddy
sudo systemctl start caddy

Caddy should automatically generate a TLS certificate for you. But in case not stop the service first.

sudo systemctl stop caddy

And run the command.

sudo caddy reverse-proxy --from <your-domain> --to 10.0.0.2:<APPLICATION_PORT>

Then restart caddy service again.

Check VPS Connectivity

At last we will check if everything works by opening our browser and typing in our domain and hopefully we will have established a secure HTTPS connection to our home server.

But it should be noted that one drawback of such an setup can be reduced speed. So choose wisely what applications you want to run and what data you want to access and send through this way of connection.

Resources

For fine tuning and more information I can recommend to visit the Wireguard and Caddy documentation.

0
Subscribe to my newsletter

Read articles from Mahdi Bagheri directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mahdi Bagheri
Mahdi Bagheri

Hey, I am Mahdi. I am currently a computer science student.