nginx (Русский)

Состояние перевода:
На этой странице представлен перевод статьи
nginx
. Дата последней синхронизации: 18 июля 2022. Вы можете
помочь
синхронизировать перевод, если в английской версии произошли
изменения
.
nginx
(произносится "э́нжин-э́кс" или "э́нжин-и́кс") — это свободный высокопроизводительный HTTP-сервер с открытым исходным кодом, а также обратный прокси и IMAP/POP3 прокси-сервер, написанный Игорем Сысоевым в 2005 году. nginx получил широкое распространение благодаря своей стабильности, богатой функциональности, простой настройке и низкому потреблению ресурсов.
Данная статья описывает установку nginx и интеграцию с
PHP
через
#FastCGI
.
Установка
Установите
один из пакетов:
nginx-mainline
- основная ветка: новые возможности, обновления и исправления ошибок.
nginx
- стабильная ветка; только исправления серьёзных ошибок.
angie
AUR
- форк, предполагает подмену nginx на месте без переработки конфигурации с расширением возможностей.
Рекомендуется использовать основную (mainline) ветку. Основная причина для использования стабильной ветки — возможная несовместимость со сторонними модулями или непреднамеренное появление ошибок при реализации новых функций.
Примечание
Все модули nginx, доступные в
официальных репозиториях
, в качестве зависимости требуют пакет
nginx
(а не
nginx-mainline
). Возможно, стоит просмотреть список модулей на наличие тех, которые вам могут понадобиться, прежде чем принимать решение о выборе между
nginx
и
nginx-mainline
. Модули для
nginx-mainline
можно найти в
пользовательском репозитории Arch
.
Если для обеспечения дополнительной безопасности вы хотите установить nginx в chroot-окружении, смотрите раздел
#Установка в chroot
.
Запуск
Запустите/включите
службу
nginx.service
или
angie.service
, если вы используете Angie.
Страница по умолчанию, доступная по адресу
http://127.0.0.1
располагается в
/usr/share/nginx/html/index.html
.
Настройка
Первые шаги по настройке и использованию nginx описаны в официальном
руководстве для начинающих
. Вы можете настроить сервер, редактируя файлы в
/etc/nginx/
; главный файл настроек расположен в
/etc/nginx/nginx.conf
.
Более подробную информацию можно прочитать на странице
Nginx Configuration Examples
[
устаревшая ссылка
2025-08-16 ⓘ]
и в
официальной документации
.
Приведенные далее примеры покрывают большинство типичных потребностей. Предполагается, что вы используете стандартное место расположения веб-документов (
/usr/share/nginx/html
). Если это не так, замените путь на свой.
Совет
DigitalOcean предоставляет
инструмент для настройки nginx
.
Пример настройки
/etc/nginx/nginx.conf
user http;
worker_processes auto;
worker_cpu_affinity auto;

events {
    multi_accept on;
    worker_connections 1024;
}

