Nginx jako reverse proxy pro Node.js a Python aplikace
Jak dát nginx před aplikaci na portu 3000 nebo 8000: server blok, hlavičky X-Forwarded, WebSockety, timeouty, velikost uploadu a ladění chyby 502.
Aplikace v Node.js, Pythonu (FastAPI, Flask, Django) nebo Go obvykle běží na vlastním portu, třeba 3000 nebo 8000. Vystavit ji přímo do internetu není dobrý nápad. Nginx před ní vyřeší HTTPS, kompresi, statické soubory, limity a umožní provozovat více aplikací na jednom serveru pod různými doménami.
Základní princip
Prohlížeč ──HTTPS:443──▶ nginx ──HTTP:127.0.0.1:3000──▶ aplikace
Aplikace by měla naslouchat jen na 127.0.0.1, ne na 0.0.0.0. Tím je zvenku nedostupná a jediná cesta k ní vede přes nginx.
- Node.js/Express:
app.listen(3000, '127.0.0.1') - Uvicorn:
uvicorn main:app --host 127.0.0.1 --port 8000 - Gunicorn:
gunicorn -b 127.0.0.1:8000 app:app
Instalace nginx
sudo apt install nginx
sudo ufw allow 'Nginx Full'
Konfigurace server bloku
Vytvořte /etc/nginx/sites-available/mojeapp.cz:
upstream mojeapp {
server 127.0.0.1:3000;
keepalive 16;
}
server {
listen 80;
listen [::]:80;
server_name mojeapp.cz www.mojeapp.cz;
client_max_body_size 20m;
location / {
proxy_pass http://mojeapp;
proxy_http_version 1.1;
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_set_header Connection "";
}
}
Aktivujte ji a otestujte:
sudo ln -s /etc/nginx/sites-available/mojeapp.cz /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Výchozí web nginx můžete vypnout: sudo rm /etc/nginx/sites-enabled/default.
Proč ty hlavičky
| Hlavička | K čemu slouží |
|---|---|
Host |
aplikace ví, jaká doména byla požadována |
X-Real-IP / X-Forwarded-For |
skutečná IP návštěvníka (jinak uvidíte jen 127.0.0.1) |
X-Forwarded-Proto |
aplikace pozná, že požadavek přišel přes HTTPS |
Aplikaci musíte říct, že má těmto hlavičkám věřit:
- Express:
app.set('trust proxy', 'loopback') - Uvicorn:
--proxy-headers --forwarded-allow-ips 127.0.0.1 - Django:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
Bez toho budou například přesměrování generovat http:// odkazy nebo rate limiting uvidí všechny návštěvníky jako jednu IP.
WebSockety
Socket.IO, live reload nebo chat potřebují upgrade spojení. Do kontextu http (např. do /etc/nginx/conf.d/websocket.conf) přidejte:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
A do location:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1h;
Řádek Connection "" ze základní konfigurace pak nahraďte tímto.
Statické soubory přímo z nginx
Nginx servíruje statické soubory mnohem efektivněji než Node nebo Python:
location /static/ {
alias /var/www/mojeapp/static/;
expires 30d;
access_log off;
}
Pozor na lomítka: u alias musí cesta končit /, pokud location končí /.
Timeouty a dlouhé požadavky
Výchozí proxy_read_timeout je 60 sekund. Pokud vaše API generuje export nebo volá pomalou službu, prodlužte ho jen pro konkrétní cestu:
location /api/export {
proxy_pass http://mojeapp;
proxy_read_timeout 300s;
}
Pro streamované odpovědi (Server-Sent Events, postupné generování textu) vypněte buffering:
proxy_buffering off;
Více aplikací na jednom serveru
Každá doména má vlastní soubor v sites-available s jiným server_name a jiným portem v upstream. Alternativně můžete aplikace rozdělit podle cesty:
location /api/ {
proxy_pass http://127.0.0.1:8000/;
}
Koncové lomítko v proxy_pass znamená, že se prefix /api/ odstraní – aplikace dostane /users místo /api/users. Bez lomítka se cesta předá beze změny.
Ladění 502 Bad Gateway
502 znamená, že nginx se k aplikaci nedostal. Postup:
sudo tail -n 20 /var/log/nginx/error.log
curl -I http://127.0.0.1:3000
sudo ss -tlpn | grep 3000
Typické příčiny:
- aplikace neběží nebo spadla – zkontrolujte
systemctl status/journalctl, - naslouchá na jiném portu nebo jen na IPv6 (
::1), - v logu je
connect() failed (111: Connection refused)= nikdo neposlouchá, upstream timed out= aplikace odpovídá pomalu (504).
Další krok: HTTPS
S funkčním HTTP blokem stačí spustit sudo certbot --nginx -d mojeapp.cz -d www.mojeapp.cz a certbot doplní HTTPS konfiguraci sám. Aplikaci pak spouštějte jako systemd službu, aby se po restartu serveru rozběhla automaticky.