Configuring Nginx as a reverse proxy for backend applications
Introduction
In modern server setups, applications rarely talk directly to the internet. Instead, a reverse proxy sits in front of them and handles incoming client requests. Nginx is one of the most popular tools for this job because it is fast, reliable, and easy to configure. In this tutorial, you will learn how to configure Nginx as a reverse proxy for a backend application running on the same server.
What is a reverse proxy?
A reverse proxy is a server that:
- Accepts requests from clients (browsers, APIs, etc.)
- Forwards those requests to a backend application
- Sends the backend's response back to the client
The client never talks directly to the backend application.
Reverse proxy vs direct access
Without a reverse proxy:
Client ---> Backend application (port 3000)
With a reverse proxy:
Client ---> Nginx (port 80, 443) ---> Backend application (port 3000)
Why use Nginx as a reverse proxy?
Using Nginx in front of your application allows you to:
- Expose only ports 80/443 to the internet
- Hide backend services from direct access
- Terminate HTTPS (TLS) in one place
- Add logging, access control, and rate limiting
- Run multiple applications on one server
For system administrators, this means better security and easier management.
Scenario used in this tutorial
To keep things simple, we will use the following setup:
- Nginx listens on port
80 - Backend application listens on
127.0.0.1:3000 - Requests to
http://example.comare forwarded to the backend
Traffic flow diagram
[ Browser ] | v [ Nginx example.com:80,443 ] | v [ Backend app 127.0.0.1:3000 ]
Prerequisites
Before starting, make sure you have:
- A Linux server with latest Debian stable
- Root or sudo access
- A backend application already running (for example, a Node.js, Python, or Java app)
- Basic familiarity with the Linux terminal
Install Nginx
Update package lists and install Nginx and curl (for setup testing):
sudo apt update
sudo apt install nginx curl
Check that Nginx is running:
systemctl status nginx
You should see "active (running)" in the output.
Test Nginx locally:
curl http://localhost
If Nginx is working, you'll receive the default welcome page.
Understand Nginx configuration structure
Nginx configuration files are usually stored in /etc/nginx/. Important directories:
/etc/nginx/nginx.conf— main configuration file/etc/nginx/sites-available/— site configuration files (not active)/etc/nginx/sites-enabled/— enabled site configurations (symbolic links)
Nginx reads configuration files from the sites-enabled folder, not directly from sites-available. It's recommended to create site configuration files in sites-available and then create symbolic links to them in sites-enabled.
Create a reverse proxy configuration
Create a new site file
sudo nano /etc/nginx/sites-available/reverse-proxy.conf
Add the reverse proxy configuration
server { listen 80; server_name example.com; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Understand the configuration
Server block
server { listen 80; server_name example.com; }
listen 80;— Nginx listens for HTTP traffic on port 80server_name example.com;— domain name this server block responds to
Location block
location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
location /— matches all incoming URLsproxy_pass— forwards requests to the backend application
Proxy headers
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
These headers ensure the backend knows:
- The original domain name
- The client's real IP address
- Whether the request was HTTP or HTTPS
Without these headers, backend applications may log incorrect client information.
Enable the configuration
Disable the default Nginx site to avoid conflicts on port 80:
sudo rm /etc/nginx/sites-enabled/default
Create a symbolic link to enable the site:
sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/
Test the configuration for syntax errors:
sudo nginx -t
If the test is successful, reload Nginx:
sudo systemctl reload nginx
Test the reverse proxy
Test from the server:
curl http://example.com
Open http://example.com in a browser to test. You should receive a response from your backend application, not Nginx's default page. If everything is configured correctly, the backend application will load.
How the request is processed
- Client sends request to example.com
- Nginx receives request on port 80
- Nginx forwards request to 127.0.0.1:3000
- Backend processes the request
- Response goes back through Nginx
- Client receives the response
Common mistakes and troubleshooting
Backend not running
- Ensure the application is running
- Confirm the correct port
ss -tuln | grep 3000
Wrong proxy_pass address
- Always include
http:// - Ensure the IP and port are correct
Forgetting to reload Nginx
After every config change:
sudo systemctl reload nginx
Firewall blocking access
Ensure port 80 is open:
sudo ufw allow 80
Optional improvements
Once the reverse proxy is working, consider:
- Enabling HTTPS with Let's Encrypt
- Running multiple backend applications
- Adding access logs and error logs
- Configuring load balancing
- Supporting WebSocket connections
HTTPS Configuration
In production environments, you should always use HTTPS instead of HTTP. HTTPS encrypts traffic between the client and your server, protecting passwords, API tokens, cookies, and other sensitive data. Nginx supports HTTPS using SSL/TLS certificates. In this section, you will learn:
- What Certbot is
- How to install Certbot
- How Certbot automatically modifies Nginx configuration
- How to configure Nginx manually using a purchased certificate
What is Certbot?
Certbot is a tool that automatically obtains and installs free SSL/TLS certificates from Let's Encrypt. It can:
- Request a free certificate
- Verify domain ownership
- Automatically configure Nginx
- Set up automatic certificate renewal
For beginners and most production environments, Certbot is the easiest and safest way to enable HTTPS.
Installing Certbot
Update package lists:
sudo apt update
Install Certbot and the Nginx plugin:
sudo apt install certbot python3-certbot-nginx
The python3-certbot-nginx package allows Certbot to automatically modify your Nginx configuration.
Obtaining and Installing a Certificate
Before running Certbot, make sure:
- Your domain name points to your server's public IP address
- Nginx is running
- Ports 80 and 443 are open in the firewall
Run:
sudo certbot --nginx
Certbot will:
- Ask which domain you want to secure
- Verify domain ownership
- Automatically update your Nginx configuration
- Reload Nginx
Certbot automatically modifies your Nginx configuration. It typically adds a new server block for port 443 (HTTPS), adds SSL certificate paths, configures an HTTP to HTTPS redirect if you choose that option, and adds recommended SSL settings.
Example configuration added by Certbot:
server { listen 443 ssl; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Certbot may also modify the HTTP block to redirect traffic:
server { listen 80; server_name example.com; return 301 https://$host$request_uri; }
Because Certbot edits configuration files automatically, it is recommended to:
- Keep backups of your configuration
- Understand what changes were made
- Always test configuration after changes
Test configuration:
sudo nginx -t
Automatic Certificate Renewal
Let's Encrypt certificates are valid for 90 days. Certbot automatically installs a renewal timer. You can test renewal with:
sudo certbot renew --dry-run
If configured correctly, renewal will happen automatically without downtime.
Using a Purchased SSL Certificate
If you buy an SSL certificate from a certificate authority (CA), you must configure Nginx manually. After purchase, you usually receive:
- A certificate file (e.g.,
example.com.crt) - A private key (
example.com.key) - A CA bundle file (
ca_bundle.crt)
Create a secure directory:
sudo mkdir -p /etc/nginx/ssl
sudo chmod 700 /etc/nginx/ssl
Copy your certificate files into this directory.
Example HTTPS configuration with a purchased certificate:
server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_trusted_certificate /etc/nginx/ssl/ca_bundle.crt; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Add HTTP to HTTPS redirect:
server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; }
Reload Nginx after manual configuration:
sudo nginx -t
sudo systemctl reload nginx
For novice system administrators, Certbot is strongly recommended unless your organization requires commercial certificates.
Summary
In this tutorial, you learned:
- What a reverse proxy is and why it's useful
- How Nginx forwards requests to backend applications
- How to create and enable a reverse proxy configuration
- How to test and troubleshoot common issues
- How to configure HTTPS
Nginx reverse proxying is a foundational skill for system administrators and is widely used in production environments.