Networking

Nginx Reverse Proxy: Secure HTTPS, Headers, and Rate Limiting

Nginx Reverse Proxy: Secure HTTPS, Headers, and Rate Limiting

Exposing web services and APIs to the public carries significant risks. Without adequate protection, even a robust application can succumb to DDoS attacks or intentional abuse. I recall an incident where, after launching a crucial public API, the backend crashed in less than 48 hours. Two million requests from just three IP addresses had saturated resources. The solution? A quickly configured Nginx as a reverse proxy, with rate limiting, blocked the malicious traffic and restored stability. This event underscored the critical importance of a well-configured reverse proxy as the first line of defense. In this guide, we will explore how to configure Nginx to act not only as an efficient reverse proxy but also as a robust security guardian, implementing HTTPS, advanced security headers, and rate limiting—essential for any production environment in 2026.

Prerequisites / Test Environment

To follow this guide, you will need a Linux server (preferably Ubuntu Server 24.04 LTS or CentOS Stream 9) with root access or sudo privileges. Ensure Nginx is installed. If not, you can install it with sudo apt update && sudo apt install nginx on Ubuntu or sudo dnf install nginx on CentOS. You will also need a registered domain pointed to your server for HTTPS configuration with Let’s Encrypt. The test environment includes a simple HTTP backend (e.g., a Node.js or Python application responding on a specific port, such as 8080) to test proxying.

Why a Reverse Proxy: Security, Caching, Load Balancing

A reverse proxy is a server that sits between clients and backend servers. Instead of clients communicating directly with your application server, all requests pass through the reverse proxy. This approach offers numerous benefits that go far beyond simple traffic routing.

From a security perspective, the reverse proxy acts as an application-level firewall, hiding the internal network architecture, filtering malicious traffic, and handling SSL/TLS termination. According to a 2025 Cloudflare report, 68% of application-layer DDoS attacks were effectively mitigated by reverse proxy services or WAFs. It also offers a reduced attack surface, as only the reverse proxy is directly exposed to the internet.

For performance, a reverse proxy can implement caching mechanisms for static or dynamic responses, reducing the load on backend servers and improving response times for users. Furthermore, it is fundamental for load balancing, distributing requests among multiple application servers to ensure high availability and scalability, preventing a single server from becoming a bottleneck. This is crucial in environments handling thousands of requests per second.

Nginx as Reverse Proxy: Basic Server Block

Nginx is an excellent choice for a reverse proxy due to its event-driven architecture and its ability to handle a high number of concurrent connections with low resource consumption. The basic configuration is surprisingly simple. We will create a configuration file for our domain (e.g., /etc/nginx/sites-available/yourdomain.conf) and enable it by creating a symlink in /etc/nginx/sites-enabled/.

Here’s an Nginx server block that routes HTTPS traffic on port 443 to an HTTP backend listening on port 8080:

# /etc/nginx/sites-available/yourdomain.conf

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}

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

    # SSL/TLS Certificates (will be generated by Certbot)
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;

    # Secure SSL/TLS parameters
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1h;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    location / {
        proxy_pass http://backend:8080; # Replace 'backend' with your application server's IP/hostname
        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;

        # Buffering and timeout settings (see dedicated section)
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
        proxy_read_timeout 90s;
        proxy_send_timeout 90s;
        proxy_connect_timeout 90s;
    }
}

Enable the configuration and reload Nginx:

sudo ln -s /etc/nginx/sites-available/yourdomain.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

HTTPS with Let’s Encrypt and Certbot (Auto-Renewal)

Traffic encryption is fundamental. Let’s Encrypt offers free and recognized SSL/TLS certificates, while Certbot automates their generation and renewal. This ensures that traffic between the client and Nginx is always protected.

Install Certbot and the Nginx plugin:

sudo apt install certbot python3-certbot-nginx # For Ubuntu/Debian
# sudo dnf install certbot python3-certbot-nginx # For CentOS/RHEL

Generate the certificate for your domain. Certbot will automatically modify your Nginx configuration to include the certificates and HTTP to HTTPS redirection:

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot also configures a cron job or systemd timer for automatic certificate renewal, which typically occurs every 60-90 days, well before the 90-day expiration. You can test the renewal mechanism with:

sudo certbot renew --dry-run

This ensures your site remains accessible via HTTPS without interruptions.

Security Headers: HSTS, X-Frame-Options, CSP

Beyond encryption, HTTP security headers are a powerful tool to mitigate client-side attacks. We will add them to the Nginx HTTPS server block.

  • Strict-Transport-Security (HSTS): Forces browsers to use only HTTPS connections for your domain, preventing SSL/TLS downgrade attacks. The max-age value indicates how long the browser should remember this setting (31536000 seconds = 1 year).
  • X-Frame-Options: Prevents clickjacking by stopping your pages from being embedded in an