DEV Community

Big Mazzy
Big Mazzy

Posted on • Originally published at serverrental.store

Nginx Reverse Proxy: Complete Configuration Guide

Nginx Reverse Proxy: Your Gateway to Scalable and Secure Applications

Ever wondered how popular websites handle massive traffic or serve multiple applications from a single server? This guide will walk you through setting up an Nginx reverse proxy, a powerful tool that acts as an intermediary for your web applications. You’ll learn how to configure Nginx to direct incoming traffic to the correct backend service, enhance security, and improve performance.

What is a Reverse Proxy, Anyway?

Imagine you have a popular restaurant with several chefs, each specializing in a different cuisine. A host at the front door takes all customer orders and directs them to the appropriate chef. That host is like a reverse proxy. Instead of customers directly interacting with each chef (your backend applications), they interact with the proxy, which then forwards their request to the correct service.

A reverse proxy is a server that sits in front of one or more web servers, intercepting requests from clients. It forwards those requests to the appropriate backend server and then returns the server's response to the client, making it appear as if the proxy itself is the origin of the response. This offers several benefits, including load balancing, improved security, and SSL termination.

Why Use Nginx as Your Reverse Proxy?

Nginx (pronounced "engine-x") is a high-performance web server and reverse proxy known for its stability, rich feature set, and low resource consumption. Its event-driven architecture makes it exceptionally good at handling a large number of concurrent connections, making it an ideal choice for a reverse proxy. Many developers choose Nginx for its flexibility and the extensive community support available.

Getting Started: Installation

Before we configure Nginx, you need to have it installed on your server. The installation process varies slightly depending on your operating system.

For Debian/Ubuntu:

sudo apt update
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

For CentOS/RHEL:

sudo yum update
sudo yum install nginx
Enter fullscreen mode Exit fullscreen mode

Once installed, you can start and enable the Nginx service:

sudo systemctl start nginx
sudo systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

You can verify the installation by visiting your server's IP address in a web browser. You should see the default Nginx welcome page.

Basic Reverse Proxy Configuration

The core of Nginx configuration lies in its configuration files, typically found in /etc/nginx/. The main configuration file is nginx.conf, but it's best practice to create separate configuration files for each site or proxy configuration in the sites-available directory and then create symbolic links to them in the sites-enabled directory.

Let's create a configuration file for our first reverse proxy. We'll name it my_app.conf.

sudo nano /etc/nginx/sites-available/my_app.conf
Enter fullscreen mode Exit fullscreen mode

Now, let's add a basic configuration to proxy requests to a hypothetical application running on localhost:3000.

