Настройка Nginx
Установка на Nginx вполне возможна, и, по нашему опыту, намного быстрее, чем на apache. В этом разделе не будет рассказано о том, как устанавливается Nginx и т.д., но будет показана рабочая конфигурация Nginx.
Конфигурация
Ниже приведена конфигурация для сервера Nginx (только серверная часть, http и т.д. часть может быть сохранена по умолчанию, при условии, что включены mime.types).
Предположения - измените их в соответствии с вашей средой/дистрибутивом:
- Pimcore был установлен в:
/var/www/pimcore; следовательно, корень документа:/var/www/pimcore/public. - Файлы журналов записываются в папку по умолчанию
/var/log/nginx. Если вы предпочитаете хранить журналы вместе с журналами Pimcore, они находятся в папке/var/www/pimcore/var/log. - PHP-FPM настроен на прослушивание сокета
/var/run/php/pimcore.sock. Если ваши настройки отличаются, измените директивуserverв блокеupstreamсоответствующим образом. - Прежде чем изменять порядок расположения блоков, прочитайте Общие сведения о сервере Nginx и алгоритмах выбора блока расположения
- Срок действия ассетов истекает через 14 дней; измените все указания
expiresв соответствии с вашими потребностями. - Ассеты не хранятся в удаленном хранилище, таком как GCS или S3. Если это так, смотрите раздел #Ассеты в конфигурации Nginx.
Среда разработки
Следующая конфигурация используется в предположении, что она предназначена только для разработки. Она не подходит для продакшн среды и не должна предоставляться в открытый доступ.
# типы mime уже описаны в файле nginx.conf
#include mime.types;
upstream php-pimcore10 {
server unix:/var/run/php/pimcore.sock;
}
map $args $static_page_root {
default /var/tmp/pages;
"~*(^|&)pimcore_editmode=true(&|$)" /var/nonexistent;
"~*(^|&)pimcore_preview=true(&|$)" /var/nonexistent;
"~*(^|&)pimcore_version=[^&]+(&|$)" /var/nonexistent;
}
map $uri $static_page_uri {
default $uri;
"/" /%home;
}
server {
listen 80;
listen [::]:80;
server_name YOUPROJECT.local;
root /var/www/pimcore/public;
index index.php;
# Размер файла зависит от ваших данных
client_max_body_size 100m;
# Рекомендуется изолировать журналы для каждого виртуального хоста
access_log /var/log/access.log;
error_log /var/log/error.log error;
# Защищенные ассеты
#
### 1. Опция - Полное ограничение доступа к определенным ассетам
#
# location ~ ^/protected/.* {
# return 403;
# }
# location ~ ^/var/.*/protected(.*) {
# return 403;
# }
#
# location ~ ^/cache-buster\-[\d]+/protected(.*) {
# return 403;
# }
#
### 2. Опция - Проверка разрешений перед отправкой
#
# rewrite ^(/protected/.*) /index.php$is_args$args last;
#
# location ~ ^/var/.*/protected(.*) {
# return 403;
# }
#
# location ~ ^/cache-buster\-[\d]+/protected(.*) {
# return 403;
# }
# Удаление кэша заголовочных ссылок Pimcore
rewrite ^/cache-buster-(?:\d+)/(.*) /$1 last;
# Оставайтесь в безопасности
#
# a) не разрешайте PHP в папках, разрешающих загрузку файлов
location ~* /var/assets/.*\.php(/|$) {
return 404;
}
# b) Запретить клиентам доступ к скрытым файлам (начинающихся с точки)
# Доступ к `/.well-known/` разрешен.
# https://www.mnot.net/blog/2010/04/07/well-known
# https://tools.ietf.org/html/rfc5785
location ~* /\.(?!well-known/) {
deny all;
log_not_found off;
access_log off;
}
# c) Запретить клиентам доступ к резервным/конфигурационным/исходным файлам
location ~* (?:\.(?:bak|conf(ig)?|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ {
deny all;
}
# Это необходимо некоторым административным модулям:
# Server Info, Opcache
location ~* ^/admin/external {
rewrite .* /index.php$is_args$args last;
}
# Thumbnails
location ~* .*/(image|video)-thumb__\d+__.* {
try_files /var/tmp/thumbnails$uri /index.php;
expires 2w;
access_log off;
add_header Cache-Control "public";
}
# Ассеты
# По-прежнему используется метод allowlist, чтобы предотвратить передачу всех отсутствующих ресурсов через движок PHP.
# Если вы используете удаленные хранилища, такие как S3 или Google Cloud Storage, это не сработает. Вы либо отключаете его, либо обрабатываете в PHP
# или перенаправьте эти суффиксы непосредственно на ваш URL-адрес CDN. Кроме того, вам следует соответствующим образом настроить префиксы URL-адресов внешнего интерфейса, см.: https://pimcore.com/docs/pimcore/current/Development_Documentation/Installation_and_Upgrade/System_Setup_and_Hosting/File_Storage_Setup.html
location ~* ^(?!/admin|/asset/webdav)(.+?)\.((?:css|js)(?:\.map)?|jpe?g|gif|png|svgz?|eps|exe|gz|zip|mp\d|m4a|ogg|ogv|webp|webm|pdf|docx?|xlsx?|pptx?)$ {
try_files /var/assets$uri $uri =404;
expires 2w;
access_log off;
log_not_found off;
add_header Cache-Control "public";
}
location / {
error_page 404 /meta/404;
try_files $static_page_root$static_page_uri.html $uri /index.php$is_args$args;
}
# Используйте это расположение, когда необходимо запустить программу установки
# location ~ /(index|install)\.php(/|$) {
#
# Используйте это после завершения первоначальной установки:
location ~ ^/index\.php(/|$) {
send_timeout 1800;
fastcgi_read_timeout 1800;
# регулярное выражение для разделения $uri на $fastcgi_script_name и $fastcgi_path_info
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Убедитесь, что PHP-скрипт существует, прежде чем передавать его
try_files $fastcgi_script_name =404;
# при необходимости включите файл fastcgi.conf
include fastcgi.conf;
# Обойти тот факт, что try_files сбрасывает $fastcgi_path_info
# см.: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
# Активируйте их, если используете символические ссылки и opcache
# fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
# fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_pass php-pimcore10;
# Запрещает использование URI, которые включают в себя внешний контроллер. Это приведет к 404:
# http://domain.tld/index.php/some-path
# Удалению внутренней директивы, разрешающей использовать URI, подобные этому
внутреннему;
}
# Статус PHP-FPM и Ping
location /fpm- {
access_log off;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
location /fpm-status {
allow 127.0.0.1;
# add additional IP's or Ranges
deny all;
fastcgi_pass php-pimcore10;
}
location /fpm-ping {
fastcgi_pass php-pimcore10;
}
}
# Статус nginx
# см.: https://nginx.org/en/docs/http/ngx_http_stub_status_module.html
location /nginx-status {
allow 127.0.0.1;
deny all;
access_log off;
stub_status;
}
}
Продакшн-окружение
Следующая конфигурация обеспечивает приемлемую базу для безопасного размещения приложений. Ее можно адаптировать к вашим настройкам и предпочтениям. Однако в первую очередь она учитывает безопасность. Рекомендуется также разрабатывать в защищенной среде.
# типы mime уже описаны в файле nginx.conf
#include mime.types;
upstream php-pimcore10 {
server unix:/var/run/php/pimcore.sock;
}
map $args $static_page_root {
default /var/tmp/pages;
"~*(^|&)pimcore_editmode=true(&|$)" /var/nonexistent;
"~*(^|&)pimcore_preview=true(&|$)" /var/nonexistent;
"~*(^|&)pimcore_version=[^&]+(&|$)" /var/nonexistent;
}
server {
listen 80;
listen [::]:80;
server_name YOUPROJECT.local;
root /var/www/pimcore/public;
# Мы принимаем .well-known в случае вызова acme (например, letsencrypt)
# Все остальное, однако, возвращает имя хоста с / location
# Хорошую ссылку для объяснения можно найти здесь:
# https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms#matching-location-blocks
location ~* /\.well-known/ {
try_files $uri /;
}
# Пожалуйста, обратите внимание, что возврат обойдется дешевле, чем перенаправление
# См.: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#taxing-rewrites
location / {
return 301 https://$host$request_uri;
}
}
# Конфигурация, связанная с SSL, рекомендованная Mozilla в качестве "промежуточной".
# См.: https://ssl-config.mozilla.org/
# В этой конфигурации используются nginx 1.17.7, OpenSSL 1.1.1d
# Поддерживает: Firefox 27, Android 4.4.2, Chrome 31, Edge, IE 11 в Windows 7, Java 8u31, OpenSSL 1.0.1, Opera 20 и Safari 9.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name YOUPROJECT.local;
root /var/www/pimcore/public;
index index.php;
# SSL-сертификат и ключ
# Для запуска letsencrypt вы можете использовать следующую команду:
# certbot certonly -n -expand -nginx -d YOUPROJECT.local
# В зависимости от вашей операционной системы вам может потребоваться установить python-certbot-nginx
ssl_certificate /etc/letsencrypt/live/YOUPROJECT.local/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUPROJECT.local/privkey.pem;
# После этого проверьте безопасность (если применимо) с помощью https://ssllabs.com
# Рекомендуется исключить следующие настройки и включить в виде файла
# Раскомментировать, если применимо:
# включить /etc/nginx/conf-available/ssl.configuration.conf;
### Настройка SSL
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# Запустите следующий комментарий, чтобы получить доступ к самому последнему файлу dhparam
# Пожалуйста, убедитесь, что имя владельца установлено правильно в зависимости от операционной системы (обычно root) и права равны 644
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/ssl/dhparam.pem
ssl_dhparam /etc/ssl/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS (требуется ngx_http_headers_module) (63072000 секунд)
add_header Strict-Transport-Security "max-age=63072000" always;
# Сшивание OCSP
ssl_stapling on;
ssl_stapling_verify on;
# проверьте цепочку доверия в ответе OCSP, используя корневой центр сертификации и промежуточные сертификаты
# Выполните следующие команды, чтобы получить цепочку доверия для LetsEncrypt
# curl https://letsencrypt.org/certs/isrgrootx1.pem.txt > /etc/ssl/letsencrypt.cot.pem \
# && curl https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt >> /etc/ssl/letsencrypt.cot.pem \
# && curl https://letsencrypt.org/certs/letsencryptauthorityx3.pem.txt >> /etc/ssl/letsencrypt.cot.pem \
# && chown root:ssl-cert /etc/ssl/letsencrypt.cot.pem && chmod 644 /etc/ssl/letsencrypt.cot.pem
ssl_trusted_certificate /etc/ssl/letsencrypt.cot.pem;
# замените на IP-адрес вашего распознавателя
# Это может быть, например, 1.1.1.1 (с использованием службы Cloudflares DNS)
# или, в качестве альтернативы, внутренний DNS-сервер
resolver 127.0.0.1;
### Настройка SSL
# установите http-заголовки для обеспечения максимальной безопасности ... в любом случае, насколько это возможно.
# После этого проверьте безопасность (если применимо) с помощью https://securityheaders.com/
# Рекомендуется исключить следующие настройки и включить в виде файла
# Раскомментируйте, если применимо:
# включить /etc/nginx/conf-включить/http.header.configuration.conf;
### Защита заголовка HTTP
# Удалить токен
server_tokens off;
# Установите CSP
# Пожалуйста, обратите внимание, что CSP очень сложны и могут быть достаточно сложными для правильного использования
# Для обеспечения оптимальной безопасности, однако, они абсолютно обязательны
# Есть способы "переопределить" их для упрощения разработки
# Однако их следует тщательно оценить, определить и включить
add_header Content-Security-Policy "default-src 'self';" always;
# Политика привлечения рефералов
add_header Referrer-Policy same-origin;
# Политика в отношении функций и политика разрешений
# Обратите внимание, что политика в отношении функций должна быть заменена Политикой разрешений
# Смотрите документ W3C, касающийся настройки: https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md
#
# Пожалуйста, ознакомьтесь с тем, как правильно оценивать, определять и включать в соответствии с вашими потребностями
# Спасибо: https://fearby.com/article/set-up-feature-policy-referrer-policy-and-content-security-policy-headers-in-nginx/
# за предварительную подготовку.
add_header Feature-Policy "geolocation 'none';midi 'none';sync-xhr 'none';microphone 'none';camera 'none';magnetometer 'none';gyroscope 'none';fullscreen 'self';payment 'none';";
add_header Permissions-Policy "geolocation=(), midi=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=()";
# установить X-Frame-Options
add_header X-Frame-Options "SAMEORIGIN" always;
# установить Xss-Protection
add_header X-Xss-Protection "1; mode=block" always;
# X-Content-Type-Options
add_header X-Content-Type-Options "nosniff" always;
### HTTP Header security
# Размер файла зависит от ваших данных
client_max_body_size 100m;
# Рекомендуется изолировать журналы для каждого виртуального хоста
access_log /var/log/access.log;
error_log /var/log/error.log error;
# Защищенные ассеты
#
### 1. Опция - Полное ограничение доступа к определенным ассетам
#
# location ~ ^/protected/.* {
# return 403;
# }
# location ~ ^/var/.*/protected(.*) {
# return 403;
# }
#
# location ~ ^/cache-buster\-[\d]+/protected(.*) {
# return 403;
# }
#
### 2. Опция - Проверка разрешений перед отправкой
# rewrite ^(/protected/.*) /index.php$is_args$args last;
#
# location ~ ^/var/.*/protected(.*) {
# return 403;
# }
#
# location ~ ^/cache-buster\-[\d]+/protected(.*) {
# return 403;
# }
# Удаление кэша заголовочных ссылок Pimcore
rewrite ^/cache-buster-(?:\d+)/(.*) /$1 last;
# Оставайтесь в безопасности
#
# a) не разрешайте PHP в папках, разрешающих загрузку файлов
location ~* /var/assets/.*\.php(/|$) {
return 404;
}
# b) Запретить клиентам доступ к скрытым файлам (начинающимся с точки)
# Разрешен доступ к файлам `/.well-known/`.
# https://www.mnot.net/blog/2010/04/07/well-known
# https://tools.ietf.org/html/rfc5785
location ~* /\.(?!well-known/) {
deny all;
log_not_found off;
access_log off;
}
# c) Запретить клиентам доступ к резервным/конфигурационным/исходным файлам
location ~* (?:\.(?:bak|conf(ig)?|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ {
deny all;
}
# Это необходимо для некоторых модулей администрирования:
# Server Info, Opcache
location ~* ^/admin/external {
rewrite .* /index.php$is_args$args last;
}
# Thumbnails
location ~* .*/(image|video)-thumb__\d+__.* {
try_files /var/tmp/thumbnails$uri /index.php;
expires 2w;
access_log off;
add_header Cache-Control "public";
}
# Ресурсы
# По-прежнему используется метод allowlist, чтобы предотвратить передачу всех отсутствующих ресурсов через движок PHP.
# Если вы используете удаленные хранилища, такие как S3 или Google Cloud Storage, это не сработает. Вы либо отключаете его, либо обрабатываете в PHP
# или перенаправьте эти суффиксы непосредственно на ваш URL-адрес CDN. Кроме того, вам следует соответствующим образом настроить префиксы URL-адресов внешнего интерфейса, см.: https://pimcore.com/docs/pimcore/current/Development_Documentation/Installation_and_Upgrade/System_Setup_and_Hosting/File_Storage_Setup.html
location ~* ^(?!/admin|/asset/webdav)(.+?)\.((?:css|js)(?:\.map)?|jpe?g|gif|png|svgz?|eps|exe|gz|zip|mp\d|m4a|ogg|ogv|webp|webm|pdf|docx?|xlsx?|pptx?)$ {
try_files /var/assets$uri $uri =404;
expires 2w;
access_log off;
log_not_found off;
add_header Cache-Control "public";
}
location / {
error_page 404 /meta/404;
try_files $static_page_root$uri.html $uri /index.php$is_args$args;
}
# Используйте это расположение, когда необходимо запустить программу установки.
# location ~ /(index|install)\.php(/|$) {
#
# Используйте это после завершения первоначальной установки:
location ~ ^/index\.php(/|$) {
send_timeout 1800;
fastcgi_read_timeout 1800;
# регулярное выражение для разделения $uri на $fastcgi_script_name и $fastcgi_path_info
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Убедитесь, что PHP-скрипт существует, прежде чем передавать его
try_files $fastcgi_script_name =404;
# при необходимости включите файл fastcgi.conf
include fastcgi.conf;
# Обойти тот факт, что try_files сбрасывает $fastcgi_path_info
# см.: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
# Активируйте их, если используете символические ссылки и opcache
# fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
# fastcgi_param DOCUMENT_ROOT $realpath_root;
# Устранение https://httpoxy.org/ уязвимостей
fastcgi_param HTTP_PROXY "";
fastcgi_pass php-pimcore10;
# Запрещает использование URI, которые включают в себя внешний контроллер. Это приведет к 404:
# http://domain.tld/index.php/some-path
# Удалению внутренней директивы, разрешающей использовать URI, подобные этому
внутреннему;
}
# Статус PHP-FPM и Ping
location /fpm- {
access_log off;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
location /fpm-status {
allow 127.0.0.1;
# добавьте дополнительные IP-адреса или диапазоны
deny all;
fastcgi_pass php-pimcore10;
}
location /fpm-ping {
fastcgi_pass php-pimcore10;
}
}
# статус nginx
# см.: https://nginx.org/en/docs/http/ngx_http_stub_status_module.html
location /nginx-status {
allow 127.0.0.1;
deny all;
access_log off;
stub_status;
}
}
Защита от перегрузки при создании миниатюр
В случае, если в вашем веб-приложении есть страница с большим количеством изображений, которые обрабатываются конвейером изображений, есть вероятность, что это может перегрузить ваш сервер из-за слишком большого количества параллельно запущенных PHP-процессов, которые пытаются генерировать миниатюры, особенно если ваши пользователи загружают довольно большие изображения (например, в формате 16:9, более 5000 пикселей в ширину).
В этом случае вы можете расширить конфигурацию nginx, описанную выше, чтобы использовать ограничение скорости nginx. Вам все равно следует ознакомиться с ограничением скорости, чтобы защитить свой сайт от атак типа "Отказ в обслуживании".
Шаг 1: Создайте зону
Где-нибудь в разделе http вашей конфигурации nginx добавьте это:
# Зона для ограничения генерации изображений Pimcore по запросу
limit_req_zone $server_name zone=imggen:1M rate=5r/s;
Это определяет новую зону под названием imggen, которая использует $server_name в качестве ключа и допускает 5 запросов в секунду. Вам следует настроить это число в соответствии с возможностями ваших серверов.
Шаг 2: Замените местоположение, которое обрабатывает создание эскизов по запросу.
# Создание эскизов Pimcore по запросу
# с ограничением скорости.
location ~* .*/(image|video)-thumb__\d+__.* {
try_files /var/tmp/thumbnails$uri @imggen;
expires 2w;
access_log off;
add_header Cache-Control "public";
}
location @imggen {
limit_req zone=imggen burst=15;
try_files /var/tmp/thumbnails$uri /index.php;
expires 2w;
access_log off;
add_header Cache-Control "public";
}
Это связано с затратами на дополнительный вызов stat, который в любом случае должен быть кэширован, поэтому накладные расходы должны быть незначительными.
Эта конфигурация позволяет поставить в очередь 15 запросов, прежде чем отклонять дополнительные запросы с ошибкой HTTP 429. Такая корзина поддерживается для каждого виртуального хоста и удаляется с использованием 5 запросов в секунду (как определено на шаге 1).
Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.