I Finally Figured out Nginx Reverse Proxy

After getting my cloud server, the natural first step was to build and host my personal website (or web app!) on it.

That got me into the rabbit hole of learning about proxies, reverse proxies, A records, SSL certificates, etc.

It took me a couple of hours to comb through dense computer networking and internet-routing blog posts, but I eventually figured it out.

Now, if you go to irtizahafiz.com or www.irtizahafiz.com, you will see a working version of my NextJS example app — coming to you straight from my Digital Ocean server!

In this blog post, I plan on taking you through a step-by-step tutorial helping you achieve the same thing that I did, but hopefully without the 2-3 hours of learning that I went through.

What Will You Learn?

I don’t want to waste anyone’s precious time. So, take a look at the topics I will cover below, and read on if it’s of value to you.

    Connecting your domain to your server

    Installing and configuring Nginx

    Exposing your internal web app (NextJS, ReactJS, Python Flask, etc) to the public internet

    Proxies and reverse proxies

    Creating SSL certificates for your domain

    Serving your website through secured HTTPS

If you are still interested, let’s get started.

Connect Your Domain to Your Server

The first step requires the least number of steps.

You need 2 things:

    Access to your Domain Dashboard (GoDaddy, Namecheap, etc)

    The public IP address of your server machine

Then, you go to the DNS management in your Domain Dashboard and add an “A” record with the value set to your server’s IP address.

It will take you 2 minutes to do this!

Running Your Web App of Choice

Now, onto the more exciting part.

It doesn’t matter what framework you use to run your web app locally — NextJS, ReactJS, Python Flask, Python Django, etc.

In all cases, you do the same thing. You run your web app on a given port in your machine.

In my case, that was running a NextJS app in port 3000.

You can do something as simple as:


    npm run start
  

And you will have your web app running on your local machine. You can access it from within your WiFi network, but not from outside.

Installing Nginx Web Server

To serve your web app to public internet users, you need to use a web server. Then, you have to proxy the incoming web server request to your locally running app.

Let me explain.

First, let’s install Nginx on your server.


    sudo apt update
    sudo apt install nginx
  

Once successfully installed, you will find the relevant Nginx config files below:


   /etc/nginx
  

With a working Nginx, any request coming to your server’s port 80 (by default) will be served by a static Nginx HTML page.

Next, we will replace this static page with your locally running web app.

Configuring Nginx

The default Nginx configuration is housed in the directory:


   /etc/nginx/sites-available/default
  

As the first step, we will delete the default config, and create our custom config in a file called myserver.config.

Here’s the sequence of commands:


    sudo unlink /etc/nginx/sites-available/default
    rm /etc/nginx/sites-enabled/default
    cd /etc/nginx/sites-available
    touch myserver.config
  

What are we doing?

    Unlinking the default config

    Deleting the mirrored version of the default config

    Creating our custom config file called myserver (will be populated soon)

Proxying Requests to Your Web App

Then, write the following Nginx config inside your newly created myserver.config file.


    server{
        server_name irtizahafiz.com;
        location / {
            proxy_set_header Host $host;
            proxy_pass http://127.0.0.1:3000;
        }
    }
  

This will do the following:

    Accepts requests coming to the domain irtizahafiz.com

    Proxies the request to the machine’s port 3000 (whatever port your web app is running on)

    Returns to the user response from your web app

Finally, Restart Nginx

Once all the steps are complete, restart Nginx:


    sudo systemctl restart nginx
  

Now, any HTTP request coming to irtizahafiz.com will be routed and served by your locally running web application.

Works…But Not Through HTTPS

If you have been following closely, you will see that we haven’t talked about the SSL certificate yet.

Also, if you go to your linked website — irtizahafiz.com in my case — you will see that it’s being served through HTTP, not HTTPS.

Some browsers, such as Safari, might even refuse to show you the web page because of security concerns.

Let’s fix that.

Getting A Free SSL Certificate

I was always under the impression that you have to pay for SSL certificates.

It didn’t help that all the domain management websites — GoDaddy, Namecheap — even try to sell you SSL certificates for $8/month, $10/month, etc.

When you are hosting your web app on your machine, you can instead get SSL certificates for FREE!

There’s a brilliantly written blog post by Certbot that you can follow to get a free automatically renewing SSL certificate for your domain.

Please check out the linked blog post, but to make it easy to follow along, I will list the sequence of bash commands below:


    sudo snap install --classic certbot
    sudo ln -s /snap/bin/certbot /usr/bin/certbot
    sudo certbot --nginx
  

Certbot will make some changes to your Nginx config file — in our tutorial the myserver.config file that we created.

It essentially creates some private keys, stores them in your Keychain, and then links them to your domain.

Now, your traffic will be served from a secured port 443 rather than the default port 80.

Closing Thoughts

Overall, the above configuration ensures that all traffic to irtizahafiz.com is redirected to HTTPS and proxied to a backend server running on port 3000.

I hope this guide was helpful.

If you have more questions, drop a comment below. If you found this valuable, give me a follow and subscribe to my newsletter.

Irtiza Hafiz

;