Configuring Nginx as a Reverse Proxy for Node.js and Python Applications

Applications built with Node.js (Express/NestJS) or Python (Django/Flask/FastAPI) typically run on their own internal HTTP servers on specific ports (e.g., 3000 or 8000). While these servers can handle traffic, they lack the robust features of Nginx. By using Nginx as a Reverse Proxy on your Hovixa VPS, you gain advanced SSL termination, static file caching, load balancing, and a hardened security layer between the public internet and your application logic.

1. The Reverse Proxy Architecture

In this setup, Nginx listens on ports 80 and 443. When a request arrives, Nginx terminates the SSL connection and "proxies" the request over the local network interface (loopback) to your application.

2. Basic Configuration for Node.js

Assuming your Node.js application is running on localhost:3000, your Nginx server block should be configured as follows:

server {
    listen 80;
    server_name node.example.com;

    location / {
        proxy_pass http://127.0.0.1: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;
        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;
    }
}
    

3. Specifics for Python (Gunicorn/Uvicorn)

Python applications are often served via an WSGI (like Gunicorn) or ASGI (like Uvicorn) server. A common optimization is using a Unix Domain Socket instead of a TCP port to reduce overhead.

location / {
    include proxy_params;
    proxy_pass http://unix:/home/user/app/app.sock;
}
    

4. Header and Buffer Optimization

To ensure your application correctly identifies the client's original IP and protocol (especially for SSL/HTTPS), specific headers must be passed. Additionally, tuning buffers prevents Nginx from prematurely closing connections for large requests.

Directive Recommended Value Purpose
`proxy_set_header Host` `$host` Passes the requested domain name to the app.
`proxy_buffers` `16 16k` Prevents disk-writing for mid-sized responses.
`client_max_body_size` `20M` Defines the maximum allowed upload size.
`proxy_read_timeout` `90s` Wait time for slow backend computations.

5. Technical Implementation Details

  • WebSockets: Node.js apps frequently use WebSockets. The Upgrade and Connection headers in the Node.js example above are mandatory to allow the "handshake" to pass through the proxy.
  • Static File Offloading: Don't let your application server waste CPU cycles serving CSS, JS, or images. Configure a separate location /static/ block in Nginx to serve these files directly from the NVMe storage.
  • Security (X-Forwarded-Proto): If your application generates absolute URLs (like in redirects), it needs to know the original request was HTTPS. The X-Forwarded-Proto $scheme header informs the backend to use the correct protocol.

Sysadmin Advice: Use **nginx -t** every time you modify a server block. If you have multiple applications, use the **upstream** directive to define your backends; this makes it much easier to scale to multiple app instances or perform rolling updates in the future.

Kas see vastus oli kasulik? 0 Kasutajad peavad seda kasulikuks (0 Hääled)