Nginx, reverse proxy, DNS a HTTPS
Jak jsme oddělili veřejnou vrstvu VPS od backendu v Dockeru a přidali TLS přes Let's Encrypt.
Systémový nginx vs. nginx v containeru
Nginx není automaticky reverse proxy. Reverse proxy z něj dělá až konfigurace typu
proxy_pass.
sites-available vs. sites-enabled
Debianí instalace nginxu používá běžnou organizační konvenci:
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
sites-available
Tady máme uložené konfigurace webů, které na serveru existují nebo které máme připravené.
/etc/nginx/sites-available/
├── default
├── docker.kekor.cz
└── tahak.kekor.cz
Samotná přítomnost souboru v sites-available
ještě neznamená, že jej nginx používá.
server_name tahak.kekor.cz;.
sites-enabled
Nginx má ve své hlavní konfiguraci nastaveno načítání konfigurací
ze sites-enabled.
Proto jsou aktivní právě konfigurace dostupné přes tento adresář.
/etc/nginx/sites-enabled/
├── default
├── docker.kekor.cz
└── tahak.kekor.cz
Obvykle tam ale nedáváme kopii skutečného konfiguračního souboru. Použijeme symbolický link.
Výhoda je, že skutečná konfigurace existuje pouze jednou.
Web lze deaktivovat odstraněním symlinku ze
sites-enabled, aniž bychom smazali jeho konfiguraci
ze sites-available.
Jak přesně funguje ln -s?
Správný příkaz:
sudo ln -s \
/etc/nginx/sites-available/tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
Syntaxe je:
ln -s TARGET LINK_NAME
| Část | Význam |
|---|---|
ln |
vytvoření linku |
-s |
symbolický link místo hard linku |
| první cesta | skutečný cílový soubor |
| druhá cesta | kde má vzniknout symlink |
Výsledek ověříme:
ls -l /etc/nginx/sites-enabled/
Správně například:
tahak.kekor.cz -> /etc/nginx/sites-available/tahak.kekor.cz
Chyba: symlink ukazuje sám na sebe
Během našeho cvičení jsme omylem použili:
sudo ln -s tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
První cesta byla relativní. Relativní target symlinku se interpretuje vzhledem k adresáři, ve kterém se samotný symlink nachází.
Vzniklo tedy ve skutečnosti:
Nginx pak při testu skončil chybou:
Too many levels of symbolic links
Operační systém zastavil nekonečné následování symlinku.
Oprava:
sudo rm /etc/nginx/sites-enabled/tahak.kekor.cz
sudo ln -s \
/etc/nginx/sites-available/tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
Konfigurace jedné domény
server {
listen 80;
listen [::]:80;
server_name docker.example.cz;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
server_name vybírá virtual host podle HTTP hlavičky Host.
Díky tomu může jeden VPS a jedna veřejná IP obsluhovat mnoho různých domén.
Jak přesně funguje ln -s?
Správný příkaz:
sudo ln -s \
/etc/nginx/sites-available/tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
Syntaxe je:
ln -s TARGET LINK_NAME
| Část | Význam |
|---|---|
ln |
vytvoření linku |
-s |
symbolický link místo hard linku |
| první cesta | skutečný cílový soubor |
| druhá cesta | kde má vzniknout symlink |
Výsledek ověříme:
ls -l /etc/nginx/sites-enabled/
Správně například:
tahak.kekor.cz -> /etc/nginx/sites-available/tahak.kekor.cz
Chyba: symlink ukazuje sám na sebe
Během našeho cvičení jsme omylem použili:
sudo ln -s tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
První cesta byla relativní. Relativní target symlinku se interpretuje vzhledem k adresáři, ve kterém se samotný symlink nachází.
Vzniklo tedy ve skutečnosti:
Nginx pak při testu skončil chybou:
Too many levels of symbolic links
Operační systém zastavil nekonečné následování symlinku.
Oprava:
sudo rm /etc/nginx/sites-enabled/tahak.kekor.cz
sudo ln -s \
/etc/nginx/sites-available/tahak.kekor.cz \
/etc/nginx/sites-enabled/tahak.kekor.cz
Proxy hlavičky
| Hlavička | Co předává backendu |
|---|---|
Host | původní doménu |
X-Real-IP | IP návštěvníka |
X-Forwarded-For | řetězec proxy/IP přes které request prošel |
X-Forwarded-Proto | zda klient přišel přes http nebo https |
Kontrola a reload nginxu
sudo nginx -t
sudo systemctl reload nginx
Nejdřív syntaktický test, až potom reload. Je to bezpečnější než slepý restart.
DNS
U správce domény jsme vytvořili A záznam:
docker.example.cz A YOUR_VPS_IP
Ověření:
Resolve-DnsName docker.example.cz
nslookup docker.example.cz
curl -v http://docker.example.cz
HTTP request obsahuje Host: docker.example.cz, podle něhož nginx vybere správný server block.
Let's Encrypt, ACME a Certbot
Let's Encrypt
Certifikační autorita, která vydává certifikát.
ACME
Automatizovaný protokol pro vydání/obnovu certifikátu.
Certbot
ACME klient na našem VPS.
nginx
Server, který certifikát skutečně používá pro TLS.
sudo apt install certbot python3-certbot-nginx
certbot --version
sudo certbot --nginx -d docker.example.cz
TLS termination
Backend může běžet přes obyčejné HTTP, protože komunikace zůstává uvnitř VPS na loopbacku.
Co Certbot přidal do nginxu
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/docker.example.cz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/docker.example.cz/privkey.pem;
fullchain.pem je veřejný certifikát + certifikační řetězec.
privkey.pem je tajný soukromý klíč.
HTTP port 80 se pak typicky používá jen pro redirect:
return 301 https://$host$request_uri;
Ověření HTTPS
curl -I http://docker.example.cz
# očekáváme 301
curl -I https://docker.example.cz
# očekáváme 200
Automatické obnovování certifikátu
systemctl status certbot.timer
sudo certbot renew --dry-run
Timer běží pravidelně, ale nový certifikát se nevydává při každém spuštění. Certbot obnovuje až certifikáty, které se blíží expiraci.