server {
    listen 80;
    server_name your_domain.com www.your_domain.com; # Replace with your actual domain

    location / {
        proxy_pass http://localhost: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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Let's break this down:

  • listen 80;: This tells Nginx to listen for incoming HTTP traffic on port 80.
  • server_name your_domain.com www.your_domain.com;: This directive specifies the domain names for which this server block should respond.
  • location / { ... }: This block defines how Nginx should handle requests for the root path (/) of your domain.
  • proxy_pass http://localhost:3000;: This is the key directive. It tells Nginx to forward all requests matching this location to the backend application running at http://localhost:3000.
  • proxy_set_header ...: These directives pass important information from the original client request to the backend server.
    • Host $host: Passes the original Host header.
    • X-Real-IP $remote_addr: Passes the real IP address of the client.
    • X-Forwarded-For $proxy_add_x_forwarded_for: Appends the client's IP address to the X-Forwarded-For header, which is useful if you have multiple proxies.
    • X-Forwarded-Proto $scheme: Indicates whether the original request was HTTP or HTTPS.

To enable this configuration, create a symbolic link:

sudo ln -s /etc/nginx/sites-available/my_app.conf /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

Test your Nginx configuration for syntax errors:

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

If the test is successful, reload Nginx to apply the changes:

sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Now, when you visit your_domain.com in your browser, Nginx will forward the request to your application running on localhost:3000.

Serving Multiple Applications from One Server

One of the most common use cases for a reverse proxy is to host multiple applications on a single server. This is particularly useful when you don't want to manage separate IP addresses or ports for each application. Let's say you have a Node.js app on localhost:3000 and a Python app on localhost:5000.

You can configure Nginx to route traffic based on the domain name.

First, create a configuration file for your Python app:

sudo nano /etc/nginx/sites-available/python_app.conf
Enter fullscreen mode Exit fullscreen mode

Add the following content:

server {
    listen 80;
    server_name python_app.your_domain.com; # Replace with your subdomain

    location / {
        proxy_pass http://localhost:5000;
        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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, ensure your my_app.conf is set up for your Node.js app:

server {
    listen 80;
    server_name node_app.your_domain.com; # Replace with your subdomain

    location / {
        proxy_pass http://localhost: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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Remember to enable these configurations and reload Nginx as shown previously.

This setup allows you to manage multiple applications efficiently. For hosting your applications, consider providers like PowerVPS or Immers Cloud, which offer robust infrastructure suitable for running these services.

Enhancing Security with SSL/TLS

Serving your applications over HTTPS is crucial for security and user trust. Nginx makes it straightforward to implement SSL/TLS termination. This means Nginx handles the encryption and decryption of traffic, and then forwards unencrypted traffic to your backend applications.

The easiest way to obtain and manage SSL certificates is by using Let's Encrypt, a free, automated, and open certificate authority. You can use the Certbot tool to automate this process.

First, install Certbot and its Nginx plugin:

For Debian/Ubuntu:

sudo apt install certbot python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode

For CentOS/RHEL:

sudo yum install epel-release
sudo yum install certbot python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode

Once installed, run Certbot to obtain and install certificates for your domain. Make sure your domain's DNS records point to your server's IP address.

sudo certbot --nginx -d your_domain.com -d www.your_domain.com
Enter fullscreen mode Exit fullscreen mode

Certbot will automatically modify your Nginx configuration to enable HTTPS and set up automatic certificate renewals. It will also prompt you to redirect HTTP traffic to HTTPS.

Your Nginx configuration file (my_app.conf in our example) will be updated to look something like this:

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;

    # Redirect HTTP to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name your_domain.com www.your_domain.com;

    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost: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;
    }
}
Enter fullscreen mode Exit fullscreen mode

This configuration directs all traffic to port 443 (HTTPS), handles SSL termination, and then proxies the requests to your backend application.

Load Balancing with Nginx

As your application grows, you might need to run multiple instances of your backend service to handle increased traffic. Nginx can act as a load balancer, distributing incoming requests across these multiple backend servers.

First, define your backend servers in an upstream block:

upstream my_backend_servers {
    server backend1.your_domain.com:3000;
    server backend2.your_domain.com:3000;
    server backend3.your_domain.com:3000;
}

server {
    listen 80;
    server_name your_domain.com;

    location / {
        proxy_pass http://my_backend_servers; # Use the upstream name here
        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;
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  • upstream my_backend_servers { ... }: This block defines a group of servers named my_backend_servers. Nginx will distribute traffic among these servers using a round-robin algorithm by default.
  • proxy_pass http://my_backend_servers;: The proxy_pass directive now points to the name of the upstream group.

Nginx also supports other load balancing methods like least-connected and IP hash. You can also add health checks to your upstream servers to automatically remove unhealthy servers from the pool.

For managing your server infrastructure, a resource like the Server Rental Guide can be an invaluable reference.

Advanced Configurations and Tips

1. Caching: Nginx can cache responses from your backend servers, reducing the load on your applications and speeding up delivery to clients.

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

server {
    # ... other configurations ...

    location / {
        proxy_pass http://localhost:3000;
        proxy_cache my_cache; # Enable caching
        proxy_cache_valid 200 302 10m; # Cache successful responses for 10 minutes
        proxy_cache_valid 404 1m;      # Cache 404s for 1 minute
        proxy_cache_key "$scheme$request_method$host$request_uri";
        add_header X-Cache-Status $upstream_cache_status; # Helpful for debugging
        # ... other proxy_set_header directives ...
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Rate Limiting: Protect your applications from abuse by limiting the number of requests a client can make within a certain time frame.


nginx
http {
    # ... other http configurations ...

    limit_req_zone $binary_remote_addr zone=mylimit:
Enter fullscreen mode Exit fullscreen mode

Top comments (0)