Ten kompleksowy artykuł przedstawia szczegółowe omówienie instalacji i konfiguracji Nginx jako serwera WWW oraz odwrotnego serwera proxy w systemach Ubuntu. Nginx to potężne i elastyczne rozwiązanie dla nowoczesnej infrastruktury webowej, obejmujące pełny cykl wdrożenia — od instalacji, przez konfigurację reverse proxy z równoważeniem obciążenia, terminację SSL/TLS i twarde utwardzanie bezpieczeństwa. Stosując opisane metody, administratorzy mogą przygotować produkcyjne wdrożenia Nginx, obsługujące dynamiczne aplikacje, złożone reguły trasowania i wymagające wzorce ruchu przy zachowaniu wysokiego poziomu bezpieczeństwa i wydajności.
Wprowadzenie do Nginx i jego podstawowej architektury
Nginx, wymawiany jako „Engine-X”, to nowoczesny, wysokowydajny serwer WWW i odwrotny serwer proxy, powszechnie wykorzystywany we współczesnej infrastrukturze. W odróżnieniu od serwerów takich jak Apache, opartych na procesach lub wątkach, Nginx wykorzystuje asynchroniczną, zdarzeniową architekturę, zdolną obsłużyć tysiące jednoczesnych połączeń przy minimalnym zużyciu zasobów. To podejście zapewnia przewidywalną wydajność przy wysokiej współbieżności i oszczędnym wykorzystaniu CPU i pamięci.
Filozofia projektowa Nginx opiera się na modułowości, prostocie i optymalizacji wydajności. Proces nadrzędny (master) zarządza procesami roboczymi (workers), z których każdy niezależnie obsługuje żądania w modelu zdarzeniowym. Taka konstrukcja efektywnie skaluje się na wielordzeniowych procesorach, bez potrzeby tworzenia nowego procesu lub wątku dla każdego połączenia.
Nginx pełni podwójną rolę. Jako serwer WWW wydajnie serwuje treści statyczne i dynamiczne (kompresja, cache, przepisywanie URL), a jako reverse proxy pośredniczy między klientami a serwerami aplikacyjnymi, realizując m.in. SSL/TLS offloading, równoważenie obciążenia oraz jednolite wejście dla złożonego zaplecza. Ta wszechstronność sprawia, że Nginx może realizować wiele wymagań w ramach jednego wdrożenia.
Popularność Nginx rośnie dzięki zdolności obsługi ruchu na dużą skalę przy skromnych zasobach oraz prostemu, czytelnemu językowi konfiguracji.
Instalacja i wstępna konfiguracja w systemach Ubuntu
Instalacja Nginx w Ubuntu jest prosta i wykorzystuje ekosystem zarządzania pakietami. Pierwszym krokiem jest aktualizacja indeksu pakietów za pomocą menedżera apt, aby mieć dostęp do najnowszych wersji oprogramowania.
Instrukcja instalacji krok po kroku
Wykonaj poniższe kroki, aby zainstalować i uruchomić Nginx na Ubuntu:
- Zaktualizuj listy pakietów:
sudo apt update. - (Opcjonalnie) Zaktualizuj istniejące pakiety:
sudo apt upgrade -y. - Zainstaluj Nginx:
sudo apt install nginx -y. - Włącz autostart i uruchom usługę:
sudo systemctl enable --now nginx. - Sprawdź status:
systemctl status nginxlub wykonaj test HTTP:curl -I http://127.0.0.1. - (Opcjonalnie) Zezwól na ruch HTTP/HTTPS w UFW:
sudo ufw allow 'Nginx Full'. - Po zmianach konfiguracji testuj i ładuj ponownie:
sudo nginx -t && sudo systemctl reload nginx.
Narzędzie systemctl pozwala uruchamiać, zatrzymywać, restartować i przeładowywać usługę Nginx w sposób bezpieczny dla środowiska produkcyjnego.
Struktura domyślnej instalacji
Najważniejsze lokalizacje i ich zastosowanie to:
- główny plik konfiguracyjny:
/etc/nginx/nginx.conf, - katalog dostępnych witryn:
/etc/nginx/sites-available/, - katalog aktywnych witryn (linki):
/etc/nginx/sites-enabled/, - domyślne treści statyczne:
/usr/share/nginx/html/, - logi dostępu i błędów:
/var/log/nginx/.
Konfiguracje witryn znajdują się w /etc/nginx/sites-available/, a aktywuje się je symbolicznie w /etc/nginx/sites-enabled/. Oddzielenie „available” od „enabled” ułatwia zarządzanie aktywacją witryn.
Podstawy konfiguracji Nginx i struktura plików
Konfiguracja Nginx ma hierarchiczną strukturę bloków z dyrektywami stosowanymi na różnych poziomach: globalnym, events, http, server i location. Taki układ daje precyzyjną kontrolę nad zachowaniem serwera i przejrzystość konfiguracji.
Hierarchia konfiguracji i konteksty
Kluczowe konteksty i ich rola przedstawiają się następująco:
- global – użytkownik procesów,
worker_processes, plik PID, ścieżkiinclude; - events – model obsługi połączeń,
worker_connections, opcje kolejek; - http – typy MIME, logowanie, GZIP, cache, definicje
upstream; - server – porty (
listen), nazwy (server_name), katalog główny, TLS; - location – szczegółowe trasowanie, dopasowania prefiksowe i regex,
proxy_pass.
Na poziomie globalnym definiuje się m.in. użytkownika dla procesów roboczych, liczbę procesów worker_processes oraz ścieżkę do pliku PID. Ustawienie worker_processes auto zwykle zapewnia dobrą równowagę (jeden proces na rdzeń CPU).
Blok events zawiera ustawienia przetwarzania połączeń, w tym worker_connections określającą maksymalną liczbę równoczesnych połączeń na proces roboczy. Domyślna wartość 512 bywa zachowawcza i często można ją zwiększyć po testach wydajności.
Blok http obejmuje konfigurację HTTP: typy MIME, formaty logów, kompresję GZIP, cache oraz definicje grup upstream. Najwięcej konfiguracji aplikacyjnej znajduje się w blokach server, które określają porty, nazwy serwerów, katalogi główne i reguły location.
Bloki location umożliwiają najdokładniejsze trasowanie. Dostępne są różne tryby dopasowania (prefiks, wyrażenia regularne, ^~). Priorytety są zdefiniowane: najpierw dopasowania dokładne, potem prefiksowe z ^~, następnie regexy w kolejności konfiguracji, a na końcu zwykłe prefiksy.
Wirtualne hosty i konfiguracja bloków server
W Ubuntu typowo każda witryna ma osobny plik w sites-available. W pliku definiuje się blok server z dyrektywami listen, server_name i root. Aktywację konfiguracji wykonuje się przez link symboliczny do sites-enabled oraz walidację nginx -t przed przeładowaniem.
Prosta witryna statyczna wymaga niewielu dyrektyw (wskazanie katalogu i pliku indeksu). Bardziej złożone aplikacje dodają reguły przepisywania, osobne cache dla zasobów statycznych itp.
Konfiguracja Nginx jako serwera WWW dla treści statycznych i dynamicznych
Jako serwer WWW Nginx przyjmuje żądania HTTP i zwraca treści statyczne lub generowane dynamicznie. Dobór i konfiguracja mechanizmów cache, kompresji oraz przepisywania URL wpływają na wydajność, bezpieczeństwo i funkcjonalność.
Wydajne serwowanie treści statycznych
Nginx doskonale obsługuje pliki HTML, obrazy, CSS i JavaScript. Konfiguracja zwykle sprowadza się do ustawienia root i plików indeksu.
Aby zwiększyć wydajność, warto skonfigurować cache przeglądarki (nagłówki Cache-Control i dyrektywa expires), dzięki czemu klienci rzadziej pobierają te same zasoby.
Kompresja GZIP potrafi zmniejszyć rozmiar odpowiedzi o 70–90% dla treści tekstowych. Włączamy ją dyrektywą gzip i określamy typy MIME dyrektywą gzip_types (np. text/css, application/javascript, application/json).
Przepisywanie URL i trasowanie żądań
Przepisywanie URL umożliwia mapowanie żądań na inne ścieżki lub przekierowania. Do prostych przypadków używa się return (np. przekierowanie 301 między domenami), a do złożonych transformacji — rewrite z wyrażeniami regularnymi i flagami (last, break).
Obsługa wielu domen i subdomen
Wiele domen i subdomen obsługuje się osobnymi blokami server z dyrektywą server_name. Nginx wybiera blok na podstawie dopasowania nagłówka Host do wartości server_name.
Dla subdomen na tym samym serwerze można użyć wzorców w server_name (wildcards). Konfiguracja DNS obejmuje rekordy A i CNAME, w zależności od potrzeb.
Zaawansowana konfiguracja reverse proxy i równoważenie obciążenia
Jako reverse proxy Nginx pośredniczy w komunikacji klient–backend, zarządza życiem połączeń i może modyfikować nagłówki oraz treść. Pozwala to wdrożyć złożone scenariusze trasowania, agregację usług i skalowanie horyzontalne.
Podstawowa konfiguracja reverse proxy
W location wskazujemy backend dyrektywą proxy_pass (np. http://localhost:3000).
Najważniejsze nagłówki przekazywane do backendu to:
- Host –
proxy_set_header Host $hostzachowuje oryginalną domenę żądania; - X-Real-IP –
proxy_set_header X-Real-IP $remote_addrprzekazuje adres IP klienta; - X-Forwarded-For –
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_fordodaje łańcuch adresów pośredników; - X-Forwarded-Proto –
proxy_set_header X-Forwarded-Proto $schemeinformuje backend o schemacie HTTP/HTTPS.
Wersję protokołu do komunikacji z backendem określa proxy_http_version (zwykle 1.1 dla keep-alive). Często należy też jawnie ustawić lub usunąć nagłówek Connection. Poprawne przekazanie oryginalnego hosta i adresu IP klienta jest kluczowe dla logowania, limitów i autoryzacji po stronie aplikacji.
Równoważenie obciążenia między wieloma serwerami backend
Grupę serwerów backend definiuje upstream, a domyślną metodą rozdziału jest round-robin. Dla serwerów o różnych możliwościach można ustawić wagi (weight). Poniższa tabela porównuje popularne algorytmy:
| Algorytm | Zasada działania | Zastosowania | Uwagi |
|---|---|---|---|
| round-robin | równe, cykliczne rozdzielanie żądań | jednorodne backendy o zbliżonej wydajności | prosty, dobry punkt wyjścia |
| least_conn | kieruje żądania na serwer z najmniejszą liczbą aktywnych połączeń | nierówne czasy obsługi, długie połączenia | lepsze wykorzystanie zasobów przy zmiennym obciążeniu |
| ip_hash | ten sam klient (IP) trafia do tego samego backendu | prosta trwałość sesji bez zewnętrznego store | wrażliwy na NAT, mniej równomierny rozkład |
Zaawansowane zdrowie backendów (health checks) oraz sticky sessions oparte na ciasteczkach dostępne są w NGINX Plus.
Zaawansowane trasowanie i transformacja żądań
Różne ścieżki URL mogą trafiać do różnych usług backend (np. /api/v1/ do jednego serwisu, /admin do innego). Realizuje się to wieloma blokami location w obrębie jednego server.
Transformacje żądań obejmują modyfikacje nagłówków (proxy_set_header), przepisywanie URI (rewrite) i dopasowanie formatu żądania do wymagań systemów legacy. Obsługa WebSocket wymaga prawidłowego przekazania nagłówków Upgrade i Connection oraz użycia zmiennej $http_upgrade.
Implementacja zabezpieczeń i strategie hardeningu
Bezpieczeństwo obejmuje ochronę serwera, szyfrowanie komunikacji, filtrowanie szkodliwych żądań i minimalizację ujawniania informacji. Kompleksowa konfiguracja HTTPS, nagłówków bezpieczeństwa, kontroli dostępu i limitów żądań znacząco podnosi odporność środowiska.
Szyfrowanie SSL/TLS i konfiguracja HTTPS
Współcześnie HTTPS jest standardem dla całego ruchu. Certyfikaty Let’s Encrypt można uzyskać i odnawiać automatycznie przy użyciu Certbota (wtyczka Nginx).
Najważniejsze praktyki przy konfiguracji HTTPS to:
- TLSv1.2/TLSv1.3 – ogranicz obsługę starych protokołów i szyfrów;
- OCSP stapling – skróć weryfikację certyfikatów po stronie klienta;
- HSTS – wymuś HTTPS nagłówkiem
Strict-Transport-Security(opcjonalniepreload); - session tickets/keys – rotuj klucze i rozważ wyłączenie ticketów, jeśli nie są potrzebne;
- ALPN – zapewnij negocjację HTTP/2 i HTTP/3.
Po instalacji certyfikatów należy wskazać ścieżki dyrektywami ssl_certificate i ssl_certificate_key oraz włączyć nasłuch TLS w listen. Ograniczenie protokołów do TLSv1.2 i TLSv1.3 poprawia bezpieczeństwo bez istotnej utraty kompatybilności.
Kontrola dostępu i uwierzytelnianie
HTTP Basic auth pozwala chronić zasoby prostym mechanizmem haseł (plik haseł tworzony np. narzędziem htpasswd). W Nginx włącza się to dyrektywami auth_basic i auth_basic_user_file.
Ograniczenia oparte na adresie IP realizują dyrektywy allow i deny (kolejność ma znaczenie). Połączenie Basic auth i filtrów IP zapewnia obronę w głąb dla wrażliwych paneli administracyjnych i endpointów.
Nagłówki bezpieczeństwa i ochrona przed typowymi atakami
Poniższe nagłówki znacząco podnoszą bezpieczeństwo aplikacji:
- Content Security Policy (CSP) – ogranicza dozwolone źródła zasobów, minimalizując XSS i ataki związane z wstrzyknięciem kodu;
- X-Frame-Options – zapobiega osadzaniu strony w ramkach (ochrona przed clickjacking);
- X-Content-Type-Options: nosniff – wymusza respektowanie deklarowanych typów MIME;
- Referrer-Policy – kontroluje ilość informacji o odsyłaczu przekazywanych do zewnętrznych serwisów;
- Permissions-Policy – ogranicza dostęp do wrażliwych API przeglądarki (kamera, lokalizacja, mikrofon).
Ograniczanie tempa żądań (rate limiting) chroni przed brute-force i DoS: strefy limitów definiuje limit_req_zone, a ich zastosowanie — limit_req. Warto także limitować jednoczesne połączenia i narzucić rozsądne timeouty po stronie klienta.
Techniki łagodzenia ataków DDoS
Ograniczanie liczby połączeń per klient zapewniają limit_conn_zone i limit_conn. Zbyt wolny odczyt nagłówków/ciała blokują client_header_timeout i client_body_timeout. Cache’owanie i serwowanie przestarzałych kopii (stale) może znacząco zmniejszyć obciążenie backendów podczas ataku. Dodatkowo listy dozwolonych adresów (allowlist) mogą chronić wewnętrzne lub partnerskie API.
Optymalizacja wydajności i strojenie
Optymalizacja obejmuje dostrajanie parametrów procesów i połączeń, cache’owanie, kompresję oraz monitorowanie wąskich gardeł.
Strojenie procesów roboczych i połączeń
Dyrektywa worker_processes (domyślnie auto) zwykle sprawdza się najlepiej, lecz dla specyficznych obciążeń można ją modyfikować.
worker_connections ogranicza liczbę jednoczesnych połączeń na proces. Zwiększenie powyżej 512 (np. 1024/2048) wymaga zapewnienia odpowiednich limitów deskryptorów i pamięci. Teoretyczne maksimum połączeń ≈ worker_processes × worker_connections.
Strategie buforowania dla zwiększenia wydajności
Cache przeglądarki ogranicza liczbę żądań do serwera, a proxy cache w Nginx potrafi serwować odpowiedzi bez kontaktu z backendem.
Konfiguracja proxy cache: ścieżka i parametry przez proxy_cache_path, włączenie per-lokalizacja przez proxy_cache oraz czasy ważności przez proxy_cache_valid. Dla aplikacji PHP/WordPress sprawdza się także fastcgi_cache. Klucz cache’u można rozszerzyć poza URI o parametry zapytania lub nagłówki, aby uniknąć kolizji i zapewnić właściwą granulację.
Kompresja i optymalizacja treści
GZIP włączamy dyrektywą gzip, a typy ustalamy w gzip_types. Poziom kompresji kontroluje gzip_comp_level (większy poziom = lepsza kompresja kosztem CPU). Brotli oferuje lepsze współczynniki niż GZIP dla treści tekstowych i JSON, można go włączyć równolegle, utrzymując kompatybilność z klientami obsługującymi jedynie GZIP.
Obsługa protokołów HTTP/2 i HTTP/3
HTTP/2 przynosi multipleksowanie, kompresję nagłówków i server push. Włącza się go dodając http2 do listen na porcie HTTPS. Rosnące wsparcie HTTP/3/QUIC oferuje dalsze korzyści wydajnościowe. Najważniejsze zalety nowoczesnych protokołów to:
- multipleksowanie wielu żądań w jednym połączeniu,
- redukcja opóźnień w sieciach o wysokim RTT,
- lepsza tolerancja strat pakietów (QUIC) i opcja 0-RTT.
Monitorowanie, logowanie i rozwiązywanie problemów
Skuteczne monitorowanie i logowanie umożliwiają wczesne wykrywanie problemów, analizę wydajności i incydentów bezpieczeństwa.
Konfiguracja logów dostępu i błędów
Nginx zapisuje logi dostępu i błędów. Format logów można dostosować dyrektywą log_format (np. czas odpowiedzi, adres upstream, stopień kompresji).
Separację logów per host/aplikację uzyskujemy przez osobne dyrektywy access_log w blokach server. Możliwe jest też logowanie warunkowe (np. z użyciem map oraz parametru if dla access_log), aby ograniczyć wolumen. Poziom logowania błędów kontroluje error_log (lokalizacja i poziom, np. warn lub error). Rotację logów zapewnia logrotate (np. plik /etc/logrotate.d/nginx).
Monitorowanie statusu i zbieranie metryk
Moduł stub_status udostępnia prostą stronę statusową (np. location /nginx_status), z licznikiem aktywnych połączeń i podstawowymi statystykami. Bardziej szczegółowe metryki dostarcza NGINX Plus (REST API z danymi o strefach serwera, stanie upstreamów, cache itp.). Do własnego monitoringu można parsować logi dostępu, analizować $request_time i zmienne upstream w celu wykrycia wolnych żądań, problematycznych backendów lub wzorców ataków.
Rozwiązywanie typowych problemów
Poniżej zebrano najczęstsze symptomy wraz z diagnozą i pierwszymi krokami naprawczymi:
- Konfiguracja i reload – błędy składni uniemożliwiają start/reload; zawsze uruchamiaj
nginx -tprzed zastosowaniem zmian i sprawdzajerror_log; - 502 Bad Gateway – typowo brak łączności z backendem lub błąd aplikacji; zweryfikuj, czy proces działa i nasłuchuje (
ss,netstat), a także adres/port wproxy_pass; - 504 Gateway Timeout – za krótkie timeouty lub zbyt wolny backend; zwiększ
proxy_read_timeout, zoptymalizuj zapytania do aplikacji; - 403/404 – błędne uprawnienia lub ścieżki; sprawdź
root,try_filesi prawa do katalogów/plików; - 413 Request Entity Too Large – zbyt małe
client_max_body_size; podnieś limit w odpowiednimserver/location.








