KAHIBARO
Discord Login Register

22.5. Nginx

Why Nginx Matters for Backend Developers

Nginx is one of the most popular web servers in the world. For backend developers it usually sits in front of your application server, for example Uvicorn or Gunicorn, and works as a reverse proxy, TLS terminator, static file server, and more.

In this chapter you will learn how Nginx fits into backend architectures and how to read and write basic Nginx configuration. You do not need to become a full Nginx expert, but you must be comfortable enough to:

Key idea: In production, your backend app usually does not listen directly on port 80 or 443. Instead, Nginx listens on these ports, then forwards requests to your app running on an internal port such as 8000.


Typical Nginx Use Cases in Backends

Reverse proxy in front of an application server

The most common pattern:

  1. Nginx listens on port 80 (HTTP) and 443 (HTTPS).
  2. Your backend app server, such as Uvicorn or Gunicorn, listens on port 8000 on the same machine or another internal machine.
  3. Nginx forwards incoming requests to http://127.0.0.1:8000 or to a private IP.

High level flow:

  1. Client sends request to https://api.example.com/users.
  2. Nginx receives the request on port 443.
  3. Nginx decrypts TLS.
  4. Nginx forwards a plain HTTP request to your app server on port 8000.
  5. Backend app processes request and returns response to Nginx.
  6. Nginx sends response back to client over HTTPS.

Simple diagram:

ComponentPortRole
Browser443Client
Nginx80/443Public entry point, proxy
App server8000Runs your Python backend
Database5432Internal, not exposed

Serving static files and media

Nginx is very efficient at serving static content such as:

Typical pattern:

This reduces load on your application and improves performance.

Terminating TLS (HTTPS)

Doing TLS in your Python app is possible, but in production it is common to:

Benefits:

How Nginx Configuration Is Structured

Nginx configuration is usually in /etc/nginx/nginx.conf which includes files like /etc/nginx/conf.d/.conf or /etc/nginx/sites-enabled/.

Typical file structure:

