Přejít na obsah
Aktuální kupón:sleva 10 %Uplatnit v objednávce

Web na VPS: Nginx a certifikát Let's Encrypt (HTTPS)

Nainstalujete Nginx, zprovozníte statický web nebo reverse proxy pro aplikaci (Node.js a další) a získáte zdarma certifikát Let's Encrypt s automatickou obnovou.

  • pokročilý
  • ~25 min
  • Aktualizováno 1. 10. 2026

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#

  1. Ověřte, že doména ukazuje na VPS. Na VPS spusťte:

    bash
    getent hosts example.cz

    Uvidíte IP adresu vaší VPS (ze záložky Síť). Pokud ne, upravte DNS a počkejte na projevení změny.

  2. 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/tcp a ufw allow 443/tcp.

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:

bash
apt update
apt -y install nginx
  • apt -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á#

CestaK čemu slouží
/etc/nginx/nginx.confHlavní konfigurace. Většinou ji neměníte. Načítá soubory ze složek níže.
/etc/nginx/sites-available/Konfigurace jednotlivých webů (server blocky). Soubor tu může být, ale aktivní není.
/etc/nginx/sites-enabled/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.

  1. 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.html
    • mkdir -p – vytvoří složku i s nadřazenými.
    • echo '…' > …/index.html – zapíše jednoduchou stránku do souboru index.html.

    Vlastní soubory webu později nahrajte do této složky přes SFTP (návod) nebo v záložce Soubory.

  2. Vytvořte konfiguraci webu:

    bash
    nano /etc/nginx/sites-available/example.cz
    /etc/nginx/sites-available/example.cznginx
    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;
        }
    }
DirektivaCo 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/www/example.cz/html;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;.
  1. 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 nginx
    • ln -s … /etc/nginx/sites-enabled/ – vytvoří odkaz, Nginx web začne načítat.
    • rm /etc/nginx/sites-enabled/default – vypne výchozí web (soubor zůstane v sites-available).
    • nginx -t – zkontroluje syntaxi všech konfigurací. Musí skončit syntax is ok a test 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):

/etc/nginx/sites-available/app.example.cznginx
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;
    }
}
DirektivaCo 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, ConnectionPř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:

bash
ln -s /etc/nginx/sites-available/app.example.cz /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Aby 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#

bash
apt -y install certbot python3-certbot-nginx
  • certbot – 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#

bash
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á v server_name některého webu.

Při prvním spuštění Certbot položí tyto otázky:

OtázkaCo odpovědětProč
E-mail (Enter email address…)Svou adresuLet'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?YBez souhlasu s podmínkami certifikát nedostanete.
Would you be willing… to share your email address with the Electronic Frontier Foundation…Y nebo NJen zasílání novinek EFF, na certifikát nemá vliv.

Výsledek: Successfully deployed certificate for example.cz to /etc/nginx/sites-enabled/example.cz a Congratulations! You have successfully enabled HTTPS….

Co Certbot v konfiguraci změnil#

Otevřete konfiguraci webu (nano /etc/nginx/sites-available/example.cz). Řádky označené # managed by Certbot přidal Certbot:

Přidaný řádekCo 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/letsencrypt/live/example.cz/fullchain.pem;Certifikát (včetně mezicertifikátů).
ssl_certificate_key /etc/letsencrypt/live/example.cz/privkey.pem;Soukromý klíč certifikátu. Nikomu ho nedávejte.
include /etc/letsencrypt/options-ssl-nginx.conf;Doporučené nastavení TLS od Certbotu (protokoly, šifry).
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;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:

bash
systemctl list-timers | grep certbot
certbot renew --dry-run
  • systemctl list-timers | grep certbot – vypíše řádek s certbot.timer a časem dalšího spuštění.
  • certbot renew --dry-run – vyzkouší obnovu proti testovacímu serveru, skutečné certifikáty nemění. Musí skončit Congratulations, 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žimSpojení z Cloudflare na VPSDoporučení
OffBez šifrováníNepoužívat.
FlexibleNešifrované HTTP na port 80Nepoužívat. Spolu s přesměrováním na HTTPS v Nginxu vytvoří nekonečnou smyčku (ERR_TOO_MANY_REDIRECTS).
FullStejný protokol jako u návštěvníka; u HTTPS se certifikát VPS neověřujeJen dočasně.
Full (strict)Stejný protokol jako u návštěvníka; u HTTPS s ověřením certifikátu VPSDoporuč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í#

  1. Skrytí verze Nginxu. Na Debianu 13 je v /etc/nginx/nginx.conf už výchozí řádek server_tokens off;. Na Ubuntu 24.04 ho otevřete (nano /etc/nginx/nginx.conf) a v bloku http odstraňte # před řádkem # server_tokens off;. Nginx pak neprozradí svou verzi v hlavičkách ani na chybových stránkách.

  2. Bezpečnostní hlavičky. Do bloku server s 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í.
  3. Po každé změně spusťte nginx -t a systemctl 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í#

bash
curl -I http://example.cz
curl -I https://example.cz
  • curl -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/nginx/sites-enabled/example.cz:12. 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:

bash
ss -tlnp | grep 3000
  • ss -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/nginx/sites-enabled/default 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/nginx/sites-available/, aktivní jsou jen ty s odkazem v sites-enabled.
  • Po každé změně: nginx -t a systemctl reload nginx.
  • Aplikace ať poslouchá na 127.0.0.1 a Nginx ji zpřístupní přes proxy_pass včetně hlaviček X-Forwarded-*.
  • Certifikát získáte příkazem certbot --nginx -d …; obnovuje se sám, ověříte certbot renew --dry-run.
  • S Cloudflare používejte režim Full (strict), nikdy Flexible.

Hledání v návodech