Nginx — высокопроизводительный веб-сервер и почтовый прокси-сервер с открытым исходным кодом, обслуживающий огромное количество высоконагруженных сайтов по всему миру. Nginx завоевал широкую популярность благодаря своей лёгкости, надёжности, масштабируемости и простоте настройки.
Если вы хотите облегчить трудовые будни вашего сервера, nginx поможет снять с него часть нагрузки, а также повысить безопасность и отказоустойчивость ваших сайтов.
В этой статье мы расскажем, как установить и настроить nginx, и рассмотрим его основные возможности на примере связки с php-fpm (PHP FastCGI Process Manager).
Установка nginx в Linux
Если nginx ещё не установлен в вашей системе, сделать это очень просто:
sudo apt update && sudo apt install nginx
для deb-based дистрибутивов (Debian и другие) и
sudo dnf update && sudo dnf install nginx
для rpm-based (CentOS и прочие).
В дальнейшем мы будем говорить о Debian и CentOS, при необходимости останавливаясь на некоторых технических различиях этих платформ. Какой бы дистрибутив вы не выбрали, любой из них с успехом справится с обслуживанием вашего сайта.
Запуск nginx
После стандартной установки nginx запуск службы (service) можно выполнить командой:
sudo systemctl start nginx
Автозапуск nginx после перезагрузки системы включается так:
sudo systemctl enable nginx
Статус службы можно проверить этой командой:
sudo systemctl status nginx
Если все прошло успешно, вы должны увидеть строки:
...
Loaded: loaded
Active: active (running)
...
Теперь, если в браузере ввести адрес вашего сервера, например http://localhost
в случае локальной установки, то вы увидите тестовую страницу приветствия.
Если вы настраиваете сервер удалённо, здесь и далее замените localhost
на IP-адрес или доменное имя вашего сайта.
Если что-то пошло не так, возможно, придётся добавить необходимое правило для вашего брандмауэра (firewall). В любом случае вы всегда можете посмотреть подробный отчёт о работе nginx в журналах (логах) службы (об этом чуть позже), в терминале или с помощью команды
sudo journalctl -u nginx
Nginx в Docker
Если ваш сайт будет работать в контейнере и Docker уже установлен, то запустить nginx в новом контейнере можно командой
docker run -p 80:80 nginx
Если nginx ещё не установлен, эта команда также автоматически скачает и установит его из официального образа. Ключ -p
здесь отвечает за сопоставление, или «проброс», портов: первым указывается порт на локальном компьютере, вторым — внутри контейнера. Поскольку мы пока не меняем настройки nginx, для тестирования используем стандартный порт 80 для http соединений.
Теперь можно посмотреть список запущенных контейнеров:
docker ps
Обратите внимание на столбцы IMAGE и PORTS. В нашем примере в выводе этой команды должна присутствовать строка
... nginx ... 0.0.0.0:80->80/tcp ...
Это значит, что nginx готов принимать входящие HTTP соединения по IP-адресу вашего сервера. Например, если docker установлен локально, то по адресу http://localhost
в браузере вы увидите страницу приветствия с надписью.
Отлично, мы запустили nginx, конфигурация по умолчанию сделала за нас всю основную работу.
Запуск внутри контейнера особенно удобен для разработки, потому что позволяет отлаживать неограниченное число копий сайта с разными настройками и версиями программ.
Структура каталогов nginx
Во время установки nginx может создавать несколько папок в зависимости от вашего дистрибутива Linux. Нас интересует, в первую очередь, главный файл конфигурации nginx.conf
, который по умолчанию обычно расположен в каталоге /etc/nginx/
.
На тот случай, если на вашем сервере будет работать несколько сайтов, их настройки удобно вынести в отдельные файлы. Debian предлагает использовать для этого папку /etc/nginx/sites-available/
или /etc/nginx/conf.d/
на выбор, а CentOS — только /etc/nginx/conf.d/
.
В этом руководстве мы поместим настройки всех наших сайтов в каталог /etc/nginx/conf.d/
, что обеспечит переносимость конфигурации на любой дистрибутив.
Тестовая страница приветствия находится в каталоге /usr/share/nginx/html
, а журналы службы записываются в /var/log/nginx/
.
Первичная настройка nginx
Теперь можно приступать к самому интересному — настройке. Давайте взглянем на основной файл конфигурации /etc/nginx/nginx.conf
. Он содержит строки, содержащие директивы nginx и их параметры, и комментарии, начинающиеся со знака «#».
Общая структура конфигурации nginx выглядит так:
...
http {
...
server {
...
location ... {
...
}
}
}
Блок server
определяет общие настройки вашего сайта, а location
обрабатывает конкретные пути (URI) в адресах запросов. Блоков server
и location
может быть несколько. Как внутри, так и снаружи блоков могут располагаться директивы — строки, содержащие имя директивы и её параметры и завершающиеся точкой с запятой.
Конечно, можно внести все настройки прямо в файл nginx.conf
, но это неудобно.
Во-первых, у вас может быть несколько сайтов. Тогда вам понадобится несколько блоков server, и файл станет настолько большим, что его будет трудно читать.
Во-вторых, некоторые настройки могут повторяться в разных блоках, поэтому обычно их выносят в отдельные файлы и в нужных местах подключают директивой include.
В-третьих, если вынести настройки каждого блока server в отдельную конфигурацию, очень удобно включать и отключать сайты простым переносом или переименованием всего одного файла.
В-четвёртых, вы всегда будете видеть, какой именно сайт был изменён последним по времени модификации файла.
И в пятых, хранение настроек сайта в отдельном файле сводит к минимуму риск случайного повреждения общей конфигурации при редактировании.
Надеемся, мы убедили вас придерживаться правила «один сайт — один файл конфигурации».
А пока давайте рассмотрим nginx.conf
, настройка которого была выполнена автоматически при установке пакета, повнимательней. Полная версия этого файла в Debian выглядит так:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
а в CentOS так:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
Как мы видим, эти файлы очень похожи. Разница в том, что основная конфигурация CentOS содержит блок server для сайта по умолчанию, который в Debian вынесен в отдельный файл в каталоге /etc/nginx/sites-enabled/
и включается директивой include
. После установки мы найдем тут файл default
(на самом деле, являющийся ссылкой на файл /etc/nginx/sites-available/default
) следующего содержания:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
Как мы убедились ранее, этот блок указывает службе nginx принимать, или, как говорят администраторы, «слушать» входящие соединения на порту 80. Это порт по умолчанию для протокола HTTP.
Теперь давайте в каталоге /etc/nginx/conf.d/
создадим файл example.conf
с настройками нашего первого сайта, или, в терминах nginx, «виртуального сервера»:
sudo nano /etc/nginx/conf.d/example.conf
Конечно, вместо nano вы можете использовать свой любимый редактор.
Поместите в этот файл такие строки:
server {
listen 8080;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
Обратите внимание, что наш новый виртуальный сервер слушает порт 8080. Это сделано потому, что порт 80 уже занят сервером по умолчанию, описанным выше.
После перезапуска nginx конфигурация вступит в силу:
sudo systemctl restart nginx
Давайте проверим результат, набрав в адресной строке браузера http://localhost:8080/
. Вы должны увидеть уже знакомую нам страницу приветствия.
А теперь давайте отредактируем example.conf
таким образом, чтобы nginx перенаправлял, или «проксировал», входящие соединения службе php-fpm
. Для этого в блоке server
добавьте ещё один блок location
:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
Этот блок обработает все запросы к динамическим файлам с расширением .php
, а директива fastcgi_pass
здесь делает основную работу — проксирует запросы на порт 9000 (номер порта можно изменить). Адрес 127.0.0.1 используется, если оба сервера запущены на одном компьютере. Теперь можно настроить ваш основной сервер php-fpm на прослушивание локального адреса http://127.0.0.1:9000.
Обратите внимание на использование специальной директивы fastcgi_pass. Если вам нужно перенаправить запрос другой службе или другому серверу в сети, можно использовать более общий вариант — proxy_pass
:
proxy_pass 127.0.0.1:9000;
Если ваши службы работают на разных физических серверах, здесь и в дальнейших примерах замените 127.0.0.1
на их IP-адреса в сети.
Полная версия конфигурации сайта теперь должна выглядеть таким образом:
server {
listen 8080;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
}
После внесения изменений не забудьте перезапустить службу nginx:
sudo systemctl restart nginx
Установка и настройка php-fpm
Установить пакет php-fpm можно командой
sudo apt install php-fpm
для Debian и
sudo dnf install php-fpm
для CentOS.
Конфигурация для CentOS будет находится в файле /etc/php-fpm.d/www.conf
,
а для Debian в /etc/php/8.2/fpm/pool.d/www.conf
.
Номер установленной версии PHP (в нашем примере 8.2) можно узнать так:
sudo ls /etc/php/
или так:
php --version
Затем в файле конфигурации www.conf
добавьте строку:
listen = 127.0.0.1:9000
а существующую директиву listen
закомментируйте:
; listen = /run/...
Для проверки работы связки nginx — php-fpm давайте создадим тестовый файл:
sudo echo "<?php echo phpinfo(); ?>" > /var/www/html/info.php
и перезапустим службу php-fpm:
sudo systemctl restart php8.2-fpm
для Debian или
sudo systemctl restart php-fpm
для CentOS.
Если вы всё сделали правильно, то по адресу http://localhost:8080/info.php
в браузере откроется стандартный вывод phpinfo.
А если нет, лучше заглянуть в журнал /var/log/nginx/error.log
. Кроме того, вы всегда можете проверить прослушиваемые порты командой:
netstat -lntp
Как видите, настройка веб-сервера nginx в связке с php-fpm также не вызывает особых сложностей.
Настройка безопасного соединения
Если ваш сервер принимает или передаёт чувствительные данные пользователя, например данные авторизации или платёжную информацию, рекомендуется использовать протокол безопасной передачи данных HTTPS. Этот протокол по умолчанию использует порт 443. Для прослушивания этого порта в блок server в файле конфигурации сайта нужно добавить строку
listen 443 ssl;
Кроме того, для работы по протоколу HTTPS вам понадобится сертификат SSL. Его можно как купить, так и получить бесплатно, например в центре сертификации Let’s Encrypt. Для того, чтобы nginx самостоятельно проверял сертификаты, нужно добавить строки
ssl_certificate example.ru.crt
ssl_certificate_key example.ru.key;
где www.example.ru.crt
— абсолютный путь к файлу публичного сертификата, а www.example.ru.key
— секретный ключ. Например, для сертификатов Let’s Encrypt эти строки могут выглядеть так:
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
Разумеется, права доступа к файлу с секретным ключом следует ограничить.
Таким образом, минимальная рабочая конфигурации сайта теперь может выглядеть примерно так:
server {
listen 8080;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
}
server {
listen 443 ssl;
server_name example.ru www.example.ru;
root /var/www/html;
index index.html index.htm;
charset UTF-8;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
}
Для автоматического обновления SSL-сертификатов Let’s Encrypt вы можете использовать клиент certbot. Документацию по его настройке можно найти на официальном сайте (на английском языке) или в статье «Как установить бесплатный сертификат Let’s Encrypt и настроить автоматический перевыпуск».
Обратите внимание, что этот виртуальный сервер принимает только запросы к сайту example.ru
(и его «алиасу» www.example.ru
), а все остальные соединения продолжает обрабатывать блок server
по умолчанию.
Если вы ещё не настроили DNS для домена example.ru или отлаживаете сервер локально, пользуясь самозаверенным сертификатом, вы можете временно указать соответствие этого домена IP-адресу сервера в файле hosts на вашем персональном компьютере, добавив в него строку
127.0.0.1 example.ru www.example.ru
Расположение файла hosts
зависит от операционной системы. Для Windows это будет c:\windows\system32\drivers\etc\hosts
, для MacOS — /private/etc/hosts
, а для Linux — /etc/hosts
. Для редактирования этого файла потребуются права администратора.
После включения протокола HTTPS рекомендуется проверить соответствие ваших настроек современным требованиям безопасности. Для этого удобно использовать онлайн сервисы, например: https://audit.statdom.ru/, https://observatory.mozilla.org/, https://www.wormly.com/test_ssl и другие.
Редирект с http на https
Для того, чтобы пользователи вашего сайта случайно не зашли на страницу авторизации по протоколу http, лучше перенаправить их на безопасный протокол https автоматически. Nginx легко справится и с этой задачей. Просто добавьте в файл конфигурации вашего сайта в блок server, прослушивающий порт 80, такую директиву:
return 301 https://$host$request_uri;
и перезапустите nginx.
В итоге полная версия файла будет такой:
server {
listen 80;
server_name example.ru www.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.ru www.example.ru;
root /var/www/html;
index index.html index.htm;
charset UTF-8;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
}
Обратите внимание, что в этой конфигурации мы снова прослушиваем порт 80, но на этот раз на домене example.ru. Если из блока server
, отвечающего за редирект, убрать директиву server_name
, перенаправление работать не будет, так как nginx применит настройку по умолчанию. Другими словами, при добавлении виртуальных доменов вам нужно следить, чтобы один и тот же порт не использовался на одинаковых доменах.
Если виртуальный сервер по умолчанию, созданный автоматически при установке nginx, вам больше не нужен, можно просто удалить блок server
, описанный в начале этого руководства. В Debian вместо этого достаточно удалить только символическую ссылку на файл default
:
sudo rm /etc/nginx/sites-enabled/default
После этого, если это необходимо, вы можете удалить директивы server_name
из конфигурации вашего сайта, чтобы nginx использовал его по умолчанию.
Если вам понадобится изменять основной файл настройки nginx, лучше предварительно сохранить резервную копию:
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.orig
Директивы nginx
Мы уже рассмотрели блочные директивы http, server и location. Теперь можно привести краткий справочник прочих директив, используемых в этом руководстве (в алфавитном порядке):
- access_log — задаёт путь, формат и настройки буферизованной записи в лог;
- allow — позволяет ограничить доступ для определённых адресов клиентов;
- auth_basic — включает проверку имени и пароля пользователя по протоколу «HTTP Basic Authentication»;
- auth_basic_user_file — задаёт файл, в котором хранятся имена и пароли пользователей;
- charset — добавляет указанную кодировку в поле «Content-Type» заголовка ответа;
- client_max_body_size — задаёт максимально допустимый размер тела запроса клиента;
- default_type — задаёт MIME-тип ответов по умолчанию;
- deny — запрещает доступ для указанной сети или адреса;
- error_log — конфигурирует запись в лог;
- error_page — задаёт URI, который будет показываться для указанных ошибок;
- events — предоставляет контекст файла конфигурации, в котором указываются директивы, влияющие на обработку соединений;
- fastcgi_pass — задаёт адрес FastCGI-сервера. Адрес может быть указан в виде доменного имени или IP-адреса и порта;
- include — включает в конфигурацию другой файл или файлы, подходящие под заданную маску;
- index — определяет файлы, которые будут использоваться в качестве индекса;
- keepalive_timeout — задаёт таймаут, в течение которого keep-alive соединение с клиентом не будет закрыто со стороны сервера;
- limit_conn — задаёт зону разделяемой памяти и максимально допустимое число соединений для одного значения ключа;
- limit_conn_zone — задаёт параметры зоны разделяемой памяти, которая хранит состояние для разных значений ключа;
- limit_req — задаёт зону разделяемой памяти (zone) и максимальный размер всплеска запросов (burst);
- limit_req_zone — задаёт параметры зоны разделяемой памяти, которая хранит состояние для разных значений ключа;
- log_format — задаёт формат лога;
- pid — задаёт файл, в котором будет храниться номер (PID) главного процесса;
- proxy_cache — задаёт зону разделяемой памяти, используемой для кэширования;
- proxy_cache_path — задаёт протокол и адрес проксируемого сервера;
- proxy_pass — задаёт протокол и адрес проксируемого сервера;
- proxy_set_header — позволяет переопределять или добавлять поля заголовка запроса, передаваемые проксируемому серверу;
- return — завершает обработку и возвращает клиенту указанный код;
- root — задаёт корневой каталог для запросов;
- satisfy — разрешает доступ, если все (all) или хотя бы один (any) из модулей разрешают доступ;
- server_name — задаёт имена виртуального сервера;
- ssl_certificate — указывает файл с сертификатом в формате PEM для виртуального сервера;
- ssl_certificate_key — указывает файл с секретным ключом в формате PEM для виртуального сервера;
- stub_status — информация о состоянии будет доступна из данного location;
- tcp_nopush — разрешает или запрещает использование параметра сокета TCP_CORK при использовании sendfile;
- types_hash_max_size — задаёт максимальный размер хэш-таблиц типов;
- upstream — описывает группу серверов;
- user — задаёт пользователя и группу, с правами которого будут работать рабочие процессы;
- worker_processes — задаёт число рабочих процессов.
С полным перечнем директив можно ознакомиться на официальном сайте.
Важно упомянуть, что параметры nginx, установленные этими директивами в главном файле конфигурации, наследуются файлами виртуальных серверов, но вы всегда можете переопределить их там. Другими словами, все параметры, не указанные явно в конфигурации вашего сайта, nginx возьмёт из файла nginx.conf
.
Переменные в nginx
В файлах конфигурации можно использовать встроенные переменные. Например, выше мы использовали переменные $host
и $request_uri
. $host
содержит название вашего домена (в примере это example.ru или www.example.ru), а $request_uri
— всю остальную часть запроса (путь) или пустую строку.
Другим полезным примером может быть передача доменного имени и IP-адреса в заголовках запроса. Для этого достаточно в блок location добавить строки
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
Здесь мы использовали переменные $http_host
и $remote_addr
. С полным списком переменных можно ознакомиться в официальной документации.
Команды nginx
Мы уже упоминали, что после изменения настроек службы её нужно перезапустить командой restart
. Но для этого в nginx есть и более удобная команда — reload
:
sudo systemctl reload nginx
или
sudo nginx -s reload
Эта команда выполнит «горячую» перезагрузку без остановки nginx. При наличии ошибки в одном из файлов конфигурации перезагрузка выполнена не будет, а сервис продолжит работу. Настоятельно рекомендуется на рабочем сервере использовать именно reload
.
Другая полезная команда, выполняющая проверку всех файлов конфигурации без перезагрузки, это
sudo nginx -t
Для немедленной остановки используется команда
sudo systemctl stop nginx
Статические файлы
Теперь, когда вы научились свободно обращаться с вашим сервером и выполнили основные настройки, пришло время сделать что-то полезное. Одна из самых востребованных функций nginx — возможность отдавать клиентам «статические» файлы, такие как css, js, изображения и любые другие. Для примера, давайте поместим эти файлы в отдельную папку и добавим в блок server такую запись:
location /static {
root /путь/к/папке/со/статическими/файлами;
}
Этот блок обработает все запросы, поступившие на адрес https://example.ru/static
. Теперь ваш основной сервер не будет тратить ресурсы на передачу статического содержимого. Просто и эффективно, не правда ли?
При необходимости в блоке location
вы можете использовать регулярные выражения так же, как мы делали это для файлов .php:
location ~ \.(jpg|jpeg|png|ico|gif|css|js)$ {
root /путь/к/папке/со/статическими/файлами;
}
Кэширование в nginx
Что, если после того, как ваш сайт наберёт обороты, вы поймёте, что php-fpm начал плохо справляться с возросшей нагрузкой? В таком случае разумно будет на непродолжительное время запомнить наиболее частые ответы сервера во временных файлах (кэше) и отдавать эти файлы клиенту напрямую.
В nginx за этот режим отвечает директива proxy_cache_path
. Вот пример:
proxy_cache_path /var/lib/nginx/proxy_cache keys_zone=nginx_proxy_cache:10m;
Здесь /var/lib/nginx/proxy_cache
— путь хранения кэша. Этот каталог можно предварительно создать командой
sudo mkdir /var/lib/nginx/proxy_cache
где параметр keys_zone
определяет имя зоны для хранения активных ключей и размер выделяемой для этого памяти.
Чтобы включить режим кэширования, нужно поместить директиву proxy_cache_path
в блок http
(контекст верхнего уровня), а в блок server
добавить заданное этой директивой имя зоны. Например:
http {
...
proxy_cache_path /var/lib/nginx/proxy_cache keys_zone=nginx_proxy_cache:10m;
server {
proxy_cache nginx_proxy_cache;
location ~ \.php$ {
...
fastcgi_pass 127.0.0.1:9000;
}
}
}
Мониторинг nginx
Кроме чтения журналов, nginx предоставляет возможность отслеживать его статус на «странице состояния» с помощью модуля ngx_http_stub_status_module
. Проверить наличие этого модуля в вашей системе можно командой
nginx -V 2>&1 | grep -o http_stub_status_module
Если модуль установлен, вы можете добавить в блок server
ещё один блок location
:
location /nginx-status {
stub_status on;
}
После перезагрузки nginx вы сможете открыть в браузере страницу https://example.ru/nginx-status, содержащую базовую информацию о состоянии службы, например:
Active connections: 21
server accepts handled requests
907 907 453
Reading: 12 Writing: 74 Waiting: 18
Полная версия файла конфигурации виртуального сервера теперь должна быть такой:
server {
listen 80;
server_name example.ru www.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.ru www.example.ru;
charset UTF-8;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
location /nginx-status {
stub_status on;
}
}
Доступные состояния расшифровываются так:
- active connections — текущее число активных клиентских соединений, включая Waiting соединения;
- accepts — суммарное число принятых клиентских соединений;
- handled — суммарное число обработанных соединений;
- requests — суммарное число клиентских запросов;
- reading — текущее число соединений, в которых nginx в настоящий момент читает заголовок запроса;
- writing — текущее число соединений, в которых nginx в настоящий момент отвечает клиенту;
- waiting — текущее число бездействующих клиентских соединений в ожидании запроса.
Балансировка нагрузки
Перед высоконагруженными сайтами часто встаёт задача распределения нагрузки между группой серверов, обрабатывающих запросы клиентов. Nginx в роли регулятора нагрузки может помочь вам справится с увеличением трафика без необходимости покупки дополнительного оборудования. Благодаря простоте настройки конфигурация такого балансировщика нагрузки может выглядеть очень лаконично:
http {
upstream load_balancer {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
}
server {
listen 80;
server_name example.ru;
location / {
proxy_pass http://load_balancer;
include proxy_params;
}
}
}
Здесь load_balancer — произвольное имя вышестоящего потока (upstream), используемое в директиве proxy_pass
. В этом примере nginx распределяет запросы между двумя независимыми службами, слушающими порты 9000 и 9001.
Безопасность сайтов в nginx
Мы уже рассматривали работу nginx по безопасному протоколу HTTPS. Теперь давайте включим авторизацию пользователей, например при просмотре настроенной выше страницы мониторинга. Для этого измените location
таким образом:
location /nginx-status {
stub_status on;
auth_basic "Restricted area";
auth_basic_user_file /etc/nginx/conf.d/htpasswd;
}
После перезагрузки службы nginx будет запрашивать имя пользователя и пароль.
Создать файл /etc/nginx/conf.d/htpasswd
можно так:
sudo htpasswd -c /etc/nginx/conf.d/htpasswd admin
Эта команда предложит вам ввести пароль пользователя admin и подтвердить его, а затем поместит зашифрованные данные в указанный файл. Утилита htpasswd входит в состав пакета apache2-utils в Debian и httpd-tools — в CentOS. Если этот пакет ещё не установлен в вашей системе, выполните стандартную команду install
.
Кроме запроса авторизации, мы можем также ограничить доступ к странице по IP-адресу пользователя:
location /nginx-status {
stub_status on;
satisfy any;
allow 192.168.0.0/24;
deny all;
}
Директива allow
разрешает доступ к странице только из локальной сети. Таких директив при необходимости может быть несколько — например, вы можете перечислить здесь конкретные IP-адреса администраторов.
Ещё мы можем закрыть доступ к некоторым каталогам в структуре сайта, например блок
location ~ /.git {
return 404;
}
закроет доступ к директории .git.
Вот что у нас должно получиться:
server {
listen 80;
server_name example.ru www.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.ru www.example.ru;
root /var/www/html;
index index.html index.htm;
charset UTF-8;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
location /nginx-status {
stub_status on;
stub_status on;
satisfy any;
allow 192.168.0.0/24;
deny all;
auth_basic "Restricted area";
auth_basic_user_file /etc/nginx/conf.d/htpasswd;
}
location ~ /.git {
return 404;
}
}
Как видите, nginx позволяет нам свободно комбинировать различные ограничения.
Предотвращение DDoS атак
DoS, или Denial of Service (отказ в обслуживании), и его разновидность DDoS, или Distributed Denial of Service (распределённый отказ в обслуживании), — это тип хакерской атаки, вызывающий перегрузку сервера и, в результате, замедление или полную недоступность сайта. Конечно, nginx, конфигурация которого позволяет выполнять очень широкий спектр задач, придёт нам на помощь и в этот раз.
Предотвращать последствия DDoS атак можно несколькими методами. Выше мы уже рассматривали балансировку нагрузки и кэширование, которые также снижают возможный ущерб от DDoS. Ещё одним способом добиться стабильной работы сайта может стать ограничение скорости обработки запросов. Давайте добавим к конфигурации нашего сайта директивы limit_req_zone
и limit_req
:
limit_req_zone $binary_remote_addr zone=limitbyreq:10m rate=10r/s;
server {
...
location ~ \.php$ {
limit_req zone=limitbyreq;
...
}
}
В этом примере limit_req_zone
определяет ограничение скорости обработки для каждого IP-адреса клиента до 10 запросов в секунду, а limit_req
включает это ограничение для нужного вида запросов (здесь мы снимаем нагрузку с php-fpm).
Ещё один метод борьбы с нежелательным трафиком — ограничение количества одновременных подключений с помощью директивы limit_conn
:
limit_conn_zone $binary_remote_addr zone=limitbyaddr:20m;
server {
...
location ~ \.php$ {
limit_conn limitbyaddr 50;
...
}
}
В этом примере мы позволяем подключиться к php-fpm не более 50-ти клиентам одновременно.
Конечно, на этом возможности по борьбе с хакерскими атаками не ограничиваются. Вы также можете использовать директиву keepalive_timeout
, позволяющую удерживать одно соединение для каждого клиента вместо открытия нового для каждого запроса, настроить сжатие и буферизацию.
Ошибки nginx
Мы уже узнали, как настроить nginx и познакомились с общими методами решения возможных проблем, почти неизбежно возникающих при настройке сервера. Напомним, что лучшая практика при отладке служб — это анализ журналов (логов). Также, разумеется, первым делом нужно проверить статус служб и убедиться, что они находятся в активном состоянии. Кроме того, стоит обратить внимание на коды ошибок, которые предоставляет нам nginx. Вот некоторые из них:
502 Bad Gateway
Эта ошибка означает, что nginx не может получить ответ от службы, на которую перенаправлен запрос, в нашем случае php-fpm. Как правило, возникает из-за отключённого или неверно настроенного сервиса, а так же в случае ошибки 500 в самом сервисе. Рекомендации по устранению приведены в разделе «Установка и настройка php-fpm». Ошибка 502 может также возникать, если php-fpm не справляется с нагрузкой. В этом случае лучше ещё раз взглянуть на раздел «балансировка нагрузки».
503 Service Unavailable
Сервер временно не готов обработать запрос, например из-за перегрузки или при проведении технических работ.
504 Gateway Time-out
Означает, что служба не отвечает в течение установленного времени. В случае php-fpm можно попробовать увеличить это ограничение:
location ~ \.php$ {
...
fastcgi_read_timeout 120;
}
403 Forbidden
Ошибка авторизации. Пользователь неверно ввёл логин/пароль или пытается зайти в авторизованную зону вашего сайта, не имея достаточных прав.
413 Request Entity Too Large
Возможно, клиент пытается загрузить слишком большой файл. Ограничение размера файла можно изменить директивой client_max_body_size
в блоке server:
server {
...
client_max_body_size 100m;
...
}
404 Not Found
Означает, что запрашиваемого файла просто нет в структуре сайта. Эта ошибка не имеет прямого отношения к nginx, но тем не менее её, как и другие ошибки, можно обработать.
Давайте будем показывать пользователям вместо сухой технической информации красивые страницы в фирменном стиле вашего сайта. Для этого добавьте в блок server ещё несколько директив, например:
error_page 404 /404.html;
location = /404.html {
internal;
}
При необходимости в блоке location вы также можете использовать директиву root для указания каталога, содержащего файл страницы ошибки.
Теперь вы можете отредактировать HTML страницу /var/www/html/404.html
в стиле вашего сайта. Таким же образом можно обработать и другие ошибки. Вот полный пример:
limit_conn_zone $binary_remote_addr zone=limitbyaddr:20m;
limit_req_zone $binary_remote_addr zone=limitbyreq:10m rate=10r/s;
server {
listen 80;
server_name example.ru www.example.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.ru www.example.ru;
root /var/www/html;
index index.html index.htm;
charset UTF-8;
ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
limit_req zone=limitbyreq;
limit_conn limitbyaddr 50;
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}
location /static {
root /var/www/html;
}
location /nginx-status {
stub_status on;
stub_status on;
satisfy any;
allow 192.168.0.0/24;
deny all;
auth_basic "Restricted area";
auth_basic_user_file /etc/nginx/conf.d/htpasswd;
}
location ~ /.git {
return 404;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
error_page 403 413 500 502 503 504 /500.html;
location = /500.html {
internal;
}
}
Заключение
В этом руководстве мы намеренно приводим лишь минимальную работающую конфигурацию. Администратору сервера крайне желательно разобраться с каждым добавленным параметром самостоятельно. В дальнейшем это сэкономит вам массу времени и нервов в случае неожиданного «падения» вашего сайта, которое, как показывает практика, может произойти в самый неподходящий момент по независящим от вас причинам. Поэтому мы не даём готовых рецептов, но предлагаем хорошую отправную точку для начала работы.
В качестве домашнего задания рекомендуем перенести структуру вашего сайта из каталога по умолчанию /var/www/html
, например, в домашнюю папку пользователя, используя директиву root
в блоке server
, и определить нужный индексный файл с помощью директивы index
.
Конечно, этот краткий обзор не может включать в себя все варианты использования такого мощного сервера, как nginx. Тонкости его применения настолько обширны, что могут составить целую книгу. В любом случае, вся нужная информация содержится в официальном руководстве.
Удачи в настройке и работе!