Hosting a site from a home server behind CGNAT

Aug 23, 2023

For simplicity, I often use Cloudflare Tunnel to make my locally hosted site available to the internet, including this blog. However, Cloudflare Tunnel is unsuitable for file-sharing programs like Pingvin Share due to Cloudflare limitation for file upload.

So I’m using Tailscale and a VPS with public IP for this project and setting up a reverse proxy. I won’t touch on how to install Pingvin Share in this guide. For this, you can refer to their GitHub. Instead, I will show an example using a simple html site.

Let’s begin!

Prerequisites

  1. A server with Ubuntu 22.04
  2. A VPS with a public IP and Ubuntu 22.04 installed
  3. A Tailscale account
  4. A domain

Setting up Nginx on your home server

To start, install Nginx using the following command:

sudo apt update && sudo apt install nginx -y

Then start Nginx and enable the service to run at boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Now we can check if Nginx is running correctly by running this command:

sudo systemctl status nginx

The result should look something like this:

* nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-08-23 11:36:38 UTC; 1min 32s ago
       Docs: man:nginx(8)
   Main PID: 11718 (nginx)
      Tasks: 2 (limit: 38186)
     Memory: 3.8M
        CPU: 76ms
     CGroup: /system.slice/nginx.service
             |-11718 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             `-11721 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""

Aug 23 11:36:38 reverse-proxy-vps systemd[1]: Starting A high performance web server and a reverse proxy server...
Aug 23 11:36:38 reverse-proxy-vps systemd[1]: Started A high performance web server and a reverse proxy server.

Now, enter the IP address of your server in a web browser, and if everything is running correctly, you should see the Nginx default page.

Nginx default page

Creating a simple HTML site

So that we can have an easier time later knowing that our reverse proxy setup works, we can modify the default Nginx page into a simple hello-world page. First, remove the default Nginx page using this command:

sudo rm /var/www/html/index.nginx-debian.html

Then, create a new index.html file:

sudo nano /var/www/html/index.html

Then add the following code to the file:

<!DOCTYPE html>
<html>
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <p>Hello, World!</p>
    </body>
</html>

Try accessing the server IP address in your browser again, and you shall be greeted with the Hello World page:

Hello world

Installing Tailscale to connect the local server and VPS

Installing Tailscale is dead simple; all you need to do is run this command and let it complete:

curl -fsSL https://tailscale.com/install.sh | sh

Once done, run this command to start tailscale.

sudo tailscale up

Then log in using the provided link. You must do this on both the VPS and local server for this to work. Both instances also must be under the same Tailscale account.

Setting up the reverse proxy on the VPS

We’ll also need to install Nginx on the VPS. Rerun this command:

sudo apt update && sudo apt install nginx -y

Then start Nginx and enable the service to run at boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Enter your VPS IP address to your web browser, and you should see the same default page for Nginx as seen in the previous step. Now point your domain to your VPS IP address using A record. I’ll use test.njeng.at for this tutorial. To check if the setup is working, try accessing the domain and see the Nginx default page, too.

Domain test

Now, we can proceed with the reverse proxy! Use this command to disable the default page on the VPS:

sudo unlink /etc/nginx/sites-enabled/default

Then, create a new Nginx configuration file for the reverse proxy:

sudo nano /etc/nginx/sites-available/your_domain

Insert the following into the new configuration file:

server {
    listen 80;
    listen [::]:80;

    server_name your_domain www.your_domain;
        
    location / {
        proxy_pass http://local_server_tailscale_IP;
        include proxy_params;
    }
}

Don’t forget to replace your_domain and local_server_tailscale_IP.

Next, enable this configuration by creating a symbolic link to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

Then reload Nginx:

sudo systemctl restart nginx

If there is no error, go ahead and recheck your domain. You will see the Hello World page we hosted on our local server!

Reverse proxy working

That’s it! I hope that helps! :smile: