This is a guide to create a reverse proxy using a Virtual Private Server, or VPS so that you can access internally hosted services.

# My Situation

I host some services from my home lab that I access remotely, such as Home Assistant.

In my previous house, I was the account owner for the internet. I was able to get a static IP, and have the ISP open incoming ports 80 and 443 for web traffic.

Now I lived in shared accommodation which has an included internet connection, in the form of an Ethernet cable coming out the wall. Everyone just uses the same LAN.
I do have access to the router, but to maintain an environment that I can ‘home lab freely' in, I wanted to set up my own LAN.

I can do this while still utilising the shared connection. We have fiber and my services are not bandwidth heavy.

I have configured a router of my own with, with all traffic sent via Mullvad VPN.

Now I need to be able to access my internal services externally, using this same internet connection.

# The Plan

There are some ways I can do this:

- A VPN to my network, such as OpenVPN, SSL VPN, WireGuard, or even an overlay network such as TailScale.
  This however this would mean I have to install a VPN app first and configure it. What if someone else wants to watch videos too? They now have to install some VPN app on their TV. Too much work! I just want to be able to browse to a domain to access the site.
- Get a VPN provider with a static IP. This is not ideal as most VPN providers do not provide static IPs, and if they do, they are quite costly.
- Use a Cloudflare Tunnel. I have used this in past, it is free, however it is not overly well suited for streaming video.
  I am working towards a goal of being able to stream 4k video remotely.

Instead, I am going to build my own cloud reverse proxy host.

This makes use of a Virtual Private Server (VPS) to run Nginx Reverse Proxy Manager. The VPS will have access to the services running on my internal network via a WireGuard VPN.

This will connect to my home network with a WireGuard VPN, and will run Reverse Proxy Manager to manage incoming web connections.

To make this, I need a few things:

1. A VPS. There are many to choose from. In the end I went with a server from OVHcloud.
   - WireGuard is efficient compared to other VPN protocols, so the server does not have to be too powerful.
   - Be sure to check how much network traffic the VPS allows. Lots have limits, which may or may not be enough for your use case. I am streaming 4k video so I am looking for unlimited bandwidth.
2. A router that allows for new VPN interfaces to be created. I use opnSense for my router which does allow this.

# VPS Setup

First I need to find a VPS provider. As I said before, I went with a server from OVHcloud.

The server I chose (VLE-4) costs $11 US per month.

- 4 vCores
- 4GB RAM
- 80 GB NVMe SSD
- 1 Gbps unmetered connection
- 1x Static IPv4 address
- Anti-DDoS Protection Included
- Ubuntu 23.04

Once I purchased the server and it had provisioned, I connected and set up a few things.

1. Updated to Ubuntu 23.10
2. Enabled Key-Based only login: See this guide: How To Configure SSH Key-Based Authentication on a Linux Server
3. Enable UFW Firewall
   - Allow port 22(SSH), 51820/UDP(WireGuard), 443(HTTPS)
     `sudo ufw allow <PORTS>`
   - Enable UFW
     `sudo ufw enable`
4. Enabled the edge firewall on my hosting provider.

# VPN Setup

After this it is time to install WireGuard VPN on the VPS.

For this, I mostly followed this guide: How To Set Up WireGuard on Ubuntu 20.04

I recommend reading that guide as there are some decisions I made that I do not explain, but at a high level, I followed through the steps up to the end of step 6:

- Install WireGurad
- Create a new WireGuard private and public key pair:
  `wg genkey | sudo tee /etc/wireguard/private.key`
  `sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key`
- Chose a new IP range, I chose 10.0.20.0/24
- Created a new WireGuard Configuration file:
  `/etc/wireguard/wg0.conf`

I was then able to start the WireGuard server, however I have still not yet added any peers. The guide explains how to do this on another Linux server, but in this case, I do not want to do that. Instead of step 7:

This is done in the WireGuard Instance settings in my Router:

Be sure to check the ‘Disable routes’ option in the Instance, as I will do this manually
For the gateway, it does not matter, just as long as it is unique.

Then in the Peers tab:

The Pubic Key is the Public key from the WireGuard Server on the VPS

The Endpoint Address is the public IP of the VPS.

After this we can continue with the Digital Ocean guide from step 8.

The below command is then run to add the new opnSense peer to the Wireguard server.

`sudo wg set wg0 peer <PUBLIC KEY> allowed-ips 10.0.20.2`

After doing this, I can see the VPN connection is up:

In the end, my /etc/wireguard/wg0.conf file looked like:

    [Interface]
    Address = 10.0.20.1/24
    SaveConfig = true
    PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    ListenPort = 51822
    PrivateKey = <SERVER PRIVATE KEY>

    [Peer]
    PublicKey = <PEER PUBLIC KEY>
    AllowedIPs = 10.0.20.0/24, 10.0.10.0/24
    PersistentKeepalive = 25

# Network Setup

Now an interface needs to be created on my router for the new VPN connection so that I can configure firewall rules to allow and deny access.

For opnSense, this is as simple as going to Interfaces > Assignments, and adding the new interface

Then configure the settings as below:

You do not need to configure a IPv4 address, as this will automatically get the IP address specified of the Instance Tunnel Address.

After this, I created the below firewall rule so that the new WireGuard interface could access the LAN.

If you have any strange issues, check the routing table (System > Routes > Status) to see if there are any old entries that need to be deleted.

# Reverse Proxy

For the reverse Proxy I am using Nginx Reverse Proxy Manager running in a Docker container.

First, install Docker: Install Docker Engine on Ubuntu

Then I installed Portainer to give a nice webUI to manage Docker: Install Portainer CE with Docker on Linux

Then in Portainer I made a new stack (docker compose).

I was then able to log into Reverse Proxy Manager and create the my domains in Reverse Proxy Manager

I also needed to point these domains to the public IP of my VPS.

Once this was done, I was able to access the internal services via my domain name.
For example, this website!