nginx
user www-data;
worker_processes auto;
events {
    worker_connections 1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile on;
    include /etc/nginx/conf.d/*.conf;
}

Inside http you define server blocks. Each server handles one virtual host (for example one domain).

Basic server block

nginx
server {
    listen 80;
    server_name example.com;
    location / {
        return 200 'Hello from Nginx';
    }
}

Important parts:

Nginx as a Reverse Proxy for a Backend API

Simple reverse proxy configuration

Example: you have a FastAPI app served by Uvicorn at http://127.0.0.1:8000.

nginx
server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
    }
}

Explanation of key directives:

Important rule: When using Nginx as a reverse proxy, always forward the real client IP and the protocol to your backend with X-Real-IP and X-Forwarded-Proto. Without this, your app sees Nginx as the client.

Example: splitting API and docs

Assume:

nginx
server {
    listen 80;
    server_name api.example.com;
    # Static docs
    location /docs/ {
        root /var/www/api-docs;
        try_files $uri $uri/ =404;
    }
    # Everything else goes to backend
    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
    }
}

Requests to:

Serving Static Files with Nginx

Static files can be served with root or alias.

Example directory layout

text
/var/www/myapp/
  static/
    css/
      main.css
    js/
      app.js
    images/
      logo.png

Using `root`

nginx
location /static/ {
    root /var/www/myapp;
    try_files $uri $uri/ =404;
}

This maps:

Because root adds the location path to the root:

Using `alias`

nginx
location /assets/ {
    alias /var/www/myapp/static/;
    try_files $uri $uri/ =404;
}

This maps:

Because alias replaces the location path with the alias path:

Table summary:

DirectiveURL path exampleConfig base pathFinal file path
root/static/css/main.css/var/www/myapp/var/www/myapp/static/css/main.css
alias/assets/css/main.css/var/www/myapp/static//var/www/myapp/static/css/main.css

Rule of thumb:
Use root when your location path matches the directory structure.
Use alias when you want to map a URL path to a completely different directory path.


Basic HTTPS with Nginx

Nginx is often responsible for HTTPS termination.

Minimal HTTPS configuration

Assume you already have certificates:

nginx
server {
    listen 80;
    server_name api.example.com;
    # Redirect all HTTP to HTTPS
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    # Optional basic security settings
    ssl_protocols TLSv1.2 TLSv1.3;
    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
    }
}

Here:

  1. First server block listens on port 80 and sends a redirect to HTTPS.
  2. Second server block listens on 443 with SSL and forwards to your backend.

Handling Common Concerns: Timeouts, Uploads, and Buffers

As your API grows, you will need to adjust some defaults.

Timeouts

By default Nginx expects the backend to respond quickly. For slow endpoints, such as large reports, you may need to increase timeouts.

Example:

nginx
location /reports/ {
    proxy_read_timeout 300s;
    proxy_connect_timeout 60s;
    proxy_send_timeout 300s;
    proxy_pass http://127.0.0.1:8000;
}

Maximum upload size

If you upload files to your API, Nginx may reject large uploads before the request reaches your app.

nginx
server {
    listen 443 ssl;
    server_name api.example.com;
    client_max_body_size 50M;
    location /upload/ {
        proxy_pass http://127.0.0.1:8000;
    }
}

If you see "413 Request Entity Too Large" errors, this directive is usually the fix.


Example: Nginx in Front of a FastAPI App

Assume:

Complete sample configuration:

nginx
server {
    listen 80;
    server_name api.example.com;
    # Redirect to HTTPS
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    client_max_body_size 20M;
    # Serve static files
    location /static/ {
        root /var/www/myapp;
        expires 7d;
        add_header Cache-Control "public";
        try_files $uri $uri/ =404;
    }
    # Proxy API requests
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
        proxy_read_timeout 60s;
    }
}

Points to notice:

Testing and Debugging Nginx

Basic commands (Linux)

Common commands on a typical Linux server:

bash
# Test Nginx configuration
sudo nginx -t
# Reload configuration without full restart
sudo systemctl reload nginx
# Restart Nginx service
sudo systemctl restart nginx
# View current status
sudo systemctl status nginx

Always run nginx -t before reloading to catch syntax errors.

Common problems and symptoms

SymptomPossible cause
Browser shows "Bad Gateway" (502)Backend app on port 8000 is down or misconfigured
"Connection refused" in Nginx error logWrong proxy_pass address or port
"413 Request Entity Too Large"client_max_body_size too small
Infinite redirect loop from HTTP to HTTPSProxying to https:// instead of http:// backend
Your app sees client IP as 127.0.0.1Missing X-Real-IP and X-Forwarded-For headers
Static files return 404Wrong root or alias path, or wrong URL prefix

Example logs are usually in /var/log/nginx/access.log and /var/log/nginx/error.log.


How Nginx Fits with Reverse Proxies and Load Balancing

In the broader context of this course:

Very simple load balancing example:

nginx
upstream backend_app {
    server 127.0.0.1:8000;
    server 127.0.0.1:8001;
}
server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://backend_app;
        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;
    }
}

Here:

You will see more about load balancing in the dedicated load balancing chapter. For now, it is enough to understand that Nginx can proxy to a single backend or to several.


Practical Checklist for Using Nginx with a Backend

When you set up Nginx in front of a backend application, walk through this checklist:

  1. Server block
    • Correct server_name for your domain.
    • listen 80 and listen 443 ssl if using HTTPS.
  2. Proxy to backend
    • proxy_pass points to the right address and port.
    • proxy_set_header lines forward important headers.
    • proxy_read_timeout is appropriate for your slowest endpoint.
  3. Static files
    • Use root or alias correctly.
    • Paths on disk match URL paths.
  4. HTTPS
    • Certificates exist and paths are correct.
    • HTTP redirected to HTTPS.
    • TLS versions reasonably secure.
  5. Uploads and timeouts
    • client_max_body_size fits your largest upload.
    • Timeouts keep long tasks working, but not infinite.
  6. Testing
    • nginx -t before reload.
    • Check error logs if requests fail.

If you can do these items, you can operate Nginx effectively as a backend developer.

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!