nginxconfigserversslproxydevopsweb server

Nginx Configuration Guide: Server Blocks, Reverse Proxies, and SSL

How to configure nginx for static sites, Node.js apps, PHP, and reverse proxies — with SSL termination, security headers, and performance settings.

8 min read

Related Tool

Nginx Config Generator

Open tool

Nginx Basics

Nginx (pronounced "engine-x") is a high-performance web server and reverse proxy used by a large share of the world's busiest sites. Unlike Apache, which spawns a thread per connection, nginx uses an event-driven, asynchronous architecture that handles thousands of concurrent connections with low memory usage.

Configuration lives in /etc/nginx/ — the main file is nginx.conf, and individual site configs go in /etc/nginx/sites-available/ with symlinks to /etc/nginx/sites-enabled/.

Server Blocks

A server block is nginx's equivalent of Apache's VirtualHost — it defines how nginx handles requests for a particular domain or IP. A minimal static site block:

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/example;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

try_files tells nginx to look for a file matching the URI, then a directory, then return 404 if neither exists.

HTTPS with SSL Termination

With Let's Encrypt (via Certbot), enabling HTTPS is straightforward. After running Certbot, your config gains SSL directives and a redirect block:

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;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ...
}

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

Reverse Proxy for Node.js

To proxy requests to a Node.js app running on port 3000:

location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

The Upgrade and Connection headers are needed for WebSocket support.

Security Headers

Adding security headers to every response hardens your site against common attacks:

add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";

HSTS (Strict-Transport-Security) tells browsers to only connect over HTTPS for the specified duration. Only enable it once HTTPS is fully configured — it is difficult to undo.

Gzip Compression

Enable gzip to reduce response sizes for text-based assets:

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 256;

Rate Limiting

Protect against brute force and abuse:

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api/ {
    limit_req zone=api burst=20 nodelay;
}

Testing Your Config

Before reloading nginx, test the configuration syntax: nginx -t. An error in the config file will prevent nginx from reloading, and if you reload with a broken config, nginx continues serving traffic with the old config — but a restart (e.g., after a server reboot) will fail. Always run nginx -t before systemctl reload nginx.

Generating Configs

Nginx configs involve a lot of repetitive boilerplate. A generator handles the common patterns — reverse proxy, static site, PHP-FPM, SSL — and produces a correct starting point that you can refine. The DevHexLab Nginx Config Generator produces a complete server block for your chosen setup with SSL, gzip, and security headers included.