Serwer WWW z nginx
Moduł 7: Domena, serwer WWW i https · Czas czytania: 12 min
Cel lekcji: Po tej lekcji będą Państwo potrafili zainstalować nginx, skonfigurować stronę i reverse proxy za pomocą bloku server (server block), bezpiecznie przetestować i przeładować konfigurację oraz prawidłowo ustawić uprawnienia katalogu webroot.
Kluczowe pojęcia: nginx, server block, sites-available i sites-enabled, conf.d, listen, server_name, root, index, try_files, default server, nginx -t, reload, reverse proxy, proxy_pass, Host, X-Forwarded-For, X-Forwarded-Proto, webroot, PHP-FPM
Co robi serwer WWW
Serwer WWW nasłuchuje na porcie 80 (http) i 443 (https), przyjmuje żądania od przeglądarek i coś odsyła: plik z dysku (strona statyczna) albo odpowiedź programu, który działa za nim (PHP, aplikacja Node.js, kontener). W tym drugim przypadku serwer WWW nazywa się reverse proxy: stoi z przodu, obsługuje https i przekazuje żądanie aplikacji, która nasłuchuje tylko na 127.0.0.1.
W systemie Linux najbardziej znanymi serwerami WWW są nginx i Apache, a Caddy (lekcja 7.4) to nowoczesna alternatywa, która sama zajmuje się certyfikatami. W tej lekcji używamy nginx: jest dostępny w każdej dystrybucji, oszczędnie korzysta z pamięci i jest standardem w wielu poradnikach.
Instalacja i pierwsze spojrzenie
anna@web1:~$ sudo apt install nginx
anna@web1:~$ systemctl status nginx
anna@web1:~$ curl -I http://localhost
HTTP/1.1 200 OK
Server: nginx/1.26.3
Content-Type: text/html(Numer wersji jest przykładowy.) Prosimy nie zapomnieć o zaporze: porty 80 i 443 muszą być otwarte (lekcja 5.2). Jeśli teraz otworzą Państwo http://192.0.2.10, zobaczą Państwo stronę powitalną nginx.
Konfiguracja znajduje się w /etc/nginx/:
| Ścieżka | Co |
|---|---|
nginx.conf | plik główny; zwykle się go nie zmienia |
sites-available/ | jeden plik na stronę (Debian i Ubuntu) |
sites-enabled/ | dowiązania (symlinki) do włączonych stron |
conf.d/*.conf | pojedyncze ustawienia, które są zawsze wczytywane |
snippets/ | fragmenty używane ponownie w kilku stronach |
sites-available i sites-enabled to zwyczaj Debiana i Ubuntu: stronę włącza się lub wyłącza, tworząc lub usuwając dowiązanie, bez kasowania samego pliku.
Pierwsza strona
Prosimy utworzyć katalog dla strony i stronę testową:
anna@web1:~$ sudo mkdir -p /var/www/example.com
anna@web1:~$ echo '<h1>Het werkt</h1>' | sudo tee /var/www/example.com/index.htmlNastępnie prosimy utworzyć server block: opis jednej strony.
# /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}Należy to czytać tak:
listen 80;ilisten [::]:80;sprawiają, że nginx nasłuchuje na IPv4 oraz IPv6. Jeśli zapomną Państwo o drugiej linii, rekord AAAA nie będzie działał (lekcja 7.1).server_nameokreśla, dla jakich nazw obowiązuje ten blok. Przy każdym żądaniu nginx sprawdza nazwę, o którą pyta przeglądarka (nagłówek Host), i wybiera pasujący blok.rootto katalog z plikami, aindexto plik wyświetlany dla katalogu.try_filespróbuje znaleźć żądany plik, potem katalog, a w przeciwnym razie zwraca błąd 404. Bez takiej linii błędna konfiguracja może pokazać więcej, niż Państwo chcą.- Osobne pliki logów dla każdej strony znacznie ułatwiają wyszukiwanie (lekcja 6.2).
Prosimy włączyć stronę, usunąć stronę domyślną, przetestować konfigurację i przeładować:
anna@web1:~$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
anna@web1:~$ sudo rm /etc/nginx/sites-enabled/default
anna@web1:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
anna@web1:~$ sudo systemctl reload nginx
anna@web1:~$ curl -I http://example.com
HTTP/1.1 200 OKProsimy wyrobić sobie stały nawyk uruchamiania nginx -t przed każdym przeładowaniem. W razie błędu polecenie podaje plik i linię, a działająca strona pozostaje nienaruszona. Jeśli zrestartują Państwo usługę bez testu, nginx z błędem już się nie uruchomi i wszystkie strony przestaną działać (lekcja 6.1).
Default server: co dostaje nieznana nazwa?
Co się dzieje, gdy ktoś odpyta Państwa serwer nazwą, której nie ma w żadnym server_name, albo po prostu adresem IP? Wtedy nginx wybiera default server: blok z default_server po listen, a jeśli takiego nie ma, pierwszy blok, na jaki trafił. Bez przemyślenia będzie to więc jedna z Państwa prawdziwych stron.
Lepszym rozwiązaniem jest osobny blok, który odrzuca takie żądania:
# /etc/nginx/sites-available/000-default
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}444 to specjalny kod nginx: połączenie zostaje zamknięte bez odpowiedzi. Skanery, które przeszukują kolejne adresy IP, nic wtedy nie zobaczą. Dla https (port 443) default server działa nieco inaczej, ponieważ wymaga certyfikatu; wrócimy do tego w lekcji 7.3.
nginx jako reverse proxy
Jeśli na 127.0.0.1:3000 działa aplikacja (lekcja 6.3) lub na 127.0.0.1:3001 kontener (lekcja 9.3), nginx udostępnia ją na zewnątrz:
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}Cztery linie proxy_set_header są ważne. Bez Host aplikacja nie wie, pod jaką nazwą jest odwiedzana. Bez X-Forwarded-For aplikacja widzi każdą wizytę jako pochodzącą z 127.0.0.1 (proxy) zamiast z prawdziwego adresu odwiedzającego. Bez X-Forwarded-Proto aplikacja uważa, że wszystko idzie przez http, i czasem tworzy linki lub ciasteczka dla http, choć strona działa przez https. Wiele aplikacji ma ustawienie pozwalające ufać tym nagłówkom ("trusted proxy"); prosimy wpisać tam tylko 127.0.0.1, w przeciwnym razie każdy odwiedzający może przesłać fałszywy adres.
Aplikacje korzystające z websocketów (aktualizacje na żywo, jak w Uptime Kuma) potrzebują jeszcze dwóch linii: proxy_http_version 1.1; oraz przekazania Upgrade i Connection. Dokumentacja aplikacji zwykle dokładnie podaje, które.
Uprawnienia katalogu webroot
W Debianie i Ubuntu nginx uruchamia swoje procesy robocze jako użytkownik www-data. Musi on móc czytać Państwa pliki, ale nie powinien móc ich zapisywać. Dobry podział (lekcja 3.1):
anna@web1:~$ sudo chown -R anna:www-data /var/www/example.com
anna@web1:~$ sudo find /var/www/example.com -type d -exec chmod 750 {} \;
anna@web1:~$ sudo find /var/www/example.com -type f -exec chmod 640 {} \;Państwo (anna) zarządzają plikami, grupa www-data może je czytać, pozostali nic. Jeśli strona musi gdzieś zapisywać, na przykład w katalogu na przesyłane pliki, prosimy nadać prawo zapisu dla www-data tylko temu katalogowi. Nigdy chmod 777 (lekcja 10.2). Gdy pojawi się błąd 403 Forbidden, prosimy zajrzeć do logu błędów strony: znajdą tam Państwo permission denied wraz ze ścieżką.
Kilka innych dobrych nawyków:
- Żadnych tajnych danych w webroot. Kopie zapasowe (
site.zip), pliki.envi katalogi.gitnie powinny się tam znajdować; jeśli trafią tam przez przypadek, można je pobrać. Dodatkowe zabezpieczenie:location ~ /\. { deny all; }blokuje wszystkie pliki zaczynające się od kropki (poza tym, na co wyraźnie Państwo zezwolą, jak/.well-known/, zob. lekcja 7.3 i 7.4). - Ukrycie wersji.
server_tokens off;wnginx.confusuwa numer wersji z nagłówkaServeri stron błędów. Nie jest to prawdziwe zabezpieczenie, ale daje skanerom mniej informacji.
PHP w skrócie
W przypadku stron w PHP (takich jak WordPress) nginx komunikuje się z PHP-FPM, osobną usługą. W Debianie instaluje się php-fpm i umieszcza w bloku server blok location ~ \.php$ z include snippets/fastcgi-php.conf; oraz fastcgi_pass unix:/run/php/php8.4-fpm.sock; (numer wersji różni się w zależności od wydania). Kurs WordPress omawia to szerzej.
W AlmaLinux i Rocky Linux
Tam nie ma sites-available: każdą stronę umieszcza się jako osobny plik w /etc/nginx/conf.d/<naam>.conf. nginx działa jako użytkownik nginx zamiast www-data, a domyślny webroot to /usr/share/nginx/html. SELinux domyślnie nie pozwala nginx łączyć się z aplikacją za proxy_pass; można to włączyć poleceniem setsebool -P httpd_can_network_connect 1. Pliki poza standardowymi katalogami wymagają etykiety SELinux (semanage fcontext i restorecon).
Podsumowanie
- nginx serwuje pliki lub jako reverse proxy przekazuje żądania aplikacji na
127.0.0.1. - Jeden blok server na stronę w
sites-available, włączany dowiązaniem wsites-enabled; nasłuchiwanie na80oraz[::]:80. - Zawsze
nginx -tprzedsystemctl reload nginx. - Własny default server z
return 444zapobiega temu, by nieznana nazwa lub sam adres IP pokazywały jedną z Państwa stron. - Jako reverse proxy przekazuje się
Host,X-Forwarded-ForiX-Forwarded-Proto; webroot jest czytelny dlawww-data, ale nie zapisywalny, i nie zawiera tajnych danych.
Quiz
Zadanie
Zadanie O7.2: Pierwsza strona. Prosimy zainstalować nginx (lub użyć Caddy z lekcji 7.4) i utworzyć blok server dla (sub)domeny wskazującej na Państwa serwer, z listen dla IPv4 i IPv6, osobnymi plikami logów i własnym default server. Prosimy przetestować konfigurację poleceniem nginx -t, przeładować ją i sprawdzić za pomocą curl -I przez IPv4 i IPv6. Uprawnienia katalogu webroot prosimy ustawić tak jak w lekcji. Następnie prosimy wypełnić listę kontrolną i wkleić swój blok server.
Zadanie O7.2: Pierwsza strona
To zadanie wykonuje się samodzielnie, nikt go nie sprawdza. Prosimy zaznaczyć wykonane punkty i oznaczyć zadanie jako wykonane.
Pod samym adresem IP nic (połączenie zamknięte) albo neutralna strona, nigdy strona klienta. Tylko katalog na przesyłane pliki zapisywalny dla www-data, reszta tylko do odczytu. Za proxy: Host, X-Real-IP, X-Forwarded-For i X-Forwarded-Proto.
Zaznaczenia i notatki pozostają tylko w tej przeglądarce; nie są nigdzie wysyłane. Po zalogowaniu w Moje kursy zapisywana jest jedynie informacja, że zadanie zostało wykonane.
Przeczytaj więcej
- Zabronione (403): Nie mają Państwo uprawnień dostępu do / na tym serwerze
- Dokumentacja nginx, How nginx processes a request (server_name i default server): https://nginx.org/en/docs/http/request_processing.html
- Dokumentacja nginx, Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Dokumentacja nginx,
ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
