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:

patryk@rpi01 ~ $ 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:

debian_nginx_php-fpm_phpinfo

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
Pomogłem? To może postawisz mi wirtualną kawę?
LUTy dla D-Cinelike (DJI Mini 3 Pro, DJI Avata, OSMO Pocket) od MiniFly
Wdrożenie Omnibusa w sklepie na WooCommerce
Jak (legalnie) latać dronem w Kategorii Otwartej
Patryk