http {
    charset utf-8;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;
    log_not_found off;
    types_hash_max_size 4096;
    client_max_body_size 16M;

    # MIME
    include mime.types;
    default_type application/octet-stream;

    # журналы
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    # загрузка дополнительных файлов конфигурации
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
Основные настройки
Процессы и соединения
Вы должны выбрать подходящее значение для
worker_processes
. Этот параметр определяет сколько одновременных соединений сможет принимать nginx и сколько процессоров он сможет при этом использовать. Как правило, это значение устанавливают равным количеству аппаратных потоков в системе. Однако, начиная с версий 1.3.8 и 1.2.5, в качестве значения
worker_processes
вы также можете задать
auto
, при этом nginx попытается автоматически подобрать оптимальное значение (
источник
).
Максимальное количество одновременных соединений, которое nginx сможет принимать, вычисляется как
max_clients = worker_processes * worker_connections
.
Запуск под другим пользователем
По умолчанию запускается мастер-процесс
nginx
от имени
root
, а он в свою очередь запускает рабочие процессы от имени пользователя
http
. Для запуска рабочих процессов от имени другого пользователя измените значение директивы
user
в файле
nginx.conf
:
/etc/nginx/nginx.conf
user
пользователь
[
группа
];
Если группа не указана, будет использоваться группа, совпадающая с указанным именем пользователя.
Совет
Можно запустить nginx без прав
root
через
systemd
. Смотрите
#Запуск без привилегий через systemd
.
Блоки server
Посредством добавления блоков
server
в файл настроек возможно обслуживать сразу несколько доменов одновременно. Эти блоки работают аналогично "VirtualHosts" в
Apache
.
Смотрите также
примеры в официальной документации
.
В этом примере сервер принимает запросы для двух доменов:
domainname1.dom
и
domainname2.dom
:
/etc/nginx/nginx.conf
...
server {
    listen 80;
    listen [::]:80;
    server_name domainname1.dom;
    root /usr/share/nginx/domainname1.dom/html;
    location / {
        index index.php index.html index.htm;
    }
}

server {
    listen 80;
    listen [::]:80;
    server_name domainname2.dom;
    root /usr/share/nginx/domainname2.dom/html;
    ...
}
Перезапустите
службу
nginx.service
, чтобы изменения вступили в силу.
Примечание
Убедитесь, что указанные домены существуют и указывают на IP-адрес устройства, на котором запущен nginx. Вы можете настроить DNS-сервер, например
BIND
или
dnsmasq
, или посмотрите варианты
разрешения имён в локальной сети
.
Управление блоками server
Для удобства можно поместить разные блоки
server
в разные файлы. Это также позволит включать и отключать отдельные сайты.
Создайте следующие каталоги:
# mkdir /etc/nginx/sites-available
# mkdir /etc/nginx/sites-enabled
Внутри каталога
sites-available
создайте файл, содержащий один или несколько блоков server:
/etc/nginx/sites-available/example.conf
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ...
}
В файле
nginx.conf
конце блока
http
добавьте строку
include sites-enabled/*;
:
/etc/nginx/nginx.conf
http {
    ...
    include sites-enabled/*;
}
Чтобы включить сайт, в каталоге
sites-enabled
создайте символическую ссылку на связанный с ним файл:
# ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/example.conf
А чтобы отключить сайт, удалите её:
# unlink /etc/nginx/sites-enabled/example.conf
Перезапустите
службу
nginx.service
или перезагрузите конфигурацию (reload), чтобы изменения вступили в силу.
TLS
openssl
предоставляет поддержку TLS/SSL и установлен по умолчанию на установленных Arch.
Совет
Перед тем как настраивать SSL, вы можете почитать документацию
ngx_http_ssl_module
Let's Encrypt
— это бесплатный, автоматизированный и открытый центр сертификации. Есть плагин для получения доверенных SSL-сертификатов прямо из командной строки и автоматической настройки.
На сайте Mozilla есть полезная
статья про TLS
, а также
инструмент
, помогающий составить безопасную конфигурацию.
Важно
Если вы планируете развернуть SSL/TLS, вы должны знать, что некоторые вариации и реализации
всё ещё
подвержены атакам
. За дополнительной информацией о текущих подверженных версиях этих реализаций SSL/TLS и как применить нужные настройки к nginx посетите
https://disablessl3.com/
и
https://weakdh.org/sysadmin.html
Создайте секретный ключ и самоподписанный сертификат. Это подходит для большинства случаев, в которых не требуется
CSR
:
# cd /etc/nginx/
# openssl req -new -x509 -nodes -newkey rsa:4096 -keyout nginx.key -out nginx.crt -days 1095
# chmod 400 nginx.key
# chmod 444 nginx.crt
Примечание
Опция -days является необязательной, а RSA keysize можно уменьшить до 2048 (по умолчанию).
Если же вам нужно создать
CSR
, то следуйте данным инструкциям по созданию ключа, вместо приведённых выше:
# openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out nginx.key
# chmod 400 nginx.key
# openssl req -new -sha256 -key nginx.key -out nginx.csr
# openssl x509 -req -days 1095 -in nginx.csr -signkey nginx.key -out nginx.crt
Примечание
Подробнее о доступных опциях
openssl
можно узнать в man-странице
openssl(1ssl)
или в
документации на официальном сайте
.
В качестве отправкой точки для создания конфигурации TLS в
/etc/nginx/nginx.conf
можно использовать
генератор настроек SSL от Mozilla
.
Перезапустите
службу
nginx
, чтобы изменения вступили в силу.
Пользовательские каталоги
Чтобы сделать Apache-подобные адреса вида
~пользователь
, указывающие на пользовательские каталоги
~/public_html
, используйте подобную конфигурацию. (Примечание: если вы планируете использовать PHP, то связанный с ним location должен стоять первым.)
/etc/nginx/nginx.conf
...
server {
    ...
    # Обработка файлов PHP в пользовательских каталогах, например http://example.com/~user/test.php
    location ~ ^/~(.+?)(/.+\.php)$ {
        alias          /home/$1/public_html$2;
        fastcgi_pass   unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi.conf;
    }

    # Пользовательские каталоги, например http://example.com/~user/
    location ~ ^/~(.+?)(/.*)?$ {
        alias     /home/$1/public_html$2;
        index     index.html index.htm;
        autoindex on;
    }
    ...
}
...
Подробнее о настройке PHP в
nginx
смотрите в разделе
#Реализация PHP
.
Перезапустите
службу
nginx.service
, чтобы изменения вступили в силу.
FastCGI
FastCGI или просто FCGI — это протокол, являющийся интерфейсом между веб-сервером и интерактивными программами. Это модифицированный CGI (
Common Gateway Interface
), главная цель которого — снизить накладные расходы, связанные со взаимодействием веб сервера и CGI программ, тем самым позволяя серверу обрабатывать большее количество запросов одновременно.
Технология FastCGI встроена в nginx для работы со многими внешними инструментами, например, Perl,
PHP
и
Python
.
Реализация PHP
В качестве FastCGI-сервера для PHP рекомендуется использовать
PHP-FPM
.
Установите
пакет
php-fpm
и проверьте корректность настроек
PHP
.
Основным конфигурационным файлом PHP-FPM является
/etc/php/php-fpm.conf
.
Включите
и
запустите
systemd
службу
php-fpm
.
Примечание
Если вы
запускаете nginx под другим пользователем
, убедитесь, что Unix-сокет PHP-FPM доступен этому пользователю, или используйте TCP-сокет.
Если вы запускаете nginx в изолированном окружении (к примеру, chroot находится в
/srv/nginx-jail
, веб-документы расположены в
/srv/nginx-jail/www
), то вы должны в
/etc/php/php-fpm.conf
добавить опции
chroot /srv/nginx-jail
и
listen = /srv/nginx-jail/run/php-fpm/php-fpm.sock
внутри секции пула (по умолчанию это
[www]
). Создайте каталог для файла сокета, если его нет. Более того, для модулей, которые динамически связаны с зависимостями, вам нужно будет скопировать эти зависимости в chroot (например, для php-imagick вам нужно будет скопировать в chroot библиотеки ImageMagick, но не сам imagick.so).
Настройка nginx
Внутри каждого блока
server
, который обслуживает веб-приложение PHP, должен находиться блок
location
[1]
, например:
/etc/nginx/sites-available/example.conf
server {
    root /usr/share/nginx/html;

    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        # 404
        try_files $fastcgi_script_name =404;

        # default fastcgi_params
        include fastcgi_params;

        # fastcgi settings
        fastcgi_pass			unix:/run/php-fpm/php-fpm.sock;
        fastcgi_index			index.php;
        fastcgi_buffers			8 16k;
        fastcgi_buffer_size		32k;

        # fastcgi params
        fastcgi_param DOCUMENT_ROOT	$realpath_root;
        fastcgi_param SCRIPT_FILENAME	$realpath_root$fastcgi_script_name;
        #fastcgi_param PHP_ADMIN_VALUE	"open_basedir=$base/:/usr/lib/php/:/tmp/";
    }
}
Если требуется обрабатывать другие расширения наряду с PHP (например
.html
и
.htm
):
location ~ [^/]\.(php|html|htm)(/|$) {
    ...
}
Все расширения, обрабатываемые в php-fpm должны быть также явно добавлены в
/etc/php/php-fpm.d/www.conf
:
security.limit_extensions = .php .html .htm
Примечание
Аргумент
fastcgi_pass
должен быть определен как TCP-сокет или сокет Unix выбранным FastCGI сервером в его конфигурационном файле.
По умолчанию
для
php-fpm
используется сокет
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
Вы можете использовать также общий TCP-сокет:
fastcgi_pass 127.0.0.1:9000;
Однако, доменные сокеты Unix должны работать быстрее.
Совет
Если несколько блоков
server
используют одну и ту же конфигурацию PHP-FPM, можно вынести общие настройки в отдельный файл для удобства, например
php_fastcgi.conf
:
/etc/nginx/php_fastcgi.conf
location ~ \.php$ {
    # 404
    try_files $fastcgi_script_name =404;

    # default fastcgi_params
    include fastcgi_params;

    # fastcgi settings
    ...
}
И затем подключать этот файл в тех блоках server, в которых нужна обработка PHP:
/etc/nginx/sites-available/example.conf
server {
    server_name example.com;
    ...

    include /etc/nginx/php_fastcgi.conf;
}
Проверка конфигурации
Перезапустите
службы
php-fpm
и
nginx
после изменения настроек, чтобы изменения вступили в силу.
Чтобы проверить работу FastCGI, создайте новый файл
.php
внутри каталога веб-документов, содержащий:
<?php
  phpinfo();
?>
При открытии файла в браузере должна отобразиться информационная страница с текущими настройками PHP.
Реализация CGI
Эта реализация нужна для CGI-приложений.
fcgiwrap
Установите
fcgiwrap
. Настроить его можно путём
редактирования юнита
fcgiwrap.socket
.
Включите
и
запустите
fcgiwrap.socket
.
Несколько рабочих потоков
Если вы хотите породить несколько рабочих потоков, вам рекомендуется использовать
multiwatch
AUR
, который умеет отслеживать упавшие подпроцессы и перезапускать их. Вам нужно использовать
spawn-fcgi
, чтобы создать доменный сокет Unix, так как multiwatch не может обрабатывать сокеты, созданные
systemd
, однако,
fcgiwrap
сама по себе не вызывает никаких проблем, если вызывается непосредственно из юнит-файла.
Сделайте
замещение файла юнита
fcgiwrap.service
(и юнита
fcgiwrap.socket
, если он есть), и отредактируйте строку
ExecStart
в соответствии с вашими нуждами. В примере показан юнит файл, который использует
multiwatch
AUR
. Убедитесь, что
fcgiwrap.socket
не включен и не запущен, потому что он будет конфликтовать с этим юнитом:
/etc/systemd/system/fcgiwrap.service
[Unit]
Description=Simple CGI Server
After=nss-user-lookup.target

[Service]
ExecStartPre=/bin/rm -f /run/fcgiwrap.socket
ExecStart=/usr/bin/spawn-fcgi -u http -g http -s /run/fcgiwrap.sock -n -- /usr/bin/multiwatch -f 10 -- /usr/sbin/fcgiwrap
ExecStartPost=/usr/bin/chmod 660 /run/fcgiwrap.sock
PrivateTmp=true
Restart=on-failure

[Install]
WantedBy=multi-user.target
Выберите подходящий
-f 10
, чтобы изменить количество порождаемых подпроцессов.
Важно
Строка
ExecStartPost
требуется из-за странного поведения, которое я наблюдаю при использовании опции
-M 660
для
spawn-fcgi
. Устанавливается неправильный режим. Может это баг?
Настройка nginx
В каталоге
/etc/nginx
скопируйте файл
fastcgi_params
в
fcgiwrap_params
. В файле
fcgiwrap_params
удалите строки, которые устанавливают
SCRIPT_NAME
и
DOCUMENT_ROOT
.
Внутри каждого блока
server
CGI-приложения должен находиться вложенный блок
location
:
location ~ \.cgi$ {
     include       fcgiwrap_params;
     fastcgi_param DOCUMENT_ROOT /srv/www/cgi-bin/;
     fastcgi_param SCRIPT_NAME   myscript.cgi;
     fastcgi_pass  unix:/run/fcgiwrap.sock;
}
Сокетом по умолчанию для
fcgiwrap
является
/run/fcgiwrap.sock
.
Вместо параметров
DOCUMENT_ROOT
и
SCRIPT_NAME
можно использовать более короткую альтернативу
fastcgi_param SCRIPT_FILENAME /srv/www/cgi-bin/myscript.cgi
. При её использовании не понадобится копировать
fastcgi_params
в
fcgiwrap_params
и удалять строки
DOCUMENT_ROOT
and
SCRIPT_NAME
.
Важно
Если используются SCRIPT_NAME и DOCUMENT_ROOT, fcgiwrap будет
отклонять
любые другие fastcgi_param, установленные в nginx. Вы должны использовать SCRIPT_FILENAME для того, чтобы другие параметры (например, PATH_INFO) могли быть установлены через конфигурацию Nginx.
Подробнее на GitHub.
Если вы продолжаете получать ошибку
502 - bad Gateway
, проверьте, передаёт ли ли ваше CGI-приложение mime-тип содержимого. Для html это должно быть
Content-type: text/html
.
Если вы получаете ошибки 403, убедитесь, что CGI-файл доступен для чтения и выполнения пользователю
http
и что каждая родительская папка доступна ему для чтения.
Установка в chroot
Установка nginx в
chroot
добавляет дополнительный уровень безопасности. Для максимальной безопасности chroot должен включать только файлы, необходимые для запуска сервера nginx, при этом все файлы должны иметь по возможности максимально ограниченные права доступа. Например, как можно больше файлов должно принадлежать пользователю root, а таким каталогам, как
/usr/bin
должен быть установлен запрет на чтение и запись.
Arch поставляется с пользователем
http
и группой по умолчанию, от имени которых запускается сервер. Измененный корневой каталог будет находиться в
/srv/http
.
Существует perl-скрипт для создания chroot-окружения, который доступен в
jail.pl gist
. Вы можете либо использовать его, либо следовать дальнейшим инструкциям из этой статьи. Скрипт требует прав суперпользователя для работы. Вам нужно будет раскомментировать строку, перед тем, как он сможет выполнять какие-либо изменения.
Создание необходимых устройств
Для nginx нужны
/dev/null
,
/dev/random
и
/dev/urandom
. Чтобы установить их в chroot мы создадим каталог
/dev
и добавим устройства с помощью
mknod
. Избегайте монтирования всех устройств в
/dev
: тогда, даже если chroot будет скомпрометирован, атакующий должен будет выбраться из chroot-окружения чтобы добраться до важных устройств, например
/dev/sda1
.
Совет
Убедитесь, что
/src/http
примонтирован без опции no-dev
Совет
Смотрите
mknod(1)
и
ls -l /dev/{null,random,urandom}
, чтобы лучше понять опции
mknod
.
# export JAIL=/srv/http
# mkdir $JAIL/dev
# mknod -m 0666 $JAIL/dev/null c 1 3
# mknod -m 0666 $JAIL/dev/random c 1 8
# mknod -m 0444 $JAIL/dev/urandom c 1 9
Создание необходимых каталогов
Для работы nginx требует определенный набор файлов. Перед тем, как их копировать, создайте для них соответствующие каталоги. Предполагается, что ваш корневой каталог веб-документов nginx находится в
/srv/http/www
.
# mkdir -p $JAIL/etc/nginx/logs
# mkdir -p $JAIL/usr/{lib,bin}
# mkdir -p $JAIL/usr/share/nginx
# mkdir -p $JAIL/var/{log,lib}/nginx
# mkdir -p $JAIL/www/cgi-bin
# mkdir -p $JAIL/{run,tmp}
# cd $JAIL; ln -s usr/lib lib
# cd $JAIL; ln -s usr/lib lib64
# cd $JAIL/usr; ln -s lib lib64
Затем смонтируйте
$JAIL/tmp
и
$JAIL/run
как tmpfs-ы. Размер должен быть ограничен, чтобы быть уверенным, что атакующий не сможет занять всю доступную RAM.
# mount -t tmpfs none $JAIL/run -o 'noexec,size=1M'
# mount -t tmpfs none $JAIL/tmp -o 'noexec,size=100M'
Для того, чтобы монтирование выполнялось автоматически при загрузке системы, добавьте следующие записи в
/etc/fstab
:
/etc/fstab
tmpfs   /srv/http/run   tmpfs   rw,noexec,relatime,size=1024k   0       0
 tmpfs   /srv/http/tmp   tmpfs   rw,noexec,relatime,size=102400k 0       0
Заполнение chroot
Сначала скопируйте простые файлы.
# cp -r /usr/share/nginx/* $JAIL/usr/share/nginx
# cp -r /usr/share/nginx/html/* $JAIL/www
# cp /usr/bin/nginx $JAIL/usr/bin/
# cp -r /var/lib/nginx $JAIL/var/lib/nginx
Теперь скопируйте нужные библиотеки. Используйте
ldd
, чтобы отобразить их и скопируйте все файлы в правильное место. Копирование предпочтительнее, чем создание жестких ссылок, потому, что даже если атакующий получит права записи в файлы, они не смогут уничтожить или изменить системные файлы вне chroot-окружения.
$ ldd /usr/bin/nginx
linux-vdso.so.1 (0x00007fffc41fe000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f57ec3e8000)
libcrypt.so.1 => /usr/lib/libcrypt.so.1 (0x00007f57ec1b1000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f57ebead000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f57ebbaf000)
libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f57eb94c000)
libssl.so.1.0.0 => /usr/lib/libssl.so.1.0.0 (0x00007f57eb6e0000)
libcrypto.so.1.0.0 => /usr/lib/libcrypto.so.1.0.0 (0x00007f57eb2d6000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f57eb0d2000)
libz.so.1 => /usr/lib/libz.so.1 (0x00007f57eaebc000)
libGeoIP.so.1 => /usr/lib/libGeoIP.so.1 (0x00007f57eac8d000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f57eaa77000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f57ea6ca000)
/lib64/ld-linux-x86-64.so.2 (0x00007f57ec604000)
Для файлов, находящихся в
/usr/lib
, вы можете воспользоваться следующей командой:
# cp $(ldd /usr/bin/nginx | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') $JAIL/usr/lib
А для
ld-linux-x86-64.so
— следующей командой:
# cp /lib64/ld-linux-x86-64.so.2 $JAIL/lib
Примечание
Не пытайтесь скопировать
linux-vdso.so
— это не настоящая библиотека и ее не существует в
/usr/lib
.
Копируйте другие необходимые библиотеки и системные файлы.
# cp /usr/lib/libnss_* $JAIL/usr/lib
# cp -rfvL /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf,nginx} $JAIL/etc
Создайте файлы пользователей и групп в chroot-окружении. Таким образом, в chroot-окружении будут доступны только указанные пользователи, и никакая информация о пользователях из основной системы не будет доступна атакующему, получившему доступ в chroot-окружение.
$JAIL/etc/group
http:x:33:
nobody:x:99:
$JAIL/etc/passwd
http:x:33:33:http:/:/bin/false
nobody:x:99:99:nobody:/:/bin/false
$JAIL/etc/shadow
http:x:14871::::::
nobody:x:14871::::::
$JAIL/etc/gshadow
http:::
nobody:::
# touch $JAIL/etc/shells
# touch $JAIL/run/nginx.pid
Наконец, сделайте права доступа максимально ограниченными. Как можно больше должно принадлежать суперпользователю и быть закрытым для записи.
# chown -R root:root $JAIL/

# chown -R http:http $JAIL/www
# chown -R http:http $JAIL/etc/nginx
# chown -R http:http $JAIL/var/{log,lib}/nginx
# chown http:http $JAIL/run/nginx.pid

# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod -rw
# find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod +x
# find $JAIL/etc -gid 0 -uid 0 -type f -print | xargs chmod -x
# find $JAIL/usr/bin -type f -print | xargs chmod ug+rx
# find $JAIL/ -group http -user http -print | xargs chmod o-rwx
# chmod +rw $JAIL/tmp
# chmod +rw $JAIL/run
Если ваш сервер будет принимать входящие соединения на 80 порту (или любому другому порту в диапазоне [1-1023]), дайте исполняемому файлу внутри chroot права на использование этих портов без прав суперпользователя.
# setcap 'cap_net_bind_service=+ep' $JAIL/usr/bin/nginx
Отредактируйте nginx.service для запуска chroot
Сделайте
замещение файла юнита
nginx.service
— тогда обновление nginx не изменит ваш файл
.service
.
Юнит systemd должен быть настроен так, чтобы запускать nginx в chroot от имени пользователя http и хранить pid-файл в chroot.
Примечание
Я не уверен, нужно ли хранить pid-файл в chroot.
/etc/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target

[Service]
Type=forking
PIDFile=/srv/http/run/nginx.pid
ExecStartPre=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -t -q -g 'pid /run/nginx.pid; daemon on; master_process on;'
ExecStart=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;'
ExecReload=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;' -s reload
ExecStop=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid;' -s quit

[Install]
WantedBy=multi-user.target
Примечание
Обновление nginx с помощью pacman не обновит установленную в chroot копию. Вы должны вручную выполнять обновления, повторяя указанные выше шаги по переносу файлов. Не забудьте также обновить библиотеки, которые использует nginx.
Теперь вы можете спокойно удалить nginx, установленный вне chroot.
# pacman -Rsc nginx
Если вы не удалили nginx, установленный вне chroot, проверьте, что работающий процесс nginx — это действительно именно тот, что в находится chroot. Для этого посмотрите, куда указывает символическая ссылка
/proc/
PID
/root
: она должна указывать на
/srv/http
, а не на
/
.
# ps -C nginx | awk '{print $1}' | sed 1d | while read -r PID; do ls -l /proc/$PID/root; done
Советы и рекомендации
Запуск без привилегий через systemd
Создайте
drop-in файл
для службы
nginx.service
и пропишите в нём секцию
[Service]
с опцими
User
и (опционально)
Group
, чтобы запустить службу от имени указанного вами непривилегированного пользователя:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
User=
пользователь
Group=
группа
Также можно запретить повышение привилегий:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
NoNewPrivileges=yes
Совет
Подробнее о повышающих безопасность опциях можно почитать в
systemd.exec(5)
.
После этого нужно убедиться, что
пользователь
имеет доступ ко всем необходимым ресурсам. Следуйте инструкциям, описанным в следующих разделах, и затем
запустите
nginx.
Совет
Аналогичные настройки можно применить и для
сервера FastCGI
.
Порт
По умолчанию Linux запрещает не-root процессам слушать порты ниже 1024. Можно использовать порт выше 1024:
/etc/nginx/nginx.conf
server {
        listen 8080;
}
Совет
Если вы хотите, чтобы nginx всё равно был доступен на порту 80 или 443, можно настроить
межсетевой экран
для перенаправления запросов с порта 80 или 444 на порт, который использует nginx.
Или можно выдать процессу nginx привилегию CAP_NET_BIND_SERVICE, которая позволит ему использовать порты ниже 1024:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
CapabilityBoundingSet=
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=
AmbientCapabilities=CAP_NET_BIND_SERVICE
Или можно использовать активацию сокетов systemd. В этом случае systemd будет прослушивать порты и, когда будет установлено соединение, запустит nginx, передав сокет в качестве дескриптора файла. Это означает, что процессу nginx не нужны особые привилегии, так как сокет уже существует на момент запуска. Этот подход опирается на использование внутренней переменной окружения, которую nginx использует для передачи сокетов
[2]
, и поэтому официально не поддерживается. Вместо установки
CapabilityBoundingSet
и
AmbientCapabilities
переопределите переменную окружения
NGINX
, чтобы сообщить процессу nginx, какие файловые дескрипторы будут передаваться сокетам:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
Environment=NGINX=3:4;
На каждый прослушиваемый порт будет приходиться один сокет, начиная с файлового дескриптора 3, поэтому в данном примере мы говорим nginx ожидать два сокета. Теперь создайте юнит
nginx.socket
, указав, какие порты прослушивать:
/etc/systemd/system/nginx.socket
[Socket]
ListenStream=0.0.0.0:80
ListenStream=0.0.0.0:443
After=network.target
Requires=network.target

[Install]
WantedBy=sockets.target
Сокеты будут передаваться в порядке, определённом в этом юните, поэтому порт 80 будет файловым дескриптором 3, а порт 443 — файловым дескриптором 4. Если вы ранее включали или запускали службу
nginx.service
, вам нужно остановить её и включить вместо неё
nginx.socket
. При запуске системы nginx не будет запущен, но запустится, когда вы зайдете на сайт в браузере. Благодаря этому можно дополнительно защитить службу; например, во многих случаях вы можете установить
PrivateNetwork=True
в файле службы, блокируя nginx от внешней сети, поскольку сокета, созданного systemd, достаточно для обслуживания веб-сайта. Обратите внимание, что при этом в журналы службы nginx будет выведено предупреждение:
2020/08/29 19:33:20 [notice] 254#254: using inherited sockets from "3:4;"
PID-файл
По умолчанию
nginx
использует
/run/nginx.pid
. Нужно будет создать каталог, в котором
пользователь
будет иметь право записи, и перенастроить запись PID-файла туда. Например, можно использовать
systemd-tmpfiles
:
/etc/tmpfiles.d/nginx.conf
d /run/nginx 0775 root
группа
- -
Примените изменения:
# systemd-tmpfiles --create
Отредактируйте
параметры службы, связанные с PID-файлом:
/etc/systemd/system/nginx.service.d/user.conf
[Service]
...
PIDFile=/run/nginx/nginx.pid
ExecStart=
ExecStart=/usr/bin/nginx -g 'pid /run/nginx/nginx.pid; error_log stderr;'
ExecReload=
ExecReload=/usr/bin/nginx -s reload -g 'pid /run/nginx/nginx.pid;'
/var/lib/nginx/*
Некоторые каталоги в каталоге
/var/lib/nginx
должны быть инициализированы путём запуска nginx от имени
root
. Для этого не обязательно запускать весь сервер, nginx сделает это при
проверке конфигурации
. Так что просто запустите её — и готово.
Права каталогов и файлов журналов
После запуска проверки конфигурации будет создан журнал, принадлежащий
root
. Удалите журналы в
/var/log/nginx
.
Пользователю, от имени которого будет работать служба, nginx нужно выдать разрешение на запись в
/var/log/nginx
. Для этого может понадобиться
изменить права
и/или владельца каталога.
Альтернативный скрипт для systemd
В systemd есть встроенная возможность запуска через chroot.
[3]
. Для примера используем такие настройки
пользователя, группы
и pid:
/etc/nginx/nginx.conf
user http;
pid /run/nginx.pid;
Абсолютный путь к файлу настроек будет
/srv/http/etc/nginx/nginx.conf
.
/etc/systemd/system/nginx.service
[Unit]
Description=nginx (Chroot)
After=network.target

[Service]
Type=forking
PIDFile=/srv/http/run/nginx.pid
RootDirectory=/srv/http
ExecStartPre=/usr/bin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/bin/nginx -c /etc/nginx/nginx.conf
ExecReload=/usr/bin/nginx -c /etc/nginx/nginx.conf -s reload
ExecStop=/usr/bin/nginx -c /etc/nginx/nginx.conf -s stop

[Install]
WantedBy=multi-user.target
Указывать стандартный путь к файлу настроек необязательно, nginx по умолчанию использует
-c /etc/nginx/nginx.conf
, но, возможно, явное прописывание является хорошей идеей.
Также можно запускать
только
ExecStart
внутри chroot с параметром
RootDirectoryStartOnly
заданным как
yes
(смотрите
systemd.service(5)
) или запустить его до того, как точка монтирования станет эффективной или будет доступен путь systemd (смотрите
systemd.path(5)
).
/etc/systemd/system/nginx.path
[Unit]
Description=nginx (Chroot) path
[Path]
PathExists=/srv/http/site/Public_html
[Install]
WantedBy=default.target
Включите
созданный юнит
nginx.path
и в юните
nginx.service
измените строку
WantedBy=default.target
на
WantedBy=nginx.path
.
Параметр
PIDFile
в файле юнита позволяет systemd следить за процессом (требуется абсолютный путь). Если это нежелательно, вы можете изменить тип на oneshot и удалить упоминание pid-файла из файла юнита.
Nginx beautifier
nginxbeautifier
AUR
— это инструмент командной строки, используемый для улучшения и форматирования конфигурационных файлов nginx.
Более удобное управление заголовками
Nginx имеет довольно неинтуитивную систему управления HTTP-заголовками: они могут быть определены только в одном контексте, любые другие заголовки игнорируются. Чтобы исправить это, можно установить модуль
headers-more-nginx
.
Установите
пакет
nginx-mod-headers-more
. Модуль будет установлен в каталог
/usr/lib/nginx/modules
.
Чтобы загрузить модуль, добавьте следующее в начало основного конфигурационного файла nginx.
/etc/nginx/nginx.conf
load_module "/usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so";
...
Решение проблем
Валидация конфигурации
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Ошибка: Страница, которую вы ищете, временно недоступна. Пожалуйста, попробуйте позже. (502 Bad Gateway)
Это из-за того, что сервер FastCGI не запущен или используемый сокет имеет неправильные права доступа.
Попробуйте
этот ответ
, чтобы исправить 502 ошибку.
В Arch Linux, файлом настройки, упомянутом по ссылке выше, является
/etc/php/php-fpm.conf
.
Ошибка: No input file specified
1. Убедитесь, что переменная
open_basedir
в
/etc/php/php.ini
содержит путь, который соответствует аргументу
root
в
nginx.conf
(обычно
/usr/share/nginx/
). Если в качестве FastCGI-сервера используется
PHP-FPM
, можно попробовать добавить
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";
в тот блок
location
, который используется для обработки php-файлов.
2. Другой причиной может быть то, что задан неправильный аргумент
root
в секции
location ~ \.php$
в
nginx.conf
. Убедитесь, что
root
указывает на ту же директорию, что и в
location /
на том же сервере. Либо вы можете просто задать параметр root глобально, не переопределяя его в каких-либо location секциях.
3. Проверьте права доступа: например, пользователь/группа
http
, биты разрешений
755
для каталогов и
644
для файлов. Имейте в виду, что все родительские каталоги тоже должны иметь корректные права доступа. Как массово изменить права всего дерева каталогов, описано в разделе
Разрешения и атрибуты файлов#Массовое изменение разрешений
.
4. Возможно, у вас не установлена переменная
SCRIPT_FILENAME
, содержащая полный путь до ваших скриптов. Если конфигурация nginx (
fastcgi_param SCRIPT_FILENAME
) правильная, то эта ошибка означает, что php не смог загрузить запрашиваемый скрипт. Часто это просто оказывается ошибкой прав доступа, и вы можете запустить php-cgi с правами root:
# spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/bin/php-cgi
или вам следует создать группу и пользователя для запуска php-cgi:
# groupadd www
# useradd -g www www
# chmod +w /srv/www/nginx/html
# chown -R www:www /srv/www/nginx/html
# spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/bin/php-cgi
5. Если вы используете chroot, убедитесь, что опция
chroot
в файле
/etc/php-fpm/php-fpm.d/www.conf
имеет корректное значение.
Warning: Could not build optimal types_hash
Если при запуске
nginx.service
в журнале появляется такое сообщение:
[warn] 18872#18872: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
то попробуйте увеличить значения этих параметров в блоке
http
[4]
[5]
:
/etc/nginx/nginx.conf
http {
    types_hash_max_size 4096;
    server_names_hash_bucket_size 128;
    ...
}
Cannot assign requested address
Полный текст ошибки в
статусе юнита
nginx.service
:
[emerg] 460#460: bind() to A.B.C.D:443 failed (99: Cannot assign requested address)
Даже если файл юнита nginx настроен на запуск после
network.target
с помощью systemd, nginx может попытаться прослушивать адрес, который настроен, но ещё не добавлен ни к одному интерфейсу. Убедиться, что проблема именно в этом, можно, попытавшись
запустить
nginx вручную (тем самым показав, что IP-адрес настроен правильно). Настройка nginx на прослушивание всех адресов решит эту проблему. Если же в вашем случае обязательно требуется прослушивание конкретного адреса, одним из возможных решений является перенастройка systemd.
Чтобы запустить nginx только после того, как все настроенные сетевые устройства будут запущены и получат IP-адреса, добавьте
network-online.target
к строке
After=
в файле
nginx.service
и
запустите/включите
systemd-networkd-wait-online.service
.
Смотрите также
Использование WebDAV с nginx
nginx configuration pitfalls
Very good in-depth 2014 look at nginx security and Reverse Proxying
Installing LEMP (nginx, PHP, MySQL with MariaDB engine and PhpMyAdmin) in Arch Linux
Certbot (Русский)#Nginx