Setting up Nginx as a Reverse Proxy on Ubuntu 24.04 LTS

NGINX is a web server that can also be used as a reverse proxy to forward client requests to an application running on a local or remote backend server.

This guide explains how to configure NGINX as a reverse proxy on Ubuntu 24.04 LTS (Noble Numbat).

Prerequisites

Before proceeding, make sure you have:

  • Ubuntu 24.04 LTS server
  • Root or sudo access
  • NGINX installed
  • A domain name pointed to the server
  • A backend application running on a local port, such as 127.0.0.1:8080

Install Nginx

Update the package repository and install NGINX:

sudo apt update
sudo apt install nginx -y

Enable and start NGINX:

sudo systemctl enable --now nginx

Verify the service:

sudo systemctl status nginx

Configure the Reverse Proxy

Create a server block for your domain:

sudo nano /etc/nginx/sites-available/dev.domainhere.info

Add the following configuration:

upstream app {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name dev.domainhere.info;

    location / {
        proxy_pass http://app;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Real-Port $server_port;
        proxy_set_header X-Real-Scheme $scheme;
    }
}

Create a symbolic link to enable the site:

sudo ln -s /etc/nginx/sites-available/dev.domainhere.info /etc/nginx/sites-enabled/dev.domainhere.info

Test the NGINX configuration:

sudo nginx -t

If the configuration test is successful, reload NGINX:

sudo systemctl reload nginx

Configure HTTPS

If an SSL certificate is already available, update the server block:

sudo nano /etc/nginx/sites-available/dev.domainhere.info

Use the following configuration:

upstream app {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name dev.domainhere.info;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name dev.domainhere.info;

    ssl_certificate /etc/letsencrypt/live/dev.domainhere.info/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dev.domainhere.info/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://app;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Real-Port $server_port;
        proxy_set_header X-Real-Scheme $scheme;
    }
}

Test the configuration:

sudo nginx -t

Reload NGINX:

sudo systemctl reload nginx

Configure the Firewall

If UFW is enabled, allow HTTP and HTTPS traffic:

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

Verify the firewall rules:

sudo ufw status

Verify the Backend Application

Make sure the backend application is listening on the configured port:

curl http://127.0.0.1:8080

If the application responds correctly, access the domain in a browser:

https://dev.domainhere.info

The request flow will be:

Client
    |
    v
Nginx
    |
    v
127.0.0.1:8080
    |
    v
Backend Application

Troubleshooting

Check the NGINX configuration:

sudo nginx -t

Check the NGINX service:

sudo systemctl status nginx

View the NGINX error log:

sudo tail -f /var/log/nginx/error.log

View the access log:

sudo tail -f /var/log/nginx/access.log

Verify that the backend application is listening:

sudo ss -lntp | grep 8080

CrownCloud - Get a SSD powered KVM VPS at $4.5/month!
Use the code WELCOME for 10% off!

1 GB RAM / 25 GB SSD / 1 CPU Core / 1 TB Bandwidth per month

Available Locations: LAX | MIA | ATL | FRA | AMS