1. Co to jest PHP‑FPM i dlaczego z Nginx?
PHP‑FPM (PHP FastCGI Process Manager) to zaawansowany menedżer procesów PHP, który nasłuchuje na porcie TCP lub gnieździe UNIX (socket) i obsługuje żądania przychodzące najczęściej z Nginx.
- 1. Co to jest PHP‑FPM i dlaczego z Nginx?
- 2. Założenia poradnika
- 3. Instalacja Nginx i PHP‑FPM
- 4. Struktura katalogów i wirtualny host Nginx
- 5. Powiązanie Nginx z PHP‑FPM – socket
- 6. Sprawdzenie konfiguracji i restart usług
- 7. Test – czy PHP działa?
- 8. Podstawowa optymalizacja PHP (php.ini)
- 9. Optymalizacja PHP‑FPM – pule i limity
- 10. Optymalizacja Nginx pod PHP‑FPM
- 11. Typowe problemy i diagnostyka
- 12. Dobre praktyki bezpieczeństwa
- 13. Podsumowanie kroków (checklista do szybkiego wdrożenia)
W odróżnieniu od klasycznego mod_php w Apache, PHP działa jako osobna usługa – dzięki temu:
- nginx może obsługiwać statyczne pliki (CSS, JS, obrazki) bardzo szybko,
- php‑fpm zarządza procesami PHP, skalując je do obciążenia (pule, limity, restartowanie, logi),
- można łatwo uruchomić wiele wersji PHP równolegle.
Połączenie Nginx + PHP‑FPM jest obecnie standardem w środowiskach o dużym ruchu.
2. Założenia poradnika
Poniżej przyjmujemy następujące założenia konfiguracyjne:
- system: typowy Linux (Debian/Ubuntu, analogicznie w innych – Fedora/AlmaLinux/CentOS itp.),
- php: dowolna nowoczesna wersja (np. 8.2/8.3),
- serwer http: Nginx jako reverse proxy + serwer plików statycznych,
- sposób komunikacji: UNIX socket (szybszy i bezpieczniejszy na jednym serwerze niż port TCP).
3. Instalacja Nginx i PHP‑FPM
3.1. Aktualizacja systemu
Zaktualizuj pakiety systemowe:
sudo apt-get update && sudo apt-get upgrade
3.2. Instalacja Nginx
Zainstaluj serwer Nginx:
sudo apt-get install nginx
Po instalacji włącz usługę w autostarcie i uruchom:
sudo systemctl enable nginx
sudo systemctl start nginx
Sprawdź status usługi:
sudo systemctl status nginx
3.3. Instalacja PHP z FPM
Na Debianie/Ubuntu (przykład dla PHP 8.2) zainstaluj FPM i typowe rozszerzenia:
sudo apt-get install php8.2-fpm php8.2-cli php8.2-mysql php8.2-xml php8.2-curl php8.2-zip
Upewnij się, że zainstalowany jest pakiet phpX.Y-fpm – bez tego FPM nie będzie działał.
Uruchom i włącz PHP‑FPM:
sudo systemctl enable php8.2-fpm
sudo systemctl start php8.2-fpm
sudo systemctl status php8.2-fpm
4. Struktura katalogów i wirtualny host Nginx
4.1. Katalog projektu
Załóżmy, że konfigurujesz domenę example.net. Utwórz katalog projektu i nadaj prawa:
sudo mkdir -p /var/www/example.net/html
sudo chown -R www-data:www-data /var/www/example.net
sudo chmod -R 750 /var/www/example.net
Utwórz prosty plik testowy, aby sprawdzić serwowanie statyki:
echo "Hello Nginx" | sudo tee /var/www/example.net/html/index.html
4.2. Plik vhosta (blok serwera) Nginx
Skopiuj domyślny vhost jako szablon nowej domeny:
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.net
Edytuj konfigurację:
sudo nano /etc/nginx/sites-available/example.net
Poniżej znajdziesz przykładową konfigurację HTTP (bez HTTPS, do testów):
server {
listen 80;
server_name example.net www.example.net;
root /var/www/example.net/html;
index index.php index.html index.htm;
# Obsługa plików statycznych
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Blok PHP – integracja z PHP-FPM przez socket
location ~ \.php$ {
try_files $uri =404;
include snippets/fastcgi-php.conf; # zawiera standardowe parametry FastCGI
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # dostosuj wersję PHP!
# Alternatywnie dla innych dystrybucji:
# fastcgi_pass unix:/var/run/php-fpm/www.sock;
}
# Blokowanie dostępu do ukrytych plików (.git itp.)
location ~ /\.ht {
deny all;
}
access_log /var/log/nginx/example.net.access.log;
error_log /var/log/nginx/example.net.error.log;
}
Włącz vhost dla domeny:
sudo ln -s /etc/nginx/sites-available/example.net /etc/nginx/sites-enabled/
Wyłącz domyślny vhost (opcjonalnie):
sudo rm /etc/nginx/sites-enabled/default
5. Powiązanie Nginx z PHP‑FPM – socket
Kluczowy fragment w bloku location ~ \.php$ to wskazanie gniazda FPM:
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Ścieżkę do socketa znajdziesz w konfiguracji puli FPM, np. w pliku /etc/php/8.2/fpm/pool.d/www.conf (Debian/Ubuntu) albo /etc/php-fpm.d/www.conf (CentOS/Fedora).
Wyszukaj linię zawierającą ścieżkę do gniazda:
listen = /run/php/php8.2-fpm.sock
Jeśli ścieżka jest inna, przepisz ją dokładnie do dyrektywy fastcgi_pass w Nginx.
6. Sprawdzenie konfiguracji i restart usług
Po edycji konfiguracji Nginx wykonaj test składni:
sudo nginx -t
Jeśli nie ma błędów, przeładuj Nginx bez przerywania pracy:
sudo systemctl reload nginx
Po zmianach w PHP / PHP‑FPM (np. php.ini, pule) zrestartuj FPM:
sudo systemctl restart php8.2-fpm
W bardziej zaawansowanych środowiskach można użyć systemctl reload lub sygnału USR2 do płynnego przeładowania, ale pełny restart jest wymagany przy zmianach rozszerzeń, php.ini czy plików binarnych PHP.
7. Test – czy PHP działa?
Utwórz plik info.php, aby potwierdzić działanie PHP:
echo "<?php phpinfo(); ?>" | sudo tee /var/www/example.net/html/info.php
Wejdź w przeglądarce na adres http://example.net/info.php.
Jeżeli widzisz stronę z konfiguracją PHP, komunikacja Nginx ↔ PHP‑FPM działa.
Jeśli zamiast tego plik się pobiera, Nginx nie przekazuje żądań do FPM. Najczęściej winne są:
- brak bloku
location ~ \.php$, - zła ścieżka w
fastcgi_pass, - niedziałający PHP‑FPM (
systemctl status php8.2-fpm).
8. Podstawowa optymalizacja PHP (php.ini)
Plik php.ini dla FPM znajdziesz m.in. w /etc/php/8.2/fpm/php.ini (Debian/Ubuntu) lub w /etc/php.ini//etc/php-fpm.d/* (inne dystrybucje).
Warto dopasować kilka podstawowych parametrów w celu poprawy stabilności i wydajności:
memory_limit = 256M– ograniczenie pamięci na proces PHP (zwiększ dla ciężkich aplikacji);max_execution_time = 60–300– maksymalny czas wykonywania w sekundach; 300 s to bezpieczny limit dla długich importów;post_max_size = 32M–64M– maksymalny rozmiar danych POST (formularze, JSON);upload_max_filesize = 32M–64M– maksymalny rozmiar pojedynczego pliku przy uploadzie;date.timezone = Europe/Warsaw– poprawna strefa czasu.
Po zmianach zrestartuj FPM:
sudo systemctl restart php8.2-fpm
9. Optymalizacja PHP‑FPM – pule i limity
Najważniejsza część wydajności PHP‑FPM to konfiguracja puli (plik www.conf lub osobne pule per aplikacja). Na Debian/Ubuntu znajdziesz ją w /etc/php/8.2/fpm/pool.d/www.conf, a na RHEL/Fedora w /etc/php-fpm.d/www.conf.
9.1. Tryby zarządzania procesami – dynamic, static, ondemand
Poniżej przykładowe dyrektywy sterujące liczbą procesów i ich zachowaniem:
pm = dynamic ; lub static / ondemand
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm = dynamic– domyślne i dobre w większości przypadków; FPM sam dostosowuje liczbę procesów w zależności od obciążenia;pm = static– stała liczba procesów (pm.max_children); dobra przy dokładnej kontroli RAM;pm = ondemand– procesy są tworzone na żądanie i usypiane po czasie (pm.process_idle_timeout), korzystne na małe serwery o niskim ruchu.
Dobór wartości kluczowych parametrów zależy od dostępnej pamięci i profilu ruchu. pm.max_children wyznaczysz w przybliżeniu jako: RAM dostępny dla PHP / średnie zużycie pamięci przez pojedynczy proces. Parametry pm.start_servers, pm.min_spare_servers, pm.max_spare_servers ustaw zgodnie ze średnim ruchem (dla małych serwisów zwykle 2–5).
9.2. Timeouty i logowanie powolnych skryptów
Włącz limity czasu i slowlog, aby diagnozować wąskie gardła w aplikacji:
request_terminate_timeout = 120
request_slowlog_timeout = 5s
slowlog = /var/log/php8.2-fpm/slow.log
Dzięki tym ustawieniom skrypty wiszące dłużej niż 120 s będą ubijane, a skrypty wykonujące się dłużej niż 5 s trafią do loga powolnych zapytań (slow.log).
9.3. Izolacja aplikacji w osobnych pulach
Dla wielu aplikacji (np. kilku klientów lub dużych serwisów) warto stworzyć osobne pule FPM – każdą z innymi limitami oraz użytkownikiem/UID. Polega to na skopiowaniu www.conf do app1.conf, zmianie nazwy puli i gniazda (listen), a następnie skierowaniu odpowiedniego vhosta Nginx na nowe gniazdo.
Dzięki temu awaria lub nadmierne zużycie RAM przez jedną aplikację nie wpływa na pozostałe oraz możesz stosować różne limity (pm.max_children), logi i użytkowników.
10. Optymalizacja Nginx pod PHP‑FPM
10.1. Kluczowy blok dla PHP
Najlepszą praktyką jest użycie gotowego snippetu fastcgi-php.conf (Debian/Ubuntu) oraz ustawienie try_files:
location ~ \.php$ {
try_files $uri =404;
include snippets/fastcgi-php.conf; # zawiera m.in. SCRIPT_FILENAME
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
Jeśli snippet nie jest dostępny, ustaw parametry ręcznie:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
10.2. Bufory FastCGI
W pliku globalnym (np. /etc/nginx/nginx.conf) lub w sekcji http { ... } dopasuj bufory i timeouty:
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
fastcgi_busy_buffers_size 64k;
fastcgi_read_timeout 60s;
Odpowiednio dobrane bufory zmniejszają ryzyko duplikowania ruchu między pamięcią a dyskiem i poprawiają wydajność odpowiedzi dynamicznych.
10.3. Gzip, kompresja i cache statyki
Włącz kompresję i nagłówki cache dla plików statycznych:
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml text/xml;
gzip_min_length 1024;
gzip_comp_level 5;
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|webp)$ {
expires 30d;
access_log off;
}
Nginx świetnie radzi sobie z cache’owaniem statyki, znacząco odciążając PHP‑FPM.
11. Typowe problemy i diagnostyka
11.1. Strona pobiera plik PHP zamiast go wykonać
Najczęstsze przyczyny to błędny blok obsługi PHP, nieprawidłowe gniazdo FPM lub niedziałająca usługa:
- brak bloku
location ~ \.php$, - nieprawidłowa ścieżka w
fastcgi_pass, - niedziałający PHP‑FPM.
Przydatne komendy diagnostyczne:
sudo nginx -t
sudo systemctl status php8.2-fpm
sudo tail -f /var/log/nginx/error.log
11.2. Błędy 502 Bad Gateway
Błędy 502 zwykle wynikają z problemu po stronie FPM lub ścieżki do gniazda:
- niedziałający FPM (
systemctl status php8.2-fpm), - zła ścieżka do socketa,
- przeciążony FPM (
pm.max_childrenza małe – rośnie kolejka).
Sprawdź logi FPM oraz log Nginx dla danej domeny:
sudo tail -f /var/log/php8.2-fpm.log
11.3. Serwer wolny „pod obciążeniem”
Główne potencjalne źródła problemu to limity procesów, pamięć lub brak cache kodu:
- za mało procesów FPM (
pm.max_children), - zbyt mały RAM i/lub swap (procesy PHP ubijane przez OOM),
- brak lub źle skonfigurowany opcache PHP.
Włącz slowlog (slowlog, request_slowlog_timeout) i przeanalizuj, które skrypty spowalniają aplikację.
12. Dobre praktyki bezpieczeństwa
Aby ograniczyć ryzyko incydentów, stosuj poniższe zasady:
- używaj kont nieuprzywilejowanych – uruchamiaj Nginx jako
www-data(Debian/Ubuntu) lub inny dedykowany użytkownik; - ograniczaj prawa do katalogów – np.
/var/wwwz uprawnieniami 750 i właścicielem użytkownika serwującego stronę; - filtruj dostęp do plików wrażliwych – blokuj
.git,.env, pliki konfiguracyjne itp.
Przykładowa reguła Nginx blokująca dostęp do ukrytych plików:
location ~ /\.(git|env).* {
deny all;
}
Włącz HTTPS (Let’s Encrypt, certbot): wygeneruj certyfikat i dodaj listen 443 ssl; oraz ścieżki do certyfikatów w bloku server.
13. Podsumowanie kroków (checklista do szybkiego wdrożenia)
- Zainstaluj Nginx i PHP‑FPM wraz z wymaganymi rozszerzeniami.
- Upewnij się, że działa usługa
phpX.Y-fpm(systemctl status). - Utwórz katalog
/var/www/twoja_domena/htmli nadaj odpowiednie prawa. - Skonfiguruj vhost Nginx z następującymi elementami:
- root ustawiony na katalog strony,
- blok
location /ztry_files, - blok
location ~ \.php$zfastcgi_passna socket FPM.
- Sprawdź konfigurację Nginx (
nginx -t) i przeładuj serwer. - Dodaj
info.phpi przetestuj w przeglądarce, czy PHP działa. - Dostosuj
php.ini(limity pamięci, upload, czas wykonania). - Skonfiguruj pule FPM (
www.conf):pm,pm.max_children, timeouty, slowlog. - Włącz gzip, cache statycznych plików i odpowiednie bufory FastCGI w Nginx.
- Monitoruj logi Nginx i PHP‑FPM, reaguj na 502/504 oraz długie czasy odpowiedzi.








