Nginx je rychlý webový server. Nastavíme s ním statický web nebo ho postavíme před vaši aplikaci jako reverse proxy a zapneme HTTPS s certifikátem Let's Encrypt, který se bude sám obnovovat.
Co budete potřebovat
- VPS u StormHostu s Ubuntu 24.04 nebo Debianem 13
- Doménu nasměrovanou na IP adresu VPS (záznam
A, případněAAAA), postup: Doména na VPS a Cloudflare - Připojení přes SSH jako root (návod)
- Asi 25 minut
Jak to funguje#
Prohlížeč se připojí na port 80 (HTTP) nebo 443 (HTTPS) vaší VPS. Nginx podle domény v požadavku vybere správný server block (konfiguraci jednoho webu) a buď pošle soubor z disku (statický web), nebo požadavek předá aplikaci běžící na jiném portu (reverse proxy).
Certifikát pro HTTPS vydá zdarma Let's Encrypt. Program Certbot ověří, že doménu ovládáte (Let's Encrypt se připojí na port 80 a stáhne kontrolní soubor), certifikát stáhne, nastaví ho v Nginxu a pak ho sám obnovuje.
Předpoklady: DNS a porty#
Ověřte, že doména ukazuje na VPS. Na VPS spusťte:
bash getent hosts example.czUvidíte IP adresu vaší VPS (ze záložky Síť). Pokud ne, upravte DNS a počkejte na projevení změny.
Otevřete porty 80 a 443:
- Firewall v zákaznické zóně (pokud máte režim Blokovat vše kromě povoleného): pravidlo Příchozí · Povolit · TCP · port
80,443. Návod: Firewall v zákaznické zóně. - UFW ve VPS (pokud ho používáte):
ufw allow 80/tcpaufw allow 443/tcp.
- Firewall v zákaznické zóně (pokud máte režim Blokovat vše kromě povoleného): pravidlo Příchozí · Povolit · TCP · port
Cloudflare: certifikát získejte se šedým mráčkem
Pokud doménu spravujete v Cloudflare, nechte záznamy během získání certifikátu ve stavu DNS only (šedý mráček). Až certifikát máte, můžete přepnout na Proxied, viz Cloudflare a režimy SSL.
Instalace Nginxu#
Platí pro Ubuntu 24.04 i Debian 13:
apt update
apt -y install nginxapt -y install nginx– nainstaluje Nginx. Služba se hned spustí a zapne po startu VPS.
Ověření: v prohlížeči otevřete http://<IP_ADRESA_VPS>. Za <IP_ADRESA_VPS> dosaďte IPv4 adresu ze záložky Síť (například http://203.0.113.10). Uvidíte uvítací stránku „Welcome to nginx!“.
Jak je konfigurace uspořádaná#
| Cesta | K čemu slouží |
|---|---|
/etc/nginx/nginx.conf | Hlavní konfigurace. Většinou ji neměníte. Načítá soubory ze složek níže. |
/etc/ | Konfigurace jednotlivých webů (server blocky). Soubor tu může být, ale aktivní není. |
/etc/ | Odkazy (symlinky) na soubory ze sites-available. Nginx načítá jen to, co je tady. |
/etc/nginx/conf.d/ | Další konfigurace, načítají se všechny soubory *.conf. |
/var/www/ | Obvyklé místo pro soubory webů. |
/var/log/nginx/ | Logy: access.log (požadavky) a error.log (chyby). |
Web tedy zapnete tak, že vytvoříte soubor v sites-available a odkaz na něj v sites-enabled. Vypnete ho smazáním odkazu.
Statický web#
Statický web jsou hotové soubory HTML, CSS, JavaScript a obrázky.
Vytvořte složku webu a zkušební stránku:
bash mkdir -p /var/www/example.cz/html echo '<h1>Funguje to</h1>' > /var/www/example.cz/html/index.htmlmkdir -p– vytvoří složku i s nadřazenými.echo '…' > …/index.html– zapíše jednoduchou stránku do souboruindex.html.
Vlastní soubory webu později nahrajte do této složky přes SFTP (návod) nebo v záložce Soubory.
Vytvořte konfiguraci webu:
bash nano /etc/nginx/sites-available/example.cz/etc/ nginx/ nginxsites-available/ example.cz server { listen 80; listen [::]:80; server_name example.cz www.example.cz; root /var/www/example.cz/html; index index.html; location / { try_files $uri $uri/ =404; } }
| Direktiva | Co dělá | Kdy změnit |
|---|---|---|
listen 80; | Naslouchá na portu 80 pro IPv4. | Nikdy (HTTPS doplní Certbot). |
listen [::]:80; | Totéž pro IPv6. | Smažte, pokud VPS nemá IPv6. |
server_name example.cz www.example.cz; | Domény, pro které blok platí. Podle nich Nginx vybírá web. | Uveďte své domény oddělené mezerou. |
root /var/ | Složka se soubory webu. | Při jiném umístění souborů. |
index index.html; | Který soubor poslat, když adresa končí /. | U PHP webů index.php index.html. |
location / { … } | Pravidla pro všechny adresy webu. | – |
try_files $uri $uri/ =404; | Zkusí najít soubor, pak složku; když nic neexistuje, vrátí chybu 404. | U jednostránkových aplikací (React, Vue) try_files $uri $uri/ /index.html;. |
Zapněte web, vypněte výchozí uvítací stránku, otestujte konfiguraci a načtěte ji:
bash ln -s /etc/nginx/sites-available/example.cz /etc/nginx/sites-enabled/ rm /etc/nginx/sites-enabled/default nginx -t systemctl reload nginxln -s … /etc/– vytvoří odkaz, Nginx web začne načítat.nginx/ sites-enabled/ rm /etc/– vypne výchozí web (soubor zůstane vnginx/ sites-enabled/ default sites-available).nginx -t– zkontroluje syntaxi všech konfigurací. Musí skončitsyntax is okatest is successful.systemctl reload nginx– načte novou konfiguraci bez přerušení spojení.
Ověření: http://example.cz zobrazí nadpis „Funguje to“.
Reverse proxy pro aplikaci#
Aplikace (Node.js, Python, Java, kontejner Dockeru) obvykle běží na vlastním portu, například 3000. Nginx před ni postavíte jako reverse proxy: přijme požadavky na portu 80/443 a přepošle je aplikaci. Výhody: HTTPS řeší Nginx, aplikace nemusí být vidět z internetu a na jedné VPS může běžet víc aplikací pod různými doménami.
Aplikace ať poslouchá jen na 127.0.0.1
Nastavte aplikaci, ať naslouchá na 127.0.0.1:3000, ne na 0.0.0.0:3000. Pak je dostupná jen přes Nginx a nikdo ji neobejde přímým přístupem na port. U Dockeru publikujte port jako 127.0.0.1:3000:3000 (viz Docker a Docker Compose).
Konfigurace (místo statického webu, nebo jako další soubor pro jinou doménu, například app.example.cz):
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name app.example.cz;
client_max_body_size 20m;
location / {
proxy_pass http://127.0.0.1:3000;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
}
}| Direktiva | Co dělá | Kdy změnit |
|---|---|---|
map $http_upgrade $connection_upgrade { … } | Pomocná proměnná pro websockety: když prohlížeč žádá o upgrade spojení, pošle se upgrade, jinak close. Stačí jednou v celé konfiguraci (při druhém výskytu ohlásí nginx -t duplicitu). | Nikdy. |
client_max_body_size 20m; | Největší velikost nahrávaného požadavku. Výchozí je 1 MB; větší upload skončí chybou 413. | Podle toho, co aplikace přijímá. |
proxy_pass http://127.0.0.1:3000; | Kam se požadavky přeposílají. | Port vaší aplikace. |
proxy_http_version 1.1; | Spojení k aplikaci přes HTTP/1.1. Starší verze Nginxu jinak používají HTTP/1.0, se kterým websockety nefungují. | Nikdy. |
proxy_set_header Host $host; | Aplikace uvidí původní doménu z prohlížeče. | Nikdy. |
proxy_set_header X-Real-IP …, X-Forwarded-For … | Aplikace uvidí skutečnou IP adresu návštěvníka, ne 127.0.0.1. | Nikdy. |
proxy_set_header X-Forwarded-Proto $scheme; | Aplikace pozná, že návštěvník přišel přes HTTPS (důležité pro přesměrování a cookies). | Nikdy. |
Upgrade, Connection | Přenesou požadavek na websocket (chat, živé aktualizace, Socket.IO). | Nikdy. |
proxy_read_timeout 300s; | Jak dlouho čekat na odpověď aplikace. Výchozích 60 s uzavře nečinné websockety. | Prodlužte u dlouhých operací. |
Zapnutí je stejné jako u statického webu:
ln -s /etc/nginx/sites-available/app.example.cz /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginxAby aplikace běžela trvale a po restartu VPS se spustila sama, nastavte ji jako službu: Aplikace 24/7 přes systemd.
HTTPS přes Certbot#
Instalace Certbotu#
apt -y install certbot python3-certbot-nginxcertbot– klient pro Let's Encrypt.python3-certbot-nginx– doplněk, který umí ověřit doménu přes Nginx a sám upravit jeho konfiguraci.
Certbot ze snapu
Autoři Certbotu doporučují instalaci přes snap, která má vždy nejnovější verzi. Balíček z distribuce (Ubuntu 24.04 má Certbot 2.9, Debian 13 verzi 4.0) funguje pro běžné použití stejně a aktualizuje se s ostatními balíčky. Pokud chcete snap, postupujte podle certbot.eff.org/instructions (otevře se v novém okně) a balíčky z apt nejdřív odinstalujte, ať nemáte dva Certboty.
Získání certifikátu#
certbot --nginx -d example.cz -d www.example.cz--nginx– ověření přes Nginx a automatická úprava jeho konfigurace.-d example.cz -d www.example.cz– domény, pro které certifikát chcete. Každá musí mít DNS záznam mířící na VPS a musí být uvedená vserver_nameněkterého webu.
Při prvním spuštění Certbot položí tyto otázky:
| Otázka | Co odpovědět | Proč |
|---|---|---|
E-mail (Enter email address…) | Svou adresu | Let's Encrypt na ni posílá důležitá oznámení. Upozornění na blížící se konec platnosti od roku 2025 neposílá, obnovu hlídá automatika. |
Please read the Terms of Service… Do you agree? | Y | Bez souhlasu s podmínkami certifikát nedostanete. |
Would you be willing… to share your email address with the Electronic Frontier Foundation… | Y nebo N | Jen zasílání novinek EFF, na certifikát nemá vliv. |
Výsledek: Successfully deployed certificate for example.cz to /etc/ a Congratulations! You have successfully enabled HTTPS….
Co Certbot v konfiguraci změnil#
Otevřete konfiguraci webu (nano /etc/). Řádky označené # managed by Certbot přidal Certbot:
| Přidaný řádek | Co dělá |
|---|---|
listen 443 ssl; | Web naslouchá i na portu 443 s TLS. |
listen [::]:443 ssl ipv6only=on; | Totéž pro IPv6. Certbot ho přidá, když blok obsahuje listen [::]:80. Volbu ipv6only=on (naslouchat na IPv6 jen pro IPv6 spojení) doplní jen u prvního webu na VPS, u dalších je řádek bez ní. |
ssl_certificate /etc/ | Certifikát (včetně mezicertifikátů). |
ssl_certificate_key /etc/ | Soukromý klíč certifikátu. Nikomu ho nedávejte. |
include /etc/ | Doporučené nastavení TLS od Certbotu (protokoly, šifry). |
ssl_dhparam /etc/ | Parametry pro výměnu klíčů. |
nový server blok s return 301 https://… | Přesměruje HTTP na HTTPS. Certbot ho přidává automaticky. |
Tyto řádky neupravujte ručně, pokud přesně nevíte proč. Certbot s nimi počítá při obnově.
Automatická obnova#
Certifikát Let's Encrypt platí 90 dní (stav k říjnu 2026, Let's Encrypt platnost postupně zkracuje). Balíček Certbotu nainstaloval časovač, který dvakrát denně zkontroluje certifikáty a obnoví ty, kterým zbývá zhruba třetina platnosti. Doplněk pro Nginx po obnově Nginx sám načte znovu.
Ověřte, že časovač existuje a že obnova projde:
systemctl list-timers | grep certbot
certbot renew --dry-runsystemctl list-timers | grep certbot– vypíše řádek scertbot.timera časem dalšího spuštění.certbot renew --dry-run– vyzkouší obnovu proti testovacímu serveru, skutečné certifikáty nemění. Musí skončitCongratulations, all simulated renewals succeeded.
Přehled certifikátů a jejich platnosti vypíše certbot certificates.
Limity Let's Encrypt
Let's Encrypt vydá pro stejnou sadu domén nejvýš 5 certifikátů za 7 dní a po 5 neúspěšných ověřeních domény za hodinu vás dočasně zablokuje. Při ladění proto používejte --dry-run (testovací server) a ostrý příkaz spusťte, až test projde.
Cloudflare a režimy SSL#
Pokud web běží přes proxy Cloudflare (oranžový mráček), šifrují se dvě spojení: mezi návštěvníkem a Cloudflare a mezi Cloudflare a vaší VPS. Druhé určuje režim SSL/TLS v Cloudflare:
| Režim | Spojení z Cloudflare na VPS | Doporučení |
|---|---|---|
| Off | Bez šifrování | Nepoužívat. |
| Flexible | Nešifrované HTTP na port 80 | Nepoužívat. Spolu s přesměrováním na HTTPS v Nginxu vytvoří nekonečnou smyčku (ERR_TOO_MANY_REDIRECTS). |
| Full | Stejný protokol jako u návštěvníka; u HTTPS se certifikát VPS neověřuje | Jen dočasně. |
| Full (strict) | Stejný protokol jako u návštěvníka; u HTTPS s ověřením certifikátu VPS | Doporučeno. Váš certifikát Let's Encrypt je platný, takže funguje. |
Po přepnutí na Proxied spusťte certbot renew --dry-run a ověřte, že obnova certifikátu projde i přes proxy Cloudflare. Pokud selže, zkontrolujte, že v Cloudflare neblokujete port 80 vlastními pravidly. Trvalé řešení pro pokročilé je ověřovat doménu přes DNS doplňkem python3-certbot-dns-cloudflare (postup v dokumentaci Certbotu (otevře se v novém okně)).
Základní zabezpečení#
Skrytí verze Nginxu. Na Debianu 13 je v
/etc/nginx/nginx.confuž výchozí řádekserver_tokens off;. Na Ubuntu 24.04 ho otevřete (nano /etc/nginx/nginx.conf) a v blokuhttpodstraňte#před řádkem# server_tokens off;. Nginx pak neprozradí svou verzi v hlavičkách ani na chybových stránkách.Bezpečnostní hlavičky. Do bloku
servers portem 443 můžete přidat:nginx add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy strict-origin-when-cross-origin always;X-Content-Type-Options nosniff– prohlížeč nebude hádat typ souboru (ochrana proti podvrženým skriptům).X-Frame-Options SAMEORIGIN– web nepůjde vložit do cizí stránky v rámu (ochrana proti clickjackingu).Referrer-Policy strict-origin-when-cross-origin– cizím webům se pošle jen doména, ne celá adresa stránky.always– hlavička se pošle i u chybových odpovědí.
Po každé změně spusťte
nginx -tasystemctl reload nginx.
HSTS až po rozmyšlení
Hlavička Strict-Transport-Security (HSTS) přikáže prohlížečům používat pro doménu jen HTTPS, a to i měsíce dopředu. Když pak HTTPS přestane fungovat (vypršení certifikátu, přesun domény), web se nenačte. Zapínejte ji, až HTTPS běží spolehlivě.
Ověření#
curl -I http://example.cz
curl -I https://example.czcurl -I– stáhne jen hlavičky odpovědi.
První příkaz vrátí HTTP/1.1 301 Moved Permanently s hlavičkou Location: https://example.cz/, druhý HTTP/1.1 200 OK (nebo HTTP/2 200). V prohlížeči uvidíte u adresy zámek.
Když něco nefunguje#
nginx -t hlásí chybu#
Výpis obsahuje soubor a číslo řádku, například unexpected "}" in /etc/. Nejčastěji chybí středník na konci direktivy nebo je navíc či chybí složená závorka. Opravte řádek a test spusťte znovu. Nginx s chybnou konfigurací nerestartujte, nenastartoval by.
502 Bad Gateway#
Nginx běží, ale aplikace za ním neodpovídá. Zkontrolujte, že aplikace běží a naslouchá na portu z proxy_pass:
ss -tlnp | grep 3000ss -tlnp– naslouchající TCP porty s názvy programů.
Když se nic nevypíše, aplikace neběží nebo poslouchá jinde. Podrobnosti najdete v /var/log/nginx/error.log (řádek s connect() failed (111: Connection refused)).
504 Gateway Time-out#
Aplikace odpověděla pozdě. Zvyšte proxy_read_timeout, nebo zjistěte, proč je aplikace pomalá.
413 Request Entity Too Large#
Nahrávaný soubor je větší než client_max_body_size (výchozí 1 MB). Zvyšte hodnotu v bloku server a načtěte konfiguraci.
Zobrazuje se „Welcome to nginx!“ místo webu#
Pořád je aktivní výchozí web, nebo doména v server_name neodpovídá adrese v prohlížeči. Smažte /etc/ a zkontrolujte server_name.
Nginx nenastartuje: Address already in use#
Port 80 nebo 443 drží jiný program, typicky Apache. Zjistěte který: ss -tlnp | grep -E ':80 |:443 '. Apache zastavte a vypněte (systemctl disable --now apache2), nebo ho odinstalujte.
Certbot: Could not automatically find a matching server block#
Žádný web nemá v server_name doménu, pro kterou certifikát žádáte. Doplňte ji do server_name, spusťte nginx -t, systemctl reload nginx a Certbot znovu.
Certbot: Timeout during connect (likely firewall problem) nebo Connection refused#
Let's Encrypt se nedostal na port 80. Zkontrolujte DNS (getent hosts example.cz), firewall v zákaznické zóně a UFW. Pokud má doména záznam AAAA, musí ukazovat na IPv6 adresu této VPS a web musí naslouchat i na IPv6 (listen [::]:80;).
Cloudflare: chyba 521, 522, 525 nebo 526#
- 521 – VPS spojení odmítla: Nginx neběží nebo firewall blokuje port 443.
- 522 – spojení vypršelo: VPS je nedostupná nebo firewall pakety zahazuje.
- 525 – nepovedlo se navázat TLS: Nginx na portu 443 nemá platnou konfiguraci HTTPS.
- 526 – certifikát na VPS je neplatný nebo prošlý, a to v režimu Full (strict). Zkontrolujte
certbot certificates.
ERR_TOO_MANY_REDIRECTS#
Typicky Cloudflare v režimu Flexible spolu s přesměrováním na HTTPS. Přepněte Cloudflare na Full (strict).
Shrnutí
- Weby jsou v
/etc/, aktivní jsou jen ty s odkazem vnginx/ sites-available/ sites-enabled. - Po každé změně:
nginx -tasystemctl reload nginx. - Aplikace ať poslouchá na
127.0.0.1a Nginx ji zpřístupní přesproxy_passvčetně hlavičekX-Forwarded-*. - Certifikát získáte příkazem
certbot --nginx -d …; obnovuje se sám, ověřítecertbot renew --dry-run. - S Cloudflare používejte režim Full (strict), nikdy Flexible.
Další zdroje#
- nginx: Beginner's Guide (otevře se v novém okně)
- nginx: WebSocket proxying (otevře se v novém okně)
- nginx: ngx_http_proxy_module (otevře se v novém okně)
- Certbot: User Guide (otevře se v novém okně)
- Let's Encrypt: Rate Limits (otevře se v novém okně)
- Cloudflare: SSL/TLS encryption modes (otevře se v novém okně)