Wprawdzie będzie to kompleksowy poradnik jak na czystym Debianie (np. w DigitalOcean) w kilka minut postawić serwer WWW na webserwerze Nginx z obsługą PHP (PHP5-FPM) – to proponuje też zapoznać się z tym wpisem, gdzie zostało szczegółowo omówiona instalacja pozostałych komponentów serwera WWW (m.in. MySQL, phpMyAdmin), które zapewne też się przydadzą.

Nginx i PHP5-FPM

Jak zawsze zaczynamy od aktualizacji systemu, po której przystępujemy do instalacji i konfiguracji webserwera Nginx oraz PHP-FPM.

Instalujemy Nginx i PHP5-FPM

sudo apt-get update sudo apt-get install nginx sudo apt-get install php5 php5-fpm php5-common php5-curl php5-mcrypt php5-gd php-gettext

Więcej informacji o instalacji PHP5-FPM (zwłaszcza w przypadku Raspberry Pi) znajdziesz we wcześniejszym poradniku dotyczącym instalacji i konfiguracji PHP5-FPM dla Apache2.

Po udanej instalacji teoretycznie mamy już gotowy (web)serwer z obsługą plików PHP, choć przed nami jeszcze niezbędna konfiguracja…

Zawsze najnowsza wersja Nginx

Wprawdzie Nginx jest dostępny w systemie Debian w systemowych repozytoriach, to czasem korzystam z „firmowych repozytoriów” Nginx, dzięki czemu mam zawsze najnowszą wersję webserwera w systemie.

Przed instalacją samego Nginx edytujemy plik:

sudo nano /etc/apt/sources.list

I dodajemy 2 linijki/wpisy:

deb http://nginx.org/packages/mainline/debian/ WERSJA_SYSTEMU nginx deb-src http://nginx.org/packages/mainline/debian/WERSJA_SYSTEMU nginx

Zamiast „WERSJA_SYSTEMU” wstawiamy nazwę wersji z której korzystamy, np. wheezy lub jessie.

Na koniec musimy jeszcze dodać niezbędne klucze:

wget http://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key

Musicie mieć świadomość, że w przypadku „dużo nowszych wersji” Nginx konfiguracja może całkiem inaczej…

Konfiguracja Nginx i PHP5-FPM

Po instalacji Nginxa przechodzimy do edycji domyślnego pliku strefy WWW:

sudo nano /etc/nginx/sites-available/default

Minimalna konfiguracja dla plików strony w katalogu:

  • /var/www/public_html/

wygląda tak:

