DVerkh
@DVerkh
Full Stack веб-разработчик

Как настроить Nginx + PHP-FPM + Node.js через HTTP/2 с SSL?

Приветствую, уважаемые знатоки!

Ситуация следующая, хочу настроить Nginx под PHP-FPM (PHP 7.1) через HTTP/2 с использование SSL. Там же хочу поднять Node.js, также с SSL. Сейчас конфиги имеют следующий вид:
nginx.conf

# Пользователь и группа, от имени которых будет запущен процесс.
user www-data www-data;

# Число воркеров (по числу ядер).
worker_processes auto;

# Ограничение на максимальное кол-во открытых файлов для процессов.
worker_rlimit_nofile 65000;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
	# Максимальное кол-во cоединений одного воркера.
	worker_connections 1024;

	# Метод выбора соединений (epoll = Ubuntu || kqueue = FreeBSD)
	use epoll;
	
	# Принимать максимально возможное кол-во соединений.
	multi_accept on;
}

http {
	# Указываем файл с mime-типами и указываем тип данных по-умолчанию.
	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	# Отключить вывод версии в ответе.
	server_tokens off;

	# Метод отправки данных sendfile эффективнее чем read+write.
	sendfile on;

	# Ограничивает объём данных, который может передан за один вызов sendfile(). Нужно для исключения ситуации когда одно соединение может целиком захватить воркер.
	sendfile_max_chunk 128k;

	# Отправлять заголовки и начало файла в одном пакете.
	tcp_nopush on;
	tcp_nodelay on;

	# Сбрасывать соединение если клиент перестал читать ответ.
	reset_timedout_connection on;

	# Разрывать соединение по истечению таймаута при получении заголовка и тела запроса.
	client_header_timeout 10;
	client_body_timeout 10;

	# Разрывать соединение, если клиент не отвечает в течение 2 секунд.
	send_timeout 2;

	# Объем буфера для заголовка и тела запроса.
	client_header_buffer_size 2k;
	client_body_buffer_size 256k;

	# Ограничение на размер тела запроса.
	client_max_body_size 1m;

	# Таймаут для Keep-Alive соединения.
	keepalive_timeout 10;

	# Отключаем логирование доступа к сайту.
	access_log off;

	# Кеширование.
	gzip on;
	gzip_comp_level 5;
	gzip_min_length 512;
	gzip_buffers 8 64k;
	gzip_disable "msie6";
	gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
	gzip_proxied any;

	# Подключаем дополнительные конфиги.
	include /etc/nginx/conf.d/*.conf;
}


site.conf

# Поток для Node.js.
upstream nodejs {
	server localhost:3000;
	keepalive 50;
}

# Перенаправляем с www (http, https) на без-www (https).
server {
	set $_site    "site.ru";
	set $_ssl_crt "/etc/nginx/cert/site.crt";
	set $_ssl_key "/etc/nginx/cert/site.key";

	server_name www.$_site;

	listen 80;
	listen [::]:80 ipv6only=on;
	listen 443 ssl http2;
	listen [::]:443 ssl http2 ipv6only=on;

	ssl_certificate     $_ssl_crt;
	ssl_certificate_key $_ssl_key;

	return 301 https://$_site$request_uri;
}

# Перенаправляем с без-www (http) на без-www (https).
server {
	set $_site "site.ru";

	server_name $_site;

	listen 80;
	listen [::]:80 ipv6only=on;

	return 301 https://$_site$request_uri;
}

# Основной обработчик.
server {
	set $_site      "site.ru";
	set $_ssl_crt   "/etc/nginx/cert/site.crt";
	set $_ssl_key   "/etc/nginx/cert/site.key";
	# set $_ssl_trust "";
	set $_root      "/projects/site/site/www";
	set $_index     "index.php";

	server_name $_site;

	listen 443 ssl http2;
	listen [::]:443 ssl http2 ipv6only=on;

	# Настройки SSL.
	ssl_certificate     $_ssl_crt;
	ssl_certificate_key $_ssl_key;
	ssl_session_timeout 1d;
	ssl_session_cache   shared:SSL:50m;
	ssl_session_tickets off;

	# Шифрование.
	ssl_protocols             TLSv1.2;
	ssl_ciphers               'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
	ssl_prefer_server_ciphers on;

	# HSTS.
	add_header Strict-Transport-Security max-age=15768000;

	# OCSP Stapling.
	# ssl_stapling        on;
	# ssl_stapling_verify on;

	# Root CA and Intermediate certs.
	# ssl_trusted_certificate $_ssl_trust;

	# Stapling resolver.
	# resolver 8.8.8.8;

	# Корневая директория и индексный файл.
	root $_root;
	index $_index;

	# Запрет на доступ к скрытым и важным файлам.
	location ~ /\. {
		deny all;
	}

	location = /private\.php {
		deny all;
	}

	location = /config\.php {
		deny all;
	}

	location ~ /\.ht {
		deny all;
	}

	# Разрешение доступа.
	location = /favicon\.ico {
		allow all;
	}

	location = /robots\.txt {
		allow all;
	}

	location = /sitemap\.xml {
		allow all;
	}

	# Поиск запрашиваемого URI по трем путям.
	location / {
		try_files $uri $uri/ /$_index;
	}

	# Кеширование статики.
	location ~* \.(js|css|png|jpe?g|gif|ico)$ {
		expires max;
	}

	# PHP.
	location ~* \.php$ {
		# PHP-FPM	
		include fastcgi_params;

		fastcgi_pass unix:/run/php/php7.0-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_index $_index;

		fastcgi_intercept_errors on;
		fastcgi_ignore_client_abort off;
		fastcgi_connect_timeout 60;
		fastcgi_send_timeout 180;
		fastcgi_read_timeout 180;
		fastcgi_buffer_size 128k;
		fastcgi_buffers 4 256k;
		fastcgi_busy_buffers_size 256k;
		fastcgi_temp_file_write_size 256k;
		fastcgi_param HTTPS on;
	}
	
	# Node.js.
	location /nodejs {
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-NginX-Proxy true;
		proxy_set_header X-Forwarded-Proto https;
		proxy_set_header Host $host;

		proxy_pass http://nodejs;

		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header Host $http_host;

		proxy_http_version 1.1;
		proxy_ssl_session_reuse off;
		proxy_cache_bypass $http_upgrade;
		proxy_redirect off;
	}
}



Сервер: Intel Xeon X3450, 4 ядра, 8ГБ, порт 1 Гбит/с. Взял на первое время.

Не могли бы вы дать советы касательно текущих настроек, направить на путь истинный, указать на ошибки? Особенно интересует SSL и HTTP/2. Буду вам очень признателен!
  • Вопрос задан
  • 1015 просмотров
Решения вопроса 2
VELIK505
@VELIK505
Руководитель департамента profitcentr.com
Ну а что именно то интересует? Щас всё работает так? У всех всё равно всё по разному и сугубо индивидуально.
Но в целом мне не нравится сразу бросается в глаза:
worker_connections 1024;

дефолтовое мелкое значение.
ssl_protocols TLSv1.2;

Ок. А как старенькие android-ы. Юзеры со старенькими айосями на стареньком сафари? Даже IE10 на windows 10 не фурычит по 1.2
может всё таки стоит сделать так?
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

и
send_timeout 2;

Не особо хорошо если юзер с мобилы или медленного соединения например с E.
Я например у себя 30 выставил. Но 2ва это точно маловато.
user www-data www-data;

Почему 2ва раза подряд указан один и тот же юзер?
Может надо так?
user www-data;

сгенерьте сертификат ещё .pem настройте OCSP это будет быстрее чем CAC
Всё остальное уже по ситуации смотреть где что подкручивать.

Ну а с нодой то чего? Проблем не должно быть всё так же, но только укажешь
var https = require('https');

и
httpsOptions = {
key: fs.readFileSync("/..../..../.../mysite.com.key"), // путь к ключу
cert: fs.readFileSync("/..../..../.../mysite.com.crt") // путь к сертификату
}
Ответ написан
Lynn
@Lynn
nginx, js, css
server_name $_site;

Так не работает. В server_name не работают переменные. В ssl_certificate/ssl_certificate_key тоже не работают.

location = /favicon\.ico

Это не регулярка — не нужно экранировать точку.

location ~ /\.ht — лишнее. Выше уже запрещено всё начинающееся с точки.

root $_root;
Раньше был баг, что рут из одной переменной считался относительным и дописывался к дефолтному. Может и починили уже, но я бы не стал так делать
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы