Настройка производительного веб-сервера на NGINX + PHP-FPM
Подключение репозитория, обновление сервера
Так как установка производится на вновь установленном сервере с CentOS, нужно подключить популярный репозиторий EPEL и обновить на сервере все пакеты.
# yum install epel-release -y# yum update -y
Репозиторий установился, но пакетов для обновлений не найдено, так как установлен свежий образ CentOS.
Установка и настройка веб-сервера Nginx
Для установки свежей версии Nginx, подключим репозиторий разработчика, выполнив команду:
# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
Или создав конфигурационный файл репозитория /etc/yum.repos.d/nginx.repo со следующим содержимым:
[nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 enabled=1
Если вы используете CentOS 8, измените версию в URL.
Установите пакет веб-сервера Nginx с помощью менеджера пакетов yum (или dnf):
Теперь можно запустить nginx и добавить его в автозагрузку с помощью systemctl:
# systemctl start nginx# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
Чтобы проверить, что веб-сервер работает, откройте в браузере IP-адрес сервера.
Если у вас тестовая страница не открылась, проверьте настройки разрешенных служб, портов, зон в firewalld на своем сервере.
Настроим конфигурационный файл для отдельного домена build-centos.info. Создадим для сайта отдельную директорию и сам конфигурационный файл:
# mkdir -p /var/www/build-centos.info && mkdir -p /var/www/build-centos.info/log
# nano /etc/nginx/conf.d/build-centos.info.conf
И добавим в него следующее содержимое:
server { listen 80; server_name build-centos.info; root /var/www/build-centos.info; index index.php index.html index.htm; access_log /var/www/build-centos.info/log/access.log main; error_log /var/www/build-centos.info/log/error.log; location / { return 301 https://build-centos.info$request_uri; } location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ { return 301 https://build-centos.info$request_uri; } location ~ \.php$ { return 301 https://build-centos.info$request_uri; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { rewrite ^ /robots.txt break; allow all; log_not_found off; access_log off; } location ~ /\.ht { deny all; } } server { listen 80; server_name www.build-centos.info; rewrite ^ https://build-centos.info$request_uri? permanent; } server { listen 443 ssl http2; server_name build-centos.info; root /var/www/build-centos.info; index index.php index.html index.htm; access_log /var/www/build-centos.info/log/ssl-access.log main; error_log /var/www/build-centos.info/log/ssl-error.log; keepalive_timeout 60; ssl_certificate /etc/letsencrypt/live/build-centos.info/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/build-centos.info/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; add_header Strict-Transport-Security 'max-age=604800'; location / { try_files $uri $uri/ /index.php?$args; } location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ { access_log off; expires max; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param DOCUMENT_ROOT /var/www/build-centos.info; fastcgi_param SCRIPT_FILENAME /var/www/build-centos.info/$fastcgi_script_name; fastcgi_param PATH_TRANSLATED /var/www/build-centos.info/$fastcgi_script_name; include fastcgi_params; 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 HTTPS on; fastcgi_intercept_errors on; fastcgi_ignore_client_abort off; fastcgi_connect_timeout 60; fastcgi_send_timeout 180; fastcgi_read_timeout 180; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location ~ /\.ht { deny all; } } server { listen 443 ssl http2; server_name www.build-centos.info; rewrite ^ https://build-centos.info$request_uri? permanent; }
Конфигурационный файл содержит настройки для доступа по защищенному протоколу https, так как многие популярные CMS в данный момент по умолчанию работают через него. В дальнейшем мы установим и настроим бесплатный SSL сертификат Let’s Encrypt (по аналогии с установкой Let’s Encrypt сертификата на IIS сайта в Windows Server).
Установка php-fpm и дополнительных модулей php
В Nginx нет встроенного обработчика PHP, поэтому мы должны установить php-fpm и ряд модулей php, которые будут использоваться для обработки PHP скриптов.
Php-fpm это очень легкий и быстрый менеджер процессов PHP. Он не использует HTTP протокол (как apache), и работает со специальным протоколом FastCGI. За счет легковесности и простоты FPM позволяет намного быстрее обрабатывать PHP запросы. При этом, в сравнении с аналогичной конфигурацией с apache, памяти будет использоваться намного меньше.
Nginx в свою очередь дает существенный выигрыш при отдаче статики. В нашей конфигурации ngnix будет выступать прокси-сервером (кэширующим и front-end сервером), а в качестве бэкенда будет работать php-fpm.
Для установки свежих версий php, используем репозиторий REMI:
# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
После установки, отредактируйте файл /etc/yum.repos.d/remi-php74.repo:
Запустите установку php-fpm и популярных модулей php:
# yum install php-fpm php-cli php-mysql php-gd php-ldap php-odbc php-pdo php-opcache php-pear php-xml php-xmlrpc php-mbstring php-snmp php-soap php-zip
Запустите сервис php-fpm и добавитье его в автозагрузку:
# systemctl start php-fpm# systemctl enable php-fpm
Created symlink from /etc/systemd/system/multi-user.target.wants/php-fpm.service to /usr/lib/systemd/system/php-fpm.service.
Чтобы проверить, запустился ли сервис, можно выполнить команду:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME php-fpm 1551 root 7u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN) php-fpm 1552 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN) php-fpm 1553 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN) php-fpm 1554 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN) php-fpm 1555 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN) php-fpm 1556 apache 9u IPv4 2078435 0t0 TCP localhost:cslistener (LISTEN)
Сервис php-fpm нужно запустить через unix-сокет. В конфигурационном файле /etc/php-fpm.d/www.conf удалите строку listen = 127.0.0.1:9000 и добавьте:
listen = /var/run/php-fpm/php-fpm.sock listen.mode = 0660 listen.owner = nginx listen.group = nginx
Чтобы запускать php-fpm не от пользователя apache (по-умолчанию), укажите следующие параметры в конфигурационном файле:
user = nginx group = nginx
После изменения конфигурационного php-fpm нужно перезапустить сервис:
Установка Let’s Encrypt и подключение сертификата
Чтобы выпустить бесплатный сертификат Let’s Encrypt, нужно установить нужное certbot.
После запуска команды, вам нужно будет заполнить все данные, указав почтовый ящик, домен и так далее:
Saving debug log to /var/log/letsencrypt/letsencrypt.log How would you like to authenticate with the ACME CA? ------------------------------------------------------------------------------- 1: Spin up a temporary webserver (standalone) 2: Place files in webroot directory (webroot) ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1 Plugins selected: Authenticator standalone, Installer None Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): [email protected] Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org ------------------------------------------------------------------------------- Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf. You must agree in order to register with the ACME server at https://acme-v01.api.letsencrypt.org/directory ------------------------------------------------------------------------------- (A)gree/(C)ancel: A ------------------------------------------------------------------------------- Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about EFF and our work to encrypt the web, protect its users and defend digital rights. ------------------------------------------------------------------------------- (Y)es/(N)o: N Please enter in your domain name(s) (comma and/or space separated) (Enter 'c' to cancel): build-centos.info Obtaining a new certificate Performing the following challenges: tls-sni-01 challenge for build-centos.info Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/build-centos.info/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/build-centos.info/privkey.pem Your cert will expire on 2018-01-24. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.
Чтобы сертификат был корректно выпущен, ваш домен должен быть существующим и направлен на соответствующий веб-сервер.
После выпуска сертификата, выполните перезагрузку веб-сервера nginx и проверье результат.
Соединение в браузере защищено!
Для автоматического продление сертификатов измените конфигурационный файл /etc/letsencrypt/renewal/build-centos.info.conf следующим образом:
# renew_before_expiry = 30 daysversion = 0.18.1archive_dir = /etc/letsencrypt/archive/ build-centos.infocert = /etc/letsencrypt/live/build-centos.info/cert.pemprivkey = /etc/letsencrypt/live/build-centos.info/privkey.pemchain = /etc/letsencrypt/live/build-centos.info/chain.pemfullchain = /etc/letsencrypt/live/build-centos.info/fullchain.pem
# Options used in the renewal process[renewalparams]authenticator = webrootinstaller = Noneaccount = e9c86e6aa57b45f9614bc7c0015927a5post_hook = nginx -s reload[[webroot_map]]www.build-centos.info = /var/www/build-centos.infobuild-centos.info = /var/www/build-centos.info
После изменения файла, добавьте в крон задание:
30 2 * * * root /usr/bin/certbot renew --post-hook "nginx -s reload"
Чтобы проверить, что nginx работает с php, я создал файл index.php и добавил в него:
Установка MySQL/MariaDB на веб сервере
Данный шаг мы полностью пропустим, так как на сайте уже есть статья по установке и тюнингу MariaDB. Воспользуйтесь ей.
Настройка Nginx и PHP-FPM для высоконагруженных проектов
Чтобы ваш веб-сервер работал с высокой производительностью и мог обработать большое количество запросов от клиентов, одного железа недостаточно. Важно правильно настроить работу связки nginx и php-fpm.
Настройка nginx
Откройте файл /etc/nginx/nginx.conf и изменит конфигурацию Nginx следующим образом:
worker_processes 2;
— уставите количество рабочих процессов равным количеству ядер на сервере.worker_connections 1024;
— определяет количество соединений одного рабочего процесса. Выставляйте значения от 1024 до 4096.use epoll;
— оптимальный вариант метода соединений для Linux.multi_accept on;
— nginx будет принимать максимальное количество соединений.
Для проектов в которых содержится большое количество статических файлов, обязательно включайте gzip сжатие:
Добавьте большое количество типов файлов, чтобы все проверки на googlespeed проходили:gzip_types application/atom+xml application/javascript text/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json font/ttf application/x-font-ttf application/vnd.ms-fontobject application/font-woff application/font-woff2 application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vnd.wap.wml text/vtt text/x-component text/x-cross-domain-policy;
Настройка сжатия позволит ускорить ваш проект.
keepalive_timeout 30;
— веб-сервер будет ожидать 30 секунд, прежде чем закрыть keepalive соединенияkeepalive_requests 100;
— максимальное количество keepalive запросов от одного клиентаreset_timedout_connection on;
— включите данный параметр, если не хотите, чтобы соединение от клиента, который перестал отвечать, сбрасывались.client_body_timeout 10;
— веб-сервер будет ждать 10 секунд подтверждение запроса от клиента, по истечению этого времени, соединение сбросится.send_timeout 2;
— если клиент прекращает чтение ответа от веб-сервера, nginx сбросит соединение с ним.
Если на вашем сайте не предусмотрена загрузка больших файлов, ограничьте это с помощью nginx:
Если контент на вашем проекте меняется не так часто, вы можете использовать кеширование «expires max;» Либо добавьте соответствующую опцию в конфигурационный файл вашего хоста для нужного типа файлов, например:
location ~* ^.+.(js|css|png|jpg|jpeg|gif|ico|woff)$ {expires 7d;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Кеш для указанных типов файлов будет хранится 7 дней. Вы можете управлять кешем с помощью данной функции. После всех модификаций, не забывайте выполнять перезапуск nginx:
Настройка php-fpm
При установке php-fpm вы сразу перевели его на unix-сокет. Это дает существенных прирост в производительности. По оценкам производительность вырастает в 2-3 раза. Остальные же параметры php-fpm нужно настраивать под каждый проект отдельно, рассмотрим пример настройки для сервера с 1024 Мб памяти.
Для php-fpm мы можем выделить примерно 512 мб, оставив остальное под БД и nginx.
В конфигурационный файл /etc/php-fpm/www.conf, добавим:
pm.max_children = 18
— максимальное число дочерних процессовpm.start_servers = 6
— число дочерних процессов, создаваемых при запускеpm.min_spare_servers = 4
— минимальное число неактивных процессов сервераpm.max_spare_servers = 16
— максимальное число неактивных процессов сервераpm.max_requests = 400
— число запросов дочернего процесса, после которого процесс будет перезапущен.
Все параметры нужно изменять при анализе нагрузки на ваш проект, данные значения теоретические.
На текущий сервер я сразу же установил последнюю версию CMS Bitrix, для проверки производительности. На мой взгляд это самая ресурсоемкая CMS и результаты получились неплохие, если учитывать, что это виртуальная машина на KVM с одним ядром (vCPU) и 1024 ОЗУ:
Оптимизацию настроек MariaDB я не расписывал, так как есть соответствующая статья на сайте. Я сформировал параметры для my.cnf по статье и база показала отличный результат.
При запуске сайте вы заметите невооруженным взглядом, что nginx + php-fpm будет намного быстрее обрабатывать ваши запросы и возвращать страницы, чем apache2 + mod_php. Если у вас есть возможность провести нагрузочные тесты во время настройки сервера, то это несомненно будет плюсом, если же такой возможности нет, вы можете изменить параметры для своих ресурсов исходя из нашего мануала.