Setting up a Home Server Connection via VPN (Wireguard) and a Cloud VPS
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.
Installing the Server Software (Ubuntu Server)
Creating a dedicated user and granting it sudo access
Providing root and user with strong passwords
Upgrading all available packages
Removing SSH permission for root user
Allowing only SSH access via SSH key
Changing default SSH port to reduce Bot noises
Installing and activating unattended-upgrades
Installing and enabling fail2ban
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.
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.