Очередная статья по настройке LNMP (Linux Nginx MySQL PHP). Собрал по-кусочкам из многих источников. Выкладываю тут, может кому понадобится.
Действие происходит на Fedora 31 Server. С небольшими правками должно работать и на RedHat/CentOS/Oracle Linux.
1. Начнём с плохого совета - отключаем
2. Устанавливаем основной софт
Ставим nginx, PHP, MariaDB (заменяет MySQL) и certbot для получения сертификатов Let's Encrypt.
3. Устанавливаем модули для PHP
Список модулей может сильно варьироваться в зависимости от нужд. Перечисленные необходимы для работы популярных скриптов/движков (phpmyadmin, phpbb, mybb, drupal, joomla, wordpress), поэтому пока ставим только их.
4. Создаём пользователя и настраиваем права
Безопасности ради, Nginx и PHP работают под отдельным пользователем. В примере использую www:www
5. Включаем автостарт и запускаем службы
6. Настраиваем учётки у MariaDB
7. Настраиваем PHP
7.1. Фиксим баги:
Добавляем/раскомментируем строку (потенциально фиксит уязвимости - подробнее описано в комментариях к функции):
7.2. Настройки PHP-FPM listener:
Тут нужно быть внимательным - параметры listen.acl_users и listen.acl_groups более приоритетны, чем listen.owner и listen.group, поэтому оставляем что-то одно, чтобы не было путаницы.
8. Настраиваем nginx
Рекомендую просто скопировать nginx.conf и настраивать уже его под свои нужны:
Hint. Чтобы заменить домен на свой, можно сделать так:
9. Настройка HTTPS
Сертификат получать будем от
В зависимости от используемого DNS, потребуется поставить соответствующий плагин:
Я использую cloudflare, поэтому ставим его:
Получаем сертификат:
Для проверки SSL, можно использовать сайт
Исправляем потерциальные ошибки:
1. Не запускается nginx
* Проверить конфиг:
* Проверить логи службы:
2. nginx и PHP запущены, но даже самые простые скрипты не работают
* Проверить, под какими пользователями запущены службы:
Все процессы, кроме 'nginx: master process', который работает от root'a, должны быть запущены от нашего пользователя (www:www).
Пример:
* Проверить права на файл сокетов:
Пример:
3. Простые скрипты работают, а сложные не запускаются, либо выдают ошибки:
Смотреть логи nginx. Подсказка, скорее всего, будет там:
Например, если мы видим ошибку
то стоит поискать недостающий модуль:
При копировании/репостинге ссылка на оригинал (
EOF
Действие происходит на Fedora 31 Server. С небольшими правками должно работать и на RedHat/CentOS/Oracle Linux.
1. Начнём с плохого совета - отключаем
Ссылка скрыта от гостей
. В идеале его нужно было-бы правильно настроить, но я с ним никогда не дружил.
Bash:
sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
2. Устанавливаем основной софт
Ставим nginx, PHP, MariaDB (заменяет MySQL) и certbot для получения сертификатов Let's Encrypt.
Bash:
dnf install -y nginx php-fpm mariadb-server certbot certbot-nginx
3. Устанавливаем модули для PHP
Список модулей может сильно варьироваться в зависимости от нужд. Перечисленные необходимы для работы популярных скриптов/движков (phpmyadmin, phpbb, mybb, drupal, joomla, wordpress), поэтому пока ставим только их.
Bash:
dnf install -y php-mbstring php-mysqlnd php-xml php-json php-gd php-opcache
4. Создаём пользователя и настраиваем права
Безопасности ради, Nginx и PHP работают под отдельным пользователем. В примере использую www:www
Bash:
useradd -M -U -s $(which nologin) www
mkdir /www
chown -R www:www /var/lib/nginx /var/lib/php /www
5. Включаем автостарт и запускаем службы
Bash:
systemctl enable --now nginx mariadb php-fpm
6. Настраиваем учётки у MariaDB
Bash:
mysql_secure_installation
7. Настраиваем PHP
7.1. Фиксим баги:
Bash:
vi /etc/php.ini
Код:
cgi.fix_pathinfo=0
7.2. Настройки PHP-FPM listener:
Bash:
vi /etc/php-fpm.d/www.conf
Код:
user = www
group = www
listen = /run/php-fpm/www.sock
listen.owner = www
listen.group = www
# ИЛИ
;listen.acl_users = www
;listen.acl_groups = www
8. Настраиваем nginx
Рекомендую просто скопировать nginx.conf и настраивать уже его под свои нужны:
Код:
user www www;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
#tcp_nopush on;
keepalive_timeout 30;
gzip off;
server_tokens off;
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# Deny requests to server by IP
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
# HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# Main http root
location / {
root /www;
index index.php index.html index.htm;
autoindex off;
}
# Block access to .ht* files
location ~ /\.ht {
deny all;
}
# Pass PHP scripts to php-fpm
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f /www/$fastcgi_script_name) {
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
# include the fastcgi_param setting
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /www/$fastcgi_script_name;
}
# SSL configuration
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;
# OCSP Stapling
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
resolver 1.1.1.1 1.0.0.1;
}
}
Hint. Чтобы заменить домен на свой, можно сделать так:
Bash:
sed -i 's/example.com/mydomain.com/g' /etc/nginx/nginx.conf
9. Настройка HTTPS
Сертификат получать будем от
Ссылка скрыта от гостей
В зависимости от используемого DNS, потребуется поставить соответствующий плагин:
Код:
python3-certbot-dns-ovh
python3-certbot-dns-nsone
python3-certbot-dns-gehirn
python3-certbot-dns-google
python3-certbot-dns-linode
python3-certbot-dns-luadns
python3-certbot-dns-rfc2136
python3-certbot-dns-route53
python3-certbot-dns-cloudxns
python3-certbot-dns-dnsimple
python3-certbot-dns-cloudflare
python3-certbot-dns-dnsmadeeasy
python3-certbot-dns-sakuracloud
python3-certbot-dns-digitalocean
Я использую cloudflare, поэтому ставим его:
Bash:
dnf install -y python3-certbot-dns-cloudflare
Получаем сертификат:
Bash:
certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d example.com
Для проверки SSL, можно использовать сайт
Ссылка скрыта от гостей
Там-же есть полезные советы по настройке.Исправляем потерциальные ошибки:
1. Не запускается nginx
* Проверить конфиг:
Bash:
nginx -t
Bash:
systemctl status nginx.service
journalctl -xe
2. nginx и PHP запущены, но даже самые простые скрипты не работают
* Проверить, под какими пользователями запущены службы:
Bash:
ps -ef | grep -e nginx -e php-fpm
Пример:
Код:
root 11246 1 0 13:39 ? 00:00:00 php-fpm: master process (/etc/php-fpm.conf)
www 11247 11246 0 13:39 ? 00:00:01 php-fpm: pool www
www 11248 11246 0 13:39 ? 00:00:02 php-fpm: pool www
www 11249 11246 0 13:39 ? 00:00:01 php-fpm: pool www
www 11250 11246 0 13:39 ? 00:00:01 php-fpm: pool www
www 11251 11246 0 13:39 ? 00:00:02 php-fpm: pool www
www 11254 11246 0 13:42 ? 00:00:00 php-fpm: pool www
root 11755 1 0 15:33 ? 00:00:00 nginx: master process /usr/sbin/nginx
www 11756 11755 0 15:33 ? 00:00:00 nginx: worker process
* Проверить права на файл сокетов:
Bash:
ls -la /run/php-fpm/www.sock
Код:
srw-rw---- 1 www www 0 Jan 23 13:39 /run/php-fpm/www.sock
3. Простые скрипты работают, а сложные не запускаются, либо выдают ошибки:
Смотреть логи nginx. Подсказка, скорее всего, будет там:
Bash:
tail -f /var/log/nginx/error.log
Код:
2020/01/23 13:12:23 [error] 10670#0: *7 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: Class 'Locale' not found in /www/vanilla/applications/dashboard/controllers/api/LocalesApiController.php:103
Код:
# dnf search php- | grep -i locale
Last metadata expiration check: 0:29:20 ago on Thu 23 Jan 2020 12:44:39 PM EET.
php-symfony-locale.noarch : Symfony Locale Component
# dnf install php-symfony-locale
...
При копировании/репостинге ссылка на оригинал (
Ссылка скрыта от гостей
) обязательна.EOF