server { listen 80; ## listen for ipv4; this line is default and implied #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 root /var/www/[DOMENA]/public_html/; index index.html index.htm index.php; server_name localhost [DOMENA] *.[DOMENA]; location / { try_files $uri $uri/ /index.php?$args; } access_log /var/log/nginx/[DOMENA]_access.log; error_log /var/log/nginx/[DOMENA]_error.log; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; # PHP5-FPM: fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; # Nginx 1.2.1: #include fastcgi_params; # Nginx 1.6.1+: include fastcgi.conf; # Więcej informacji w tabelce poniżej } # deny access to .htaccess files (Apache2) location ~ /\. { deny all; } }

Biały ekran śmierci PHP

Może się zdarzyć, że po instalacji Nginx i PHP-FPM niby wszystko będzie działać, strony statyczne (zwykły HTML) będą się otwierać, ale próba otworzenia dowolnej strony PHP skończy się białym ekranem. By sprawę jeszcze bardziej skomplikować – pewnie nie będzie w logach żadnych istotnych/pomocnych wpisów.

Jest duża szansa, że wynika to z tego, że m.in. ten wpis powstał na przykładzie Nginx w wersji 1.2.1, który instalował się domyślnie w stabilnej wersji Debian 7 Wheezy. W Debian 8 Jessie domyślnie instaluje się Nginx w wersji 1.6.1 lub nowszej, a to wymaga drobnej modyfikacji konfiguracji.

Wersję webserwera Nginx sprawdzicie np. poleceniem:

[email protected] ~ $ sudo nginx -v nginx version: nginx/1.6.2

Z racji tego, że cały czas można spotkać VPSy pracujące/korzystające z systemu Debian 7 postanowiłem zaktualizować wpis o ustawienia dla Nginx w wersji 1.6.1+, ale jednocześnie pozostawiając wpis dotyczący Nginx w wersji 1.2.1 (trzeba go ew odkomentować, a zakomentować ten dla 1.6.1+):

# Nginx 1.2.1: #include fastcgi_params; # Nginx 1.6.1+: include fastcgi.conf;

Alternatywną (do wyboru opartego na wersji Nginx) metodą wyboru odpowiedniego wpisu może być skorzystanie z polecenia:

sudo ls /etc/nginx | grep "fastcgi" 

Jeśli w odpowiedzi znajdziemy plik „fastcgi.conf”, to korzystamy z wpisu dla Nginx 1.6.1+, jeśli plik „fastcgi_params” – wersji dla Nginx 1.2.1.

Teraz szybki test, czy wszystko jest ok:

sudo /etc/init.d/nginx configtest

Jeśli tak – restart serwera:

sudo /etc/init.d/nginx restart

lub (preferuje) odświeżenie ustawień:

sudo /etc/init.d/nginx reload

Nginx obsługuje wszystkie pliki statyczne, a żądania PHP przekazuje do PHP5-FPM.

Kilka dodatkowych zabezpieczeń

Warto jeszcze rozważyć dodanie parametru „open_basedir” do naszej konfiguracji, dzięki czemu wszystkie (nie tylko) złośliwe skrypty będą ograniczone do katalogu domowego, a tym samym minimalizujemy szansę dostępu do plików innej strony, czy też odczytu konfiguracji całego serwera (np. katalog /etc/):

location ~ \.php$ { [...] fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root"; [...] }

Lub wersja z dostępem również do katalogu „/tmp”, by działało wgrywanie plików w PHP:

fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/tmp";

Oprócz tego warto zapoznać się z „safe_mode” (tryb bezpieczny) oraz „disable_finctions” (wyłączenie wybranych funkcji).

Połączenie szyfrowane, czyli obsługa SSL

Jeśli chcesz dodać do swojej strony obsługę połączeń szyfrowanych (HTTPS) to potrzebny Ci będzie certyfikat SSL. Informacje jak go przygotować najdziesz w wcześniejszych wpisach:

Różnica polega na tym, że konfigurację robimy dalej w plikach Nginxa, a nie Apache2:

sudo nano /etc/nginx/sites-available/default

I poniżej danych dla „normalnego połączenia” dodajemy:

 # HTTPS server server { listen 443; root /var/www/public_html/; index index.html index.htm index.php; server_name localhost [nazwa domeny] *.[nazwa domeny] 127.0.0.1; access_log /var/log/nginx/default_ssl_access.log; error_log /var/log/nginx/default_ssl_error.log; ssl on; # Dla własnego certyfikatu "odkomentuj" (usuń #) te 2 linie: #ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; #ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; # Dla komercyjnego certyfikatu "odkomentuj" (usuń #) te 2 linie: #ssl_certificate /katalog/z/certyfikatem/ssl.crt; #ssl_certificate_key /katalog/z/certyfikatem/ssl.key; # i zmień "/katalog/z/certyfikatem" na odpowiednią ścieżkę do certyfikatu ssl_session_timeout 5m; keepalive_timeout 60; ssl_protocols TLSv1.1 TLSv1.2; #ALT: #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; ssl_prefer_server_ciphers on; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; # PHP5-FPM: fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; # Nginx 1.2.1: #include fastcgi_params; # Nginx 1.6.1+: include fastcgi.conf; # Więcej informacji w tabelce powyżej } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one location ~ /\. { deny all; } }

Wspólna konfiguracja HTTP i HTTPS (SSL)

W przypadku gdy konfiguracja strony zarówno dla połączenia szyfrowanego jak i nieszyfrowanego jest identyczna – można sobie całą operację uprościć, i do konfiguracji dla połączenia nieszyfrowanego dodać:

listen 443 ssl; ssl on; # Dla własnego certyfikatu "odkomentuj" (usuń #) te 2 linie: #ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; #ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; # Dla komercyjnego certyfikatu "odkomentuj" (usuń #) te 2 linie: #ssl_certificate /katalog/z/certyfikatem/ssl.crt; #ssl_certificate_key /katalog/z/certyfikatem/ssl.key; # i zmień "/katalog/z/certyfikatem" na odpowiednią ścieżkę do certyfikatu ssl_session_timeout 10m; keepalive_timeout 60; ssl_protocols TLSv1.1 TLSv1.2; #ALT: #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; ssl_prefer_server_ciphers on;

zaraz poniżej

listen 80;

Teraz szybki test, czy wszystko jest ok:

sudo /etc/init.d/nginx configtest

Jeśli tak – restart serwera:

sudo /etc/init.d/nginx restart

lub (preferuje) odświeżenie ustawień:

sudo /etc/init.d/nginx reload

Dodatkowe domeny

Domeny dodajemy – podobnie jak w przypadku serwera Apache2 – przez utworzenie nowego pliku vHosta (sites-available) i jego aktywację (skrót w sites-enabled).

Najlepiej zacząć od kopii już istniejącego pliku:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/[nazwa domeny]

I następnie edycję pliku:

sudo nano /etc/nginx/sites-available/[nazwa domeny]

Gdzie wystarczy podmienić 2 linijki:

root /var/www/public_html/; server_name localhost [nazwa domeny] *.[nazwa domeny] 127.0.0.1;

na:

root /var/www/[nazwa domeny]/public_html/; server_name [nazwa domeny];

Warto też ustawić oddzielne pliki logów, modyfikując nazwy plików przy:

  • access_log
  • error_log

Po czym aktywujemy daną konfiguracje poleceniem:

sudo ln -s /etc/nginx/sites-available/[nazwa domeny] /etc/nginx/sites-enabled/[nazwa domeny]

Teraz szybki test, czy wszystko jest ok:

sudo /etc/init.d/nginx configtest

Jeśli tak – restart serwera:

sudo /etc/init.d/nginx restart

lub (preferuje) odświeżenie ustawień:

sudo /etc/init.d/nginx reload

Główny plik konfiguracyjny Nginx (nginx.conf)

Warto jeszcze chwile poświęcić dla pliku nginx.conf:

sudo nano /etc/nginx/nginx.conf

I tu dodajemy lub zmieniamy:

events { worker_connections 1024; multi_accept on; } 

Ukrywamy też informacje o serwerze:

http { [...] server_tokens off; ignore_invalid_headers on; reset_timedout_connection on; [...] }

Oraz jeszcze 2 modyfikacje, o których już kiedyś pisałem:

server_names_hash_bucket_size 256; client_max_body_size 512M;

Nginx i WordPress

W przypadku gdy korzystamy z bardziej rozbudowanych CMSów, jak np. WordPress – zapewne będzie potrzebna jeszcze jedna modyfikacja w pliku strony:

sudo nano /etc/nginx/sites-available/default

Gdzie zmieniamy:

location / { try_files $uri $uri/ /index.html; }

na:

location / { try_files $uri $uri/ /index.php?$args; }

MySQL i phpMyAdmin

Cała procedura instalacji serwera SQL (MySQL) jak i phpMyAdmin jest identyczna jak w przypadku serwera na Apache2, tylko do pliku danej domeny (vHosta):

sudo nano /etc/nginx/sites-available/default

Dodajemy:

location /phpmyadmin { root /usr/share/; index index.php index.html index.htm; auth_basic "STOP"; auth_basic_user_file /var/www/.passwords/.htpasswd; location ~ ^/phpmyadmin/(.+\.php)$ { try_files $uri =404; root /usr/share/; fastcgi_split_path_info ^(.+\.php)(/.+)$; # With php5-fpm: fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; # Nginx 1.2.1: #include fastcgi_params; # Nginx 1.6.1+: include fastcgi.conf; # Więcej informacji w tabelce powyżej } location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ { root /usr/share/; } location /phpMyAdmin { rewrite ^/* /phpmyadmin last; } }

I oczywiście:

sudo /etc/init.d/nginx configtest sudo /etc/init.d/nginx restart

lub

sudo /etc/init.d/nginx configtest sudo /etc/init.d/nginx reload

Testujemy czy serwer działa

Wprawdzie można przetestować serwer dowolną stroną, ale można też za pomocą pliku phpinfo.php:

<?php phpinfo(); ?>

Który otwieramy w przeglądarce, i zobaczymy zapewne coś takiego:

PS. Wpis przeleżał kilka miesięcy w oczekiwaniu aż ktoś wciśnie przycisk „publikuj”, ale wyszło mu to chyba tylko na dobre – przy okazji innych wpisów/poradników (zarówno tych opublikowanych, jak i tych które czekają na swoją kolej) czy projektów które w międzyczasie wykonywałem zawsze coś tam się jeszcze dopisało/zmodyfikował… :-)

(!) Zgłoś błąd na stronie