Nginx. Установка и настройка. Часть 1 из 3
Nginx — это веб-сервер с открытым исходным кодом, созданный работать под высокой нагрузкой, чаще всего используемый для отдачи статического контента. Он также может выполнять другие важные функции, такие как балансировка нагрузки, кеширование HTTP и использование в качестве обратного прокси.
Установка nginx-core
Обновляем списки пакетов из репозиториев и устанавливаем
$ sudo apt update $ sudo apt install nginx
После установки добавляем службу в автозагрузку
$ sudo systemctl enable nginx.service
Проверяем статус работы веб-сервера
$ sudo systemctl status nginx.service
Проверяем наличие службы в автозагрузке
$ sudo systemctl is-enabled nginx.service
Для работы с установленным веб-сервером пригодятся базовые команды управления
Функция | Команда |
---|---|
Запуск | sudo systemctl start nginx |
Остановка | sudo systemctl stop nginx |
Перезапуск (последовательно stop и start) | sudo systemctl restart nginx |
Перезагрузка (перечитать файлы конфигурации) | sudo systemctl reload nginx |
Проверка состояния | sudo systemctl status nginx |
Тест конфигурации | sudo nginx -t |
Варианты установки
Для установки доступны пакеты nginx-light
, nginx-core
(наш вариант), nginx-full
и nginx-extra
.
Пакет nginx-light
— это облегченная версия nginx, с минимальным набором модулей. Включает в себя только базовые возможности HTTP-сервера, недоступны многие модули, например модуль перезаписи URL ngx_http_rewrite_module
или модуль сжатия ngx_http_gzip_module
. Может быть полезен в контейнерных средах, таких как Docker, где минимализм является ключевым моментом. Это также неплохой выбор для основных задач балансировки нагрузки.
Пакет nginx-core
представляет собой минимальную, но полную установку веб-сервера nginx. Это отправная точка, если нужен функциональный сервер без посторонних модулей. Включает в себя базовые функции HTTP, такие как поддержка HTTP/2, поддержка Secure Sockets Layer (SSL) и основные функции обратного прокси. Хороший выбор для простых веб-приложений, статических веб-сайтов или конфигураций обратного прокси-сервера, где не нужны дополнительные функции.
Пакет nginx-full
— более многофункциональная версия nginx, предназначенная для более сложных и ресурсоемких задач. Включает в себя почти все модули с исходным исходным кодом nginx, такие как возможности проксирования, дополнительные модули HTTP, поддержку WebSocket и многое другое. Подходит для сложных веб-приложений, которым требуются различные функции, такие как SSL, проксирование и расширенные возможности кэширования. Также хорошо подходит, если нужен веб-сервер общего назначения, не слишком беспокоясь о том, какие модули могут понадобиться позже.
Пакет nginx-extras
— наиболее многофункциональный, ориентирован на узкоспециализированные развертывания, требующие широкого набора функциональных возможностей. Включает в себя все модули, имеющиеся в nginx-full
, а также дополнительные сторонние модули. Однако следует отметить, что nginx-extras
не включает в себя все возможные модули. Для тех нишевых потребностей, которые не удовлетворяются доступными пакетами, может потребоваться компиляция nginx из исходного кода.
Файлы конфигурации
Все файлы конфигурации Nginx расположены в директории /etc/nginx
$ ls -la /etc/nginx/ total 72 drwxr-xr-x 8 root root 4096 дек 11 15:43 . drwxr-xr-x 99 root root 4096 дек 11 15:44 .. drwxr-xr-x 2 root root 4096 мая 30 2023 conf.d -rw-r--r-- 1 root root 1125 мая 30 2023 fastcgi.conf -rw-r--r-- 1 root root 1055 мая 30 2023 fastcgi_params -rw-r--r-- 1 root root 2837 мая 30 2023 koi-utf -rw-r--r-- 1 root root 2223 мая 30 2023 koi-win -rw-r--r-- 1 root root 3957 мая 30 2023 mime.types drwxr-xr-x 2 root root 4096 мая 30 2023 modules-available drwxr-xr-x 2 root root 4096 дек 11 15:44 modules-enabled -rw-r--r-- 1 root root 1447 мая 30 2023 nginx.conf -rw-r--r-- 1 root root 180 мая 30 2023 proxy_params -rw-r--r-- 1 root root 636 мая 30 2023 scgi_params drwxr-xr-x 2 root root 4096 дек 11 15:43 sites-available drwxr-xr-x 2 root root 4096 дек 11 15:43 sites-enabled drwxr-xr-x 2 root root 4096 дек 11 15:43 snippets -rw-r--r-- 1 root root 664 мая 30 2023 uwsgi_params -rw-r--r-- 1 root root 3071 мая 30 2023 win-utf
Здесь много чего, но нам в первую очередь интересны следующие файлы и директории
nginx.conf
— главный конфигурационный файл nginx.conf.d
— дополнительные конфигурационные файлы nginx.sites-available
— в этой директории хранятся файлы виртуальных хостов. Nginx не использует файлы из этой директории, если ссылки на них нет в директорииsites-enabled
.sites-enabled
— директория, в которой хранятся активированные виртуальные хосты. Обычно это делается путём создания ссылки на файл конфигурации хоста из директорииsites-available
.modules-available
,modules-enabled
— эти директории содержат, соответственно, доступные и активные модули.
Главный файл конфигурации
Давайте посмотрим содержимое главного файла конфигурации /etc/nginx/nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 1024; # multi_accept on; } http { # базовые настройки sendfile on; tcp_nopush on; types_hash_max_size 2048; keepalive_timeout 40; # кодировка по умолчанию charset UTF-8; # настройки кэширования open_file_cache max=10000 inactive=30s; # настройка mime-types include /etc/nginx/mime.types; default_type application/octet-stream; # настройки SSL ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; # логирование access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # разрешить сжатие gzip on; # виртуальные хосты include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Файл конфигурации состоит из секций и директив
секция main ├── директивы main ├── секция events │ └── директивы events ├── секция http │ ├── директивы http │ ├── секция server │ │ ├── директивы server │ │ └── секция location │ └── секция server │ ├── директивы server │ └── секция location └── секция mail ├── директивы mail ├── секция server │ └── директивы server └── секция server └── директивы server
Модульная структура
Nginx является модульным приложением. Это значит, что каждая из директив в конфиге связана с определенным модулем. Так, к примеру, модуль ngx_core_module
отвечает за основную логику — то есть определяет как раз те директивы, без которых сервер просто не запустится (например user
).
Модули существуют двух видов — статические и динамические. Статические — это модули, которые входят в состав nginx в результате сборки из исходников с добавлением кода необходимого модуля. Динамические — это модули, которые можно подключать к nginx без сборки самого nginx, хотя сам модуль должен быть собран как внешняя библиотека. Однако nginx не позволяет подключить динамический модуль, если в ходе сборки nginx не была указана в параметрах сборки поддержка этого модуля. Иначе говоря — если требуется конкретный модуль, то в любом случае необходимо собирать nginx из исходных файлов. А вот как — уже на ваше усмотрение и исходя из возможностей работы модуля (не все модули умеют работать как динамические).
В директории /etc/nginx/modules-enabled
мы найдем несколько символических ссылок на файлы конфигурации. В этих файлах конфигурации с помощью директивы load_module
загружаются динамические модули.
$ ls -la /etc/nginx/modules-enabled lrwxrwxrwx 1 root root 55 дек 11 15:44 50-mod-http-geoip2.conf -> /usr/share/nginx/modules-available/mod-http-geoip2.conf lrwxrwxrwx 1 root root 61 дек 11 15:44 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf lrwxrwxrwx 1 root root 60 дек 11 15:44 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf lrwxrwxrwx 1 root root 48 дек 11 15:44 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf lrwxrwxrwx 1 root root 50 дек 11 15:44 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf lrwxrwxrwx 1 root root 57 дек 11 15:44 70-mod-stream-geoip2.conf -> /usr/share/nginx/modules-available/mod-stream-geoip2.conf
$ cat /etc/nginx/modules-enabled/50-mod-http-image-filter.conf load_module modules/ngx_http_image_filter_module.so;
Модуль ngx_http_image_filter_module
позволяет использовать в файле конфигурации директиву image_filter
, с помощью которой можно изменять размер, поворачивать и обрезать изображения. Модуль ngx_http_empty_gif_module
позволяет использовать директиву empty_gif
, которая выдает прозрачное gif-изображение размером 1x1 пиксель.
location /img/ { proxy_pass http://backend; image_filter resize 150 100; image_filter rotate 90; error_page 415 = /empty; } location = /empty { empty_gif; }
Директивы конфигурации
Существует два вида директив — простые и блочные. Простая директива состоит из имени и параметров, разделённых пробелами, и в конце строки ставится точкой с запятой. Блочная директива (секция) состоит из нескольких директив, помещённых внутри фигурных скобок.
user
— пользователь, от имени которого работает nginx, обычноwww-data
worker_processes
– количество процессов сервера, значение выставляется равным количеству ядер процессора,auto
— nginx определит автоматическиpid
— файл, внутри которого хранится идентификатор запущенного главного процесса (PID)include
— подключаемый файл или файлы конфигурацииevents
— секция директив, определяющих работу с сетевыми соединениямиworker_connections
— по умолчанию 512. Устанавливает максимальное количество соединений одного рабочего процесса, то есть nginx будет обрабатыватьworker_processes * worker_connections
, остальные запросы ставить в очередь. Следует выбирать значения от 1024 до 4096 — зависит от производительности процессора.multi_accept
— по умолчаниюoff
. Если включен, позволяет принимать максимально возможное количество соединений. Если отключен, nginx решает, какой дочерний процесс будет обрабатывать запрос. Поскольку nginx очень эффективен в этом — значениеoff
подойдет в большинстве случаев.http
— секция директив http-сервераsendfile
— позволяет использовать более совершенный системный вызов, который обеспечивает прямую передачу файла, то есть без системных вызовов read и writetcp_nopush
— позволяет передавать заголовок ответа и начало файла в одном пакете, при использовании значенияon
— повышает производительность.types_hash_max_size
— регламентирует максимальный размер хэш таблиц типов. Чтобы быстро обрабатывать статические наборы данных — nginx использует хеш-таблицы. При запуске nginx сам подбирает размеры хеш-таблиц — но не больше указанного значения. Чем больше значение, тем больше памяти будет использовано, но частота конфликтов хеш-ключей уменьшится, а скорость извлечения будет выше. Если в логах появляются сообщения «could not build optimal types_hash» — нужно увеличить значение.keepalive_timeout
— по умолчанию 75. Отвечает за максимальное время поддержания keepalive-соединения, в случае, если клиент по нему ничего не запрашивает. Для современных условий, стоит выставить от 30 до 50.open_file_cache
— по умолчанию отключена. При включении nginx будет хранить в кэше дескрипторы открытых файлов, информацию об их размерах и времени модификации, информацию о существовании каталогов, информацию об ошибках поиска файла — «файл не найден», «нет прав на чтение».default_type
— указывает тип MIME ответа по умолчаниюssl_protocols
— включает указанные SSL протоколыaccess_log
— задает путь к файлу лога доступа и формат записей; при выставлении значения вoff
, запись в журнал доступа будет отключенаerror_log
— путь к файлу лога регистрации ошибок и уровень детализацииgzip
— включает или отключает сжатие
Логирование запросов и ошибок
Директива log_format
позволяет описать, что будет содержаться в журнале запросов. По умолчанию используется формат combined
.
log_format combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"';
Все, что начинается с доллара — это переменные, большинство из которых доступно по умолчанию. Однако, возможно задать новые переменные, которые также можно использовать при описании формата логов доступа.
Лог ошибок, как нетрудно догадаться, используется для записи ошибок работы nginx. В отличие от access_log
, в директиву error_log
передается не формат логов, а минимальный уровень детализации. По умолчанию используется уровень error
, но существуют и другие уровни, вплоть до debug
.
error_log /var/log/nginx/error.log debug;
Для повышения производительности при записи логов доступа можно использовать буфер перед записью на диск. Есть два тригера для записи из буфера в файл, которые можно использовать одновременно
- если буфер заполнен и больше не вмещается
- если данные в буфере старше, чем указано
Размер буфера и время сброса на диск задаются с помощью директив buffer
и flush
access_log /var/log/nginx/access.log combined buffer=256k flush=10s; error_log /var/log/nginx/error.log warn;
Виртуальные хосты
Директива server
определяет так называемый виртуальный хост, что позволяет на одном ip-адресе обрабатывать несколько доменов. К какому домену идет обращение — nginx определяет по http-заголовку Host
. В общем случае, каждый server
может быть запущен на конкретном ip-адресе и порту, либо обрабатывать конкретное (или несколько конкретных) доменных имен.
В файле конфигурации /etc/nginx/nginx.conf
есть две директивы include
http { # виртуальные хосты include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Давайте посмотрим содержимое директории /etc/nginx/sites-enabled
$ ls -la /etc/nginx/sites-enabled total 8 drwxr-xr-x 2 root root 4096 дек 11 15:43 . drwxr-xr-x 8 root root 4096 дек 11 17:21 .. lrwxrwxrwx 1 root root 34 дек 11 15:43 default -> /etc/nginx/sites-available/default
Давайте посмотрим содержимое файла /etc/nginx/sites-enabled/default
# Default server configuration server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; server_name _; location / { # First attempt to serve request as file, then as # directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } }
Это конфигурация так называемого сервера по умолчанию. Если пришел http-запрос, но ни один из виртуальных хостов его не обработал — тогда запрос будет обработан сервером по умолчанию. Сервер по умолчанию можно задать явно с помощью параметра default_server
в директиве listen
. В противном случае сервером по умолчанию будет считаться первый сервер в списке.
server { listen 80; # сервер по умолчанию для 80-го порта server_name example.org www.example.org; # ...прочие директивы конфигурации... } server { listen 80; server_name example.net www.example.net; # ...прочие директивы конфигурации... } server { listen 80; server_name example.com www.example.com; # ...прочие директивы конфигурации... }
Сервер по умолчанию является свойством слушающего порта, поэтому у разных портов могут быть определены разные серверы по умолчанию
server { listen 80; listen 8080 default_server; server_name example.org www.example.org; # ...прочие директивы конфигурации... } server { listen 80 default_server; listen 8080; server_name example.com www.example.com; # ...прочие директивы конфигурации... }
Директивы listen и server_name
Директива listen
позволяет определить, где слушает конкретный сервер — какой порт, какой ip-адрес или вообще unix-сокет. Кроме этого, он позволяет установить большое количество опций по работе сервера, например, использовать ли SSL, по какому протоколу работать и так далее.
Директива server_name
позволяет указать, какие доменные имена будет обрабатывать конкретный сервер. Можно указать несколько доменных имен через пробел. Кроме того, допускается использовать *
— например, чтобы обрабатывать все субдомены *.example.com
server { listen 443 http2 ssl; server_name example.com www.example.com; # ...прочие директивы конфигурации... }
Когда приходит http-запрос — nginx вначале сопоставляет ip-адрес и порт запроса с директивами listen
в секциях server
. Затем сопоставляет значение поле Host
заголовка запроса с директивами server_name
в секциях server
, которые соответствуют ip-адресу и порту. Если имя сервера не найдено, запрос будет обработан сервером по умолчанию.
Давайте рассмотрим вот такой пример конфигурации
server { listen 192.168.1.1:80; server_name example.org www.example.org; # ...прочие директивы конфигурации... } server { listen 192.168.1.1:80 default_server; server_name example.net www.example.net; # ...прочие директивы конфигурации... } server { listen 192.168.1.2:80 default_server; server_name example.com www.example.com; # ...прочие директивы конфигурации... }
Запрос www.example.com
, который пришел на 192.168.1.1:80
, будет обработан сервером по умолчанию (второй в списке), потому как имени www.example.com
нет в директиве server_name
первого сервера и нет в директиве server_name
второго сервера. Это значит, что запрос должен обработать сервер по умолчанию. Если бы не было параметра default_server
для второго сервера — запрос бы обработал первый сервер.
Если необходимо обрабатывать http-запросы без поля Host
в заголовке — нужно указать в качестве значения директивы server_name
пустую строку. Это можно сделать для уже существующей секции, так и создать новую секцию server
. Если это новая секция server
— то директиву server_name
с пустой строкой можно не указывать, это значение по умолчанию.
server { listen 80; server_name example.org www.example.org ""; # ...прочие директивы конфигурации... }
server { listen 80; server_name ""; # ...прочие директивы конфигурации... }
Если в запросе вместо имени сервера указан ip-адрес, то поле Host
заголовка запроса будет содержать ip-адрес, и запрос можно обработать, используя ip-адрес как имя сервера.
server { listen 80; server_name example.org www.example.org "" 192.168.1.1; # ...прочие директивы конфигурации... }
Если запросы без поля Host
в заголовке не должны обрабатываться, можно определить сервер, который будет их отклонять. В примере ниже возвращается специальный для nginx код 444
, который закрывает соединение.
server { listen 80; server_name ""; return 444; }
В примерах конфигурации серверов, обрабатывающих все запросы, встречается странное имя _
(подчеркивание). Оно не является каким-то особенным, это просто одно из множества некорректных доменных имён, которые никогда не пересекутся ни с одним из реальных имён.
server { listen 80 default_server; server_name _; return 444; }
Директивы location и root
Директивы location
служит для установки конфигурации в зависимости от URI-запроса. Директива root
задает начальную часть пути к файлам, которые будет отдавать nginx, в файловой системе сервера.
http { server { listen 80; server_name example.org; root /var/www/example.org; location /img { # ...прочие директивы конфигурации... } location /pdf { # ...прочие директивы конфигурации... } } }
Здесь все просто — nginx сравнивает строку, которая идет после директивы location
с URI http-запроса. Скажем, приходит http-запрос http://example.org/img/logo.png
, URI этого запроса — это /img/logo.png
. Сравнивается начальная часть URI /img/logo.png
со строкой /img
— здесь есть совпадение /img
с /img
. Это значит, что nginx будет искать в файловой системе файл /var/www/example.org/img/logo.png
— это root + /img/logo.png
.
Директива location
может быть представлена одним из трех вариантов
# поиск точного совпадения URI http-запроса со строкой string, высший приоритет location = string { # ...прочие директивы конфигурации... }
# поиск совпадения начала URI http-запроса со строкой string максимальной длины location [^~] string { # ...прочие директивы конфигурации... }
# поиск первого совпадения URI http-запроса с регулярным выражением regexp location ~[*] regexp { # ...прочие директивы конфигурации... }
Nginx ищет подходящий блок location
по следующему алгоритму
- Поиск точного совпадения URI http-запроса со строкой
location = string {...}
без использования регулярных выражений. Если совпадение найдено — поиск завершается. - Поиск совпадения начала URI http-запроса со строкой
location [^~] string {...}
без использования регулярных выражений. Идет поиск совпадения максимальной длины — это значит, что поиск не завершается после первого совпадения. Если совпадение максимальной длины имеет префикс^~
— поиск завершается. Если совпадение максимальной длины не имеет префикса —location
временно сохраняется. - Поиск совпадения URI http-запроса с шаблоном
location ~[*] regexp {...}
, в порядке их определения в файле конфигурации. Если совпадение найдено — поиск завершается. Обратите внимание, что поиск завершается после первого найденного совпадения. Звездочка*
означает поиск без учета регистра. - Возвращается временно сохраненный
location
из второго пункта.
Обратите внимание, что этот алгоритм не применим при наличии вложенных location
.
Примеры location и root
Давайте рассмотрим пример файла конфигурации и посмотрим, как nginx будет искать подходящую директиву location
. Для этого создадим файл конфигурации example.com
в директории /etc/nginx/sites-available
. И поставим символическую ссылку на него в директории /etc/nginx/sites-enabled
. Кроме того, нам нужна директория /var/www/example.com
и внутри нее — несколько директорий с файлами изображений.
$ sudo mkdir /var/www/example.com $ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com $ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Структура директорий внутри /var/www/example.com
[example.com] [111] [img] nginx.png [logo] nginx.png [222] [img] nginx.png [logo] nginx.png [333] [img] nginx.png [logo] nginx.png [444] [img] nginx.png [logo] nginx.png
Смысл этого в том, что файл nginx.png
всегда разный, на каждом есть текст, указывающий путь в файловой системе — так мы будем знать, какое правило сработало и какой файл nginx.png
нам отдает веб-сервер. Чтобы выполнять http-запросы, обращаясь к веб-серверу по имени домена example.com
— добавим запись в файл hosts
на том компе, с которого будем обращаться к веб-серверу.
Первый пример
Выполняем http-запрос http://example.com/img/logo/nginx.png
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com; root /var/www/example.com; location /img { root /var/www/example.com/111; } location /img/logo { root /var/www/example.com/222; } location ~ ^/img { root /var/www/example.com/333; } location ~ ^/img/logo { root /var/www/example.com/444; } }
$ sudo nano systemctl restart nginx.service
Nginx сначала ищет самое длинное совпадение — это будет второй блок location
. Поскольку самое длинное совпадение не имеет префикса ^~
— nginx переходит к поиску по регулярным выражениям. Причем, останавливается на первом совпадении — это третий блок. Чтобы сработал четвертый блок — его надо разместить перед третьим.
Второй пример
Выполняем http-запрос http://example.com/img/logo/nginx.png
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com; root /var/www/example.com; location /img { root /var/www/example.com/111; } location ^~ /img/logo { root /var/www/example.com/222; } location ~ ^/img { root /var/www/example.com/333; } location ~ ^/img/logo { root /var/www/example.com/444; } }
$ sudo nano systemctl restart nginx.service
Nginx сначала ищет самое длинное совпадение — это будет второй блок location
. Поскольку есть префикс ^~
— поиск завершается.
Третий пример
Выполняем http-запрос http://example.com/img/nginx.png
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com; root /var/www/example.com; location /img { root /var/www/example.com/111; } location /img/logo { root /var/www/example.com/222; } location ~ ^/i { root /var/www/example.com/333; } location ~ ^/img { root /var/www/example.com/444; } }
$ sudo nano systemctl restart nginx.service
Nginx сначала ищет самое длинное совпадение — это будет первый блок location
. Поскольку самое длинное совпадение не имеет префикса ^~
— nginx переходит к поиску по регулярным выражениям. Причем, останавливается на первом совпадении — это третий блок. Чтобы сработал четвертый блок — его надо разместить перед третьим.
Четвертый пример
Выполняем http-запрос http://example.com/logo/nginx.png
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com; root /var/www/example.com; location /logo { root /var/www/example.com/111/img; } location /img/logo { root /var/www/example.com/222; } location ~ ^/lo { root /var/www/example.com/333/img; } location ~ ^/logo { root /var/www/example.com/444/img; } }
$ sudo nano systemctl restart nginx.service
Nginx сначала ищет самое длинное совпадение — это будет первый блок location
. Поскольку самое длинное совпадение не имеет префикса ^~
— nginx переходит к поиску по регулярным выражениям. Причем, останавливается на первом совпадении — это третий блок. Чтобы сработал четвертый блок — его надо разместить перед третьим.
location
сработал — через текст на всех изображениях nginx.png
. Все это можно сделать намного проще — если внутри каждого блока location
разместить директиву add_header
. Тогда через инструменты разработчика DevTools браузера можно будет посмотртеь заголовки и узнать, какой блок сработал.
Внутренние редиректы
Вернемся опять к файлу конфигурации nginx — рассмотрим директивы, которые могут вызывать внутренние редиректы. Это значит, что когда nginx нашел подходящий location
, то директивы внутри этого location
могут предписывать начать новый поиск подходящего location
.
Директива index
Директива index
всегда вызывает внутреннюю переадресацию, если используется для обработки запроса. Точные совпадения location = string {...}
часто используются для ускорения поиска с немедленным завершением алгоритма. Однако, если точное совпадение расположения представляет собой каталог, есть вероятность, что запрос будет переадресован в другой location
.
В примере ниже первому расположению соответствует URI запроса /exact
, но унаследованная директива index
предписывает поиск нового location
, который бы соответствовал новому URI /exact/index.html
.
server { listen 80; server_name example.com www.example.com; root /var/www/example.com; index index.html; location = /exact { # ...прочие директивы конфигурации... } location / { # ...прочие директивы конфигурации... } }
Чтобы этого избежать — можно переопределить директиву index
, установив для нее значение, которое никогда не совпадет. И можно включить директиву autoindex
для показа содержимого директории вместо 404 Not Found.
server { listen 80; server_name example.com www.example.com; root /var/www/example.com; index index.html; location = /exact { index nothing_will_match; autoindex on; } location / { # ...прочие директивы конфигурации... } }
Директива try_files
Директива предписывает nginx проверить существование набора файлов или каталогов с определенным именем. Последним параметром может быть URI, на который nginx осуществляет внутреннюю переадресацию, если подходящий файл или директория не существует.
server { listen 80; server_name example.com www.example.com; root /var/www/example.com; index index.html; location / { try_files $uri $uri/ /fallback/index.html; } location /fallback { add_header X-debug-message "This is location /fallback, file $document_root$uri" always; # ...прочие директивы конфигурации... } }
При http-запросе URI /foo/bar
— nginx найдет первый блок location
и начнет выполянить директиву try_files
. Сперва проверит существование файла /var/www/example.com/foo/bar
, потом существование директории /var/www/example.com/foo/bar
. Поскольку нет ни файла, ни директории — выполнит внутренний редирект. Найдет новый location
и отправит клиенту файл /var/www/example.com/fallback/index.html
.
Директива error_page
Директива используется, чтобы определить, что должно происходить при получении определенных кодов состояния, например 404 или 500.
server { listen 80; server_name example.com www.example.com; root /var/www/example.com; index index.html; location / { error_page 404 /error/404.html; } location /error { add_header X-debug-message "This is location /error, file $document_root$uri" always; # ...прочие директивы конфигурации... } }
Каждый запрос, кроме начинающихся с /error
, будет обрабатываться первым блоком, который будет выводить файлы из /var/www/example.com
. Однако, если файл не найден (статус 404) — будет выполнена внутренняя переадресация. Nginx найдет новый location
и отправит клиенту файл /var/www/example.com/error/404.html
.
Установка службы PHP-FPM
Нужно установить пакет php8.1-fpm
. FPM расшифровывается как Fastcgi Process Manager, менеджер процессов FastCGI. PHP-FPM запускается как отдельный процесс и взаимодействует с веб-сервером через порт 9000 или сокетный файл. Является альтернативной реализацией PHP FastCGI с несколькими дополнительными возможностями, обычно используемыми для высоконагруженных сайтов.
$ sudo apt update $ sudo apt install php8.1-fpm
Проверяем работу службы PHP-FPM
$ systemctl is-active php8.1-fpm.service active
Файл конфигурации службы — это /etc/php/8.1/fpm/php-fpm.conf
, мы его трогать не будем — это тема для отдельного разговора
;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; All relative paths in this configuration file are relative to PHP's install ; prefix (/usr). This prefix can be dynamically changed by using the ; '-p' argument from the command line. ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; [global] ; Pid file ; Note: the default prefix is /var ; Default Value: none ; Warning: if you change the value here, you need to modify systemd ; service PIDFile= setting to match the value here. pid = /run/php/php8.1-fpm.pid ; Error log file ; If it's set to "syslog", log is sent to syslogd instead of being written ; into a local file. ; Note: the default prefix is /var ; Default Value: log/php-fpm.log error_log = /var/log/php8.1-fpm.log ; syslog_facility is used to specify what type of program is logging the ; message. This lets syslogd specify that messages from different facilities ; will be handled differently. ; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) ; Default Value: daemon ;syslog.facility = daemon ; syslog_ident is prepended to every message. If you have multiple FPM ; instances running on the same server, you can change the default value ; which must suit common needs. ; Default Value: php-fpm ;syslog.ident = php-fpm ; Log level ; Possible Values: alert, error, warning, notice, debug ; Default Value: notice ;log_level = notice ; Log limit on number of characters in the single line (log entry). If the ; line is over the limit, it is wrapped on multiple lines. The limit is for ; all logged characters including message prefix and suffix if present. However ; the new line character does not count into it as it is present only when ; logging to a file descriptor. It means the new line character is not present ; when logging to syslog. ; Default Value: 1024 ;log_limit = 4096 ; Log buffering specifies if the log line is buffered which means that the ; line is written in a single write operation. If the value is false, then the ; data is written directly into the file descriptor. It is an experimental ; option that can potentially improve logging performance and memory usage ; for some heavy logging scenarios. This option is ignored if logging to syslog ; as it has to be always buffered. ; Default value: yes ;log_buffering = no ; If this number of child processes exit with SIGSEGV or SIGBUS within the time ; interval set by emergency_restart_interval then FPM will restart. A value ; of '0' means 'Off'. ; Default Value: 0 ;emergency_restart_threshold = 0 ; Interval of time used by emergency_restart_interval to determine when ; a graceful restart will be initiated. This can be useful to work around ; accidental corruptions in an accelerator's shared memory. ; Available Units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 ;emergency_restart_interval = 0 ; Time limit for child processes to wait for a reaction on signals from master. ; Available units: s(econds), m(inutes), h(ours), or d(ays) ; Default Unit: seconds ; Default Value: 0 ;process_control_timeout = 0 ; The maximum number of processes FPM will fork. This has been designed to control ; the global number of processes when using dynamic PM within a lot of pools. ; Use it with caution. ; Note: A value of 0 indicates no limit ; Default Value: 0 ; process.max = 128 ; Specify the nice(2) priority to apply to the master process (only if set) ; The value can vary from -19 (highest priority) to 20 (lowest priority) ; Note: - It will only work if the FPM master process is launched as root ; - The pool process will inherit the master process priority ; unless specified otherwise ; Default Value: no set ; process.priority = -19 ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. ; Default Value: yes ;daemonize = yes ; Set open file descriptor rlimit for the master process. ; Default Value: system defined value ;rlimit_files = 1024 ; Set max core size rlimit for the master process. ; Possible Values: 'unlimited' or an integer greater or equal to 0 ; Default Value: system defined value ;rlimit_core = 0 ; Specify the event mechanism FPM will use. The following is available: ; - select (any POSIX os) ; - poll (any POSIX os) ; - epoll (linux >= 2.5.44) ; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) ; - /dev/poll (Solaris >= 7) ; - port (Solaris >= 10) ; Default Value: not set (auto detection) ;events.mechanism = epoll ; When FPM is built with systemd integration, specify the interval, ; in seconds, between health report notification to systemd. ; Set to 0 to disable. ; Available Units: s(econds), m(inutes), h(ours) ; Default Unit: seconds ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; ; Multiple pools of child processes may be started with different listening ; ports and different management options. The name of the pool will be ; used in logs and stats. There is no limitation on the number of pools which ; FPM can handle. Your system will tell you anyway :) ; Include one or more files. If glob(3) exists, it is used to include a bunch of ; files from a glob(3) pattern. This directive can be used everywhere in the ; file. ; Relative path can also be used. They will be prefixed by: ; - the global prefix if it's been set (-p argument) ; - /usr otherwise include=/etc/php/8.1/fpm/pool.d/*.conf
Подключение Nginx к PHP-FPM
Чтобы принимать запросы FastCGI от Nginx, PHP-FPM может прослушивать TCP/IP сокет или UNIX сокет. Сокеты UNIX являются средством межпроцессного взаимодействия, которое обеспечивает эффективный обмен данными между процессами, работающими на одном сервере, в то время как сокеты TCP/IP позволяют процессам обмениваться данными по сети.
Сокет UNIX — это особый тип файла, к нему применяются разрешения на доступ к файлам и каталогам (как в случае с любым другим типом файла), и его можно использовать для ограничения того, какие процессы на хосте могут читать и записывать в файл (и таким образом, общаться с внутренним сервером).
Таким образом, сокет UNIX является безопасным, поскольку его могут использовать только процессы на локальном хосте. Сокет TCP/IP может быть доступен из интернета, и это может представлять угрозу безопасности, если не будут приняты дополнительные меры безопасности, такие как настройка брандмауэра.
Файл конфигурации nginx для работы с php-fpm
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com www.example.com; root /var/www/example.com/; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { # файл сокета для общения с php-fpm службой, которая будет выполнять php-код fastcgi_pass unix:/run/php/php8.1-fpm-example-com.sock; # может быть файл /etc/nginx/fastcgi_params или файл /etc/nginx/fastcgi.conf # у файлов одинаковое содержимое, но в fastcgi.conf есть еще SCRIPT_FILENAME include fastcgi.conf; } }
$ sudo systemctl restart nginx.service
В файле /etc/nginx/fastcgi.conf
устанавливаются значения переменных, которые будут доступны php скрипту во время выполнения.
$ cat /etc/nginx/fastcgi.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param REMOTE_USER $remote_user; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
Файл fastcgi_params
появился намного раньше fastcgi.conf
. Часто можно встетить конфигурации, где используется именно fastcgi_params
, а значение переменной SCRIPT_FILENAME
устанавливается отдельно внутри location
для FastCGI.
Создадим еще файл /var/www/example.com/index.php
для проверки работы php
$ sudo nano /var/www/example.com/index.php
<h1>Сайт example.com, файл /index.php</h1> <?php phpinfo(); ?>
Настройка PHP-FPM для прослушивания сокета UNIX
После установки PHP-FPM есть файл конфигурации пула www.conf
для обслуживания запросов от Nginx или Apache. В PHP-FPM каждый запрос обрабатывается заранее запущенным процессом из пула. Потому что запуск процесса — дорогая операция, лучше запустить все процессы заранее. Все процессы в пуле — однотипные, предназначены для обработки запросов от одного сайта. Для нашего сайта example.com
мы создадим отдельный пул.
$ sudo cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/example-com.conf
И отредактируем файл конфигурации пула, изменим только имя и директиву listen
. Настройка пула — это тема для отдельного разговора.
$ sudo nano /etc/php/8.1/fpm/pool.d/example-com.conf
; имя пула, должно быть обязательно задано и быть уникальным [example-com] ; пользователь и группа, от имени которого работают процессы user = www-data group = www-data listen = /run/php/php8.1-fpm-example-com.sock ; пользователь и группа, которые могут читать и записывать unix-сокет ; здесь указываются пользователь и группа, под которым работает nginx listen.owner = www-data listen.group = www-data listen.mode = 0660
Вообще, было бы правильно создать отдельного пользователя, от имени которого PHP-FPM запускал бы процессы для этого пула. Но упростим себе немного задачу — пусть процессы запускаются от имени уже существующего пользователя www-data
.
Файл пула www.conf
нужно удалить или переименовать — чтобы этот пул не создавался и мы не тратили ресурсы сервера впустую.
$ sudo mv /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/www.back
Перезапускаем службу, чтобы применить новые настройки
$ sudo systemctl restart php8.1-fpm.service
Проверяем работу службы PHP-FPM с новыми настройками
$ systemctl is-active php8.1-fpm.service active
Смотрим запущенные процессы пользователя www-data
$ ps -u www-data -F UID PID PPID C SZ RSS PSR STIME TTY TIME CMD www-data 673 669 0 13975 5708 0 12:09 ? 00:00:00 nginx: worker process www-data 1387 1386 0 50793 7128 0 14:20 ? 00:00:00 php-fpm: pool exaple-com www-data 1388 1386 0 50793 7128 0 14:20 ? 00:00:00 php-fpm: pool exaple-com
Их всего три, один процесс nginx и два процесса php-fpm. Все готово, можно проверять
Настройка PHP-FPM для прослушивания сокета TCP/IP
Отличий от прослушивания сокета UNIX немного — нужно изменить директиву listen
файла конфигурации пула процессов php-fpm и директиву fastcgi_pass
файла конфигурации nginx.
$ sudo nano /etc/php/8.1/fpm/pool.d/example-com.conf
; имя пула, должно быть обязательно задано и быть уникальным [example-com] ; пользователь и группа, от имени которого работают процессы user = www-data group = www-data listen = 127.0.0.1:9000 ; пользователь и группа, которые могут читать и записывать unix-сокет ; здесь указываются пользователь и группа, под которым работает nginx listen.owner = www-data listen.group = www-data listen.mode = 0660
$ sudo systemctl restart php8.1-fpm.service
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; server_name example.com www.example.com; root /var/www/example.com/; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { # файл сокета для общения с php-fpm службой, которая будет выполнять php-код fastcgi_pass 127.0.0.1:9000; # может быть файл /etc/nginx/fastcgi_params или файл /etc/nginx/fastcgi.conf # у файлов одинаковое содержимое, но в fastcgi.conf есть еще SCRIPT_FILENAME include fastcgi.conf; } }
$ sudo systemctl restart nginx.service
Если мы создаем новый виртуальный хост и хотим обрабатывать php-файлы — нужно создать новый пул процессов php-fpm и для директивы listen
задать другое значение порта, например 9001
. Соответственно, в файле конфигурации nginx нового виртуального хоста для директивы fastcgi_pass
указать номер этого порта.
При этом, оба пула процессов будут использовать один файл конфигурации php.ini
. Чтобы установить индивидуальные значения конфигурации для каждого пула — их нужно прописать в файле конфигурации пула процессов.
$ sudo nano /etc/php/8.1/fpm/pool.d/host-one.conf
[host-one] # ... прочие директивы конфигурации ... listen = /run/php-fpm/host-one.sock # ... прочие директивы конфигурации ... request_slowlog_timeout = 5 slowlog = /var/log/php-fpm/host-one-slow.log # ... прочие директивы конфигурации ... php_admin_value[error_log] = /var/log/php-fpm/host-one-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/host-one
$ sudo nano /etc/php/8.1/fpm/pool.d/host-two.conf
[host-two] # ... прочие директивы конфигурации ... listen = /run/php-fpm/host-two.sock # ... прочие директивы конфигурации ... request_slowlog_timeout = 5 slowlog = /var/log/php-fpm/host-two-slow.log # ... прочие директивы конфигурации ... php_admin_value[error_log] = /var/log/php-fpm/host-two-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/host-two
Директива php_admin_value
используется для установки строковых значений, директива php_admin_flag
— для установки флагов типа on
или off
. Директивы php_value
и php_flag
позволяют задать значения, которые потом можно перезаписать с помощью функции ini_set
. Директивы с использованием admin
перезаписать нельзя.
Файл конфигурации Nginx для PHP-FPM
Мы до сих пор использовали минимальную конфигурацию для работы nginx с php-fpm. Давайте доработаем конфигурацию, чтобы она больше отвечала реальности.
server { listen 80; server_name example.com www.example.com; root /var/www/example.com/; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { # рекомендуемый разработчиками nginx файл конфигурации для работы с php-fpm include snippets/fastcgi-php.conf; # файл сокета для общения с php-fpm службой, которая будет выполнять php-код fastcgi_pass unix:/run/php/php8.1-fpm-example-com.sock; } location = /robots.txt { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; } location ~* \.(ico|css|js|gif|jpe?g|png)$ { add_header Cache-Control "public, max-age=3600"; } location ~ /\. { access_log off; log_not_found off; deny all; } # при возникновении ошибок будем показывать специальные страницы error_page 404 403 /error/404.html; error_page 500 502 503 504 /error/50x.html; access_log /var/log/nginx/example.com-access.log; error_log /var/log/nginx/example.com-error.log error; }
Файл конфигурации nginx /etc/nginx/sites-enabled/default
содержит пример подключения php-fpm
— рекомендуется подключить использовать snippets/fastcgi-php.conf
.
$ cat /etc/nginx/sites-enabled/default
server { # ... прочие директивы конфигураци ... location ~ \.php$ { include snippets/fastcgi-php.conf; # With php-fpm (or other unix sockets) fastcgi_pass unix:/run/php/php7.4-fpm.sock; # With php-cgi (or other tcp sockets) fastcgi_pass 127.0.0.1:9000; } }
$ cat /etc/nginx/snippets/fastcgi-php.conf
# regex to split $uri to $fastcgi_script_name and $fastcgi_path fastcgi_split_path_info ^(.+?\.php)(/.*)$; # Check that the PHP script exists before passing it try_files $fastcgi_script_name =404; # Bypass the fact that try_files resets $fastcgi_path_info # see: http://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; fastcgi_index index.php; include fastcgi.conf;
Директива fastcgi_split_path_info
определяет регулярное выражение с двумя захваченными группами. Первая захваченная группа используется в качестве значения переменной $fastcgi_script_name
. Вторая захваченная группа используется в качестве значения переменной $fastcgi_path_info
. Необходимость в этой директиве возникает, если запрошенный URI имеет вид /index.php/foo/bar
.
Директива fastcgi_index
не нужна, если службы nginx.service
и php8.1-fpm.service
работают на одной машине. В этом случае nginx при запросе директории может проверить существование индексного файла index.php
в файловой системе сервера. Но если служба php8.1-fpm.service
работает на другом хосте — такой возможности нет. В этом случаем может помочь директива fastcgi_index
— ее значение просто добавляется к любой запрошенной директории.
server { location ~ (\.php|/)$ { fastcgi_pass 192.168.100.2:9000; fastcgi_index index.php; } }
Еще один момент по поводу безопасности. Перед тем, как отдавать php-файл на выполнение службе php-fpm
— следует проверить, что этот файл существует. Допустим, есть запрос типа /image.jpg/index.php
. Если конфигурация просто передает каждый запрос, заканчивающийся на .php
— служба php-fpm
проверит существование index.php
и выполнит его. Если index.php
не существует — служба php-fpm
будет следовать спецификации и попытается выполнить test.jpg
.
Самый простой способ избежать этого — отредактировать файл конфигурации php.ini
и установить для cgi.fix_pathinfo
нулевое значение. Другой способ, если служба php-fpm
находится на той же машине, что и служба nginx.service
— проверить наличие файлов на диске перед их передачей в процессор. В файле snippets/fastcgi-php.conf
мы как раз видим такую проверку.
Настройка поддержки HTTPS
У нас тестовый веб-сервер, нужно выпустить сертификат для локального домена example.com
. Это делается в несколько этапов. Сначала создаем приватный и публичный ключ Центра Сертификации (CA, Certificate Authority). Потом публичный ключ CA подписываем приватным ключом CA. Таким образом получаем самоподписанный сертификат CA, который надо добавить в доверенные в браузере. Далее создаем приватный и публичный ключ для домена example.com
. Публичный ключ домена example.com
подписываем приватным ключом CA — получаем сертификат для домена. Чтобы подписать публичный ключ домена — нужно создать запрос на подпись.
$ mkdir ~/ca $ chdir ~/ca
Для создания пары ключей и подписи будем использовать утилиту openssl
$ openssl команда опции
Создание приватного ключа Центра Сертификации
$ openssl genpkey \ > -aes256 \ > -algorithm RSA \ > -pkeyopt rsa_keygen_bits:4096 \ > -pass pass:qwerty \ > -out root-ca.key
Команда genpkey
(заменяет genrsa
, gendh
и gendsa
) означает создание приватного ключа (generate private key). Алгоритм ключа RSA, дина 4096 бит, зашифрован алгоритмом aes256. Опция -pass
задает пароль qwerty
для обеспечения безопасности ключа. Опция -out
указывает на имя файла для сохранения, без этой опции файл будет выведен в стандартный вывод.
Создание самоподписанного корневого сертификата
$ openssl req \ > -x509 \ > -new \ > -key root-ca.key \ > -days 7300 \ > -subj "/C=RU/ST=Moscow/L=Moscow/O=Demo Inc/OU=IT Dept/CN=Demo CA" \ > -addext "basicConstraints = critical,CA:TRUE" \ > -addext "subjectKeyIdentifier = hash" \ > -addext "authorityKeyIdentifier = keyid:always,issuer" \ > -addext "keyUsage = critical,keyCertSign,cRLSign" \ > -out root-ca.crt Enter pass phrase for root-ca.key: qwerty
Просмотр самоподписанного сертификата (не обязательно, просто для проверки, что все правильно)
$ openssl x509 -text -noout -in root-ca.crt
Команда req
означает запрос на подпись (CSR, Certificate Signing Request). Опция -new
означает создание нового сертификата. Опция -key
указывает на имя файла приватного ключа. Опция -days
— срок действия сертификата.
Создание файла приватного ключа и файла запроса на подпись (сразу две операции одной командой)
$ openssl req -newkey rsa:3072 \ > -keyform PEM \ > -outform PEM \ > -nodes \ > -subj "/C=RU/ST=Moscow/L=Moscow/O=Demo Inc/OU=IT Dept/CN=example.com" \ > -addext "basicConstraints = CA:FALSE" \ > -addext "subjectKeyIdentifier = hash" \ > -addext "keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment" \ > -addext "extendedKeyUsage=serverAuth" \ > -addext "subjectAltName=DNS:example.com,DNS:www.example.com" \ > -keyout example-com.key \ > -out example-com.csr
Просмотр запроса на подпись (не обязательно, просто для проверки, что все правильно)
$ openssl req -text -noout -in example-com.csr
Подпись запроса и получение сертификата на год
$ openssl x509 -req \ > -in example-com.csr \ > -CA root-ca.crt \ > -CAkey root-ca.key \ > -CAcreateserial \ > -days 365 \ > -out example-com.crt \ > --copy_extensions=copyall Certificate request self-signature ok subject=C = RU, ST = Moscow, L = Moscow, O = Demo Inc, OU = IT Dept, CN = example.com Enter pass phrase for root-ca.key: qwerty
Просмотр подписанного сертификата (не обязательно, просто для проверки, что все правильно)
$ openssl x509 -text -noout -in example-com.crt
Скопируем приватный ключ и сертификат в директорию /etc/ssl
$ sudo cp /home/evgeniy/ca/example-com.crt /etc/ssl/certs/ $ sudo cp /home/evgeniy/ca/example-com.key /etc/ssl/private/
Отредактируем файл конфигурации nginx
$ sudo nano /etc/nginx/sites-available/example.com
server { listen 80; listen 443 ssl; server_name example.com www.example.com; root /var/www/example.com/; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { # рекомендуемый разработчиками nginx файл конфигурации для работы с php-fpm include snippets/fastcgi-php.conf; # файл сокета для общения с php-fpm службой, которая будет выполнять php-код fastcgi_pass 127.0.0.1:9000; } error_page 404 403 /error/404.html; error_page 500 502 503 504 /error/50x.html; ssl_certificate /etc/ssl/certs/example-com.crt; ssl_certificate_key /etc/ssl/private/example-com.key; access_log /var/log/nginx/example.com-access.log; error_log /var/log/nginx/example.com-error.log error; }
$ sudo systemctl restart nginx.service
Теперь нужно скопировать корневой сертификат /home/evgeniy/ca/root-ca.crt
на свой компьютер и добавить его в доверенные в браузере.
$ scp evgeniy@example.com:/home/evgeniy/ca/root-ca.crt ~/
В браузере Chrome нужно зайти в настройки, перейти в «Безопасность и конфиденциальность», потом «Безопасность», дальше «Настроить сертификаты». И добавить сертификат в «Доверенные корневые центры сертификации».
Дополнительно
- Как установить Nginx на Ubuntu: пошаговая инструкция
- Оптимизация NGINX, ускорение работы сайта
- Работа сервера Nginx и алгоритма выбора блока
- Директива location в Nginx, алгоритм выбора блока
- Размещение нескольких сайтов на NGINX и PHP-FPM в Ubuntu 14.04
- OpenSSL, часть 1: Создание собственного Удостоверяющего Центра
- OpenSSL, часть 2: Создание ключа и сертификата для веб-сервера
- OpenSSL, часть 3: Создание ключа и сертификата для клиента
Поиск: CLI • Nginx • Конфигурация • Настройка • Установка • FastCGI • Сервер