В статье собрано все самое важное по настройке веб-сервера. Для использования будут доступны сразу несколько версий PHP. Никакого Apache, только Nginx+php-fpm. Установка MySQL, phpMyAdmin и автоматически обновляемые SSL-сертификаты Let’s Encrypt.
Статья периодически обновляется, всё сказанное проверенно в Debian 10 buster. Дополнения в комментариях приветствуются.
PHP 5.*, 7.*, 8.*
Подключим источник, откуда можно установить в систему одновременно несколько версий PHP.
apt install ca-certificates apt-transport-https
wget -q https://packages.sury.org/php/apt.gpg -O- | apt-key add -
echo "deb https://packages.sury.org/php/ buster main" | tee /etc/apt/sources.list.d/php.list
apt update
Следующие команды — установка соответствующих версий PHP. Можно установить только нужное.
apt install php5.6-fpm php5.6-cli php5.6-common php5.6-curl php5.6-mbstring php5.6-mysql php5.6-xml php5.6-gd php5.6-zip php5.6-bcmath
apt install php7.4-fpm php7.4-cli php7.4-common php7.4-curl php7.4-mbstring php7.4-mysql php7.4-xml php7.4-gd php7.4-zip php7.4-bcmath
apt install php8.2-fpm php8.2-cli php8.2-common php8.2-curl php8.2-mbstring php8.2-mysql php8.2-xml php8.2-gd php8.2-zip php8.2-bcmath
Установка специально с указанием конкретных компонентов, чтобы не ставить Apache.
Конфиги располагаются здесь /etc/php/версия/fpm/php.ini
.
После их настройки перезагрузка, соответственно:
service php5.6-fpm reload
service php7.4-fpm reload
service php8.2-fpm reload
Nginx
Установка:
apt install nginx
Простой пример конфига для сайта:
server {
listen 80;
listen [::]:80;
server_name pctuner.club;
root /var/www/pctuner.club;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Используем PHP нужной версии.
# fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
}
access_log /var/log/nginx/pctuner_access.log;
error_log /var/log/nginx/pctuner_error.log;
}
Конфиг записывается в файл с произвольным именем, но в определенный каталог, например /etc/nginx/sites-available/pctuner.club
. После этого его необходимо активировать и перезагрузить Nginx:
ln -s /etc/nginx/sites-available/pctuner.club /etc/nginx/sites-enabled/pctuner.club
service nginx reload
Когда вносятся изменения в конфиг работающего сайта, то, чтобы избежать неудачного перезапуска Nginx и остановки работы сайта, полезно вначале выполнить тестирование:
nginx -t
HTTPS
Использовать будем Let’s Encrypt. Бесплатные SSL-сертификаты и автоматическое обновление, что еще надо? Достаточно один раз настроить и можно забыть.
Установка необходимого:
apt install certbot python-certbot-nginx
Регистрация в Let’s Encrypt, для нового сервера это нужно сделать лишь один раз:
certbot register --email ваша@эл.почта
Конфиг /etc/letsencrypt/cli.ini
:
authenticator = webroot
webroot-path = /var/www/letsencrypt
post-hook = service nginx reload
text = True
Каталог /var/www/letsencrypt
необходимо создать.
Чтобы с правами доступа точно все было в порядке:
chown -R www-data /var/www/letsencrypt && chmod -R 750 /var/www/letsencrypt
Для удобства настройки Nginx создадим пару файлов. Будем их подключать потом в нужных местах конфигов, чтобы не писать одно и тоже сто раз. Первый /etc/nginx/inc_letsencrypt
— необходим для обновления SSL-сертификатов:
location ~ /.well-known {
location ~ /.well-known/acme-challenge/(.*) {
auth_basic off;
default_type "text/plain";
root /var/www/letsencrypt;
}
}
Второй — /etc/nginx/inc_ssl_pctuner
— включает все необходимое для работы https на доменах сайта pctuner.club:
ssl on;
ssl_certificate /etc/letsencrypt/live/pctuner.club/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pctuner.club/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_dhparam /etc/letsencrypt/live/pctuner.club/dh.pem;
ssl_protocols TLSv1.2;
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;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/pctuner.club/chain.pem;
resolver 8.8.8.8;
Почитать подробнее про задействованные параметры можно здесь. Правда там на немецком, но онлайн-переводчик в помощь, это самая толковая инструкция, что удалось найти в свое время.
Немного расширенный конфиг сайта /etc/nginx/sites-available/pctuner.club
:
# Вспомогательный блок.
server {
listen 80;
listen [::]:80;
server_name pctuner.club www.pctuner.club pctuner.ru www.pctuner.ru;
# Для обновления сертификатов.
include inc_letsencrypt;
# Редирект с http на https.
location / {
return 301 https://pctuner.club$request_uri;
}
}
# Блок для редиректа с дополнительных доменов.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.pctuner.club pctuner.ru www.pctuner.ru;
# Подключаем все необходимое для ssl.
include inc_ssl_pctuner;
# Редирект на основной домен.
return 301 https://pctuner.club$request_uri;
}
# Основной блок.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name pctuner.club;
# Подключаем все необходимое для ssl.
include inc_ssl_pctuner;
root /var/www/pctuner.club/;
index index.php;
add_header X-Frame-Options "SAMEORIGIN";
add_header x-xss-protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Используем PHP нужной версии.
# fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
}
access_log /var/log/nginx/pctuner_access.log;
error_log /var/log/nginx/pctuner_error.log;
}
Изначально нужные сертификаты (файлы) отсутствуют, поэтому Nginx не примет конфиг в таком виде. До того момента пока сертификаты не будут получены необходимо закоментировать подключение файла inc_ssl_pctuner
:
# include inc_ssl_pctuner;
Пример теста получения сертификата:
certbot certonly --dry-run -d pctuner.club -d www.pctuner.club
Один сертификат будет на 2 домена.
В одном сертификате имеет смысл объединять все домены, имеющие отношение к одному и тому же сайту. Больше доменов добавляются аналогично:
certbot certonly --dry-run -d pctuner.club -d www.pctuner.club -d pctuner.ru -d www.pctuner.ru
Здесь параметр --dry-run
отвечает за запуск в тестовом режиме. Это позволяет убедиться, что с настройкой сервера все хорошо и сертификат точно будет получен.
Дело в том, что есть ограничение на количество полученных сертификатов за некий промежуток времени, поэтому обязательно вначале делайте тестирование. Если все в порядке, достаточно убрать этот параметр, и тогда сертификат будет получен уже реально.
В случае успешного теста будет ответ:
- The dry run was successful.
Кроме сертификата необходимо сгенерировать ключ:
openssl dhparam -outform PEM -out /etc/letsencrypt/live/pctuner.club/dh.pem 2048
На этом все. Включаем обратно подключение файла inc_ssl_pctuner
в конфиге и перезапускаем Nginx.
В будущем если потребуется добавить в сертификат еще один домен, то просто используем выше приведенную команду, указав в ней все нужные домены, в том числе старые и новые, программа сама разберется, что с этим делать.
Для автоматического обновления сертификатов в будущем ничего делать не нужно, файл /etc/cron.d/certbot
с необходимыми для этого настройками уже был создан. Программа автоматически запускается дважды в сутки. Она видит полученные сертификаты всех сайтов на сервере, при необходимости обновляет их.
Можно протестировать процесс обновления, без получения реальных сертификатов:
certbot renew --dry-run
Basic-auth
Это простой способ организовать доступ по логину и паролю к какому-то каталогу или всему сайту. Он имеет свои изъяны, информацию можно найти в интернете. Поэтому не стоит его использовать, как единственную защиту. Ну и, конечно, HTTPS — обязателен.
Для генерации файлов с логином и паролем установим:
apt install apache2-utils
Генерация:
htpasswd -c /etc/nginx/my_auth логин_для_доступа
В процессе будет запрошен пароль.
Пример подключения файла в конфиге Nginx для всего сайта:
...
auth_basic "closed site";
auth_basic_user_file my_auth;
...
MySQL
Не знаю куда делся MySQL из штатного репозитория Debian 10, поэтому ставим следующим образом. Актуальную версию установочного файла можно посмотреть здесь.
cd /tmp
wget https://dev.mysql.com/get/mysql-apt-config_0.8.16-1_all.deb
dpkg -i mysql-apt-config_0.8.16-1_all.deb
Будет предложен выбор версии MySQL. Выберите 8.0 или 5.7.
Теперь можно продолжить:
apt update
apt install mysql-server
В процессе, если сможете, задайте пароль для root базы.
У меня не получилось, я оставил поле пароля пустым и далее сделал так:
mysql
В самом MySQL:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'здесь_свой_пароль';
FLUSH PRIVILEGES;
exit
Настройки безопасности:
mysql_secure_installation
На следующие вопросы важно ответить положительно:
Remove anonymous users? : y
Disallow root login remotely? : y
Remove test database and access to it? : y
Reload privilege tables now? : y
Настройки MySQL обычно в /etc/mysql/mysql.conf.d/mysqld.cnf
и /etc/mysql/my.cnf
.
В секцию [mysqld]
стоит добавить параметры:
# Настройка блокирует все подключения к MySQL, кроме подключений с локальной машины.
bind-address = 127.0.0.1
# Отключение функции, позволяющей получить доступ к файловой системе из MySQL.
# MySQL не будет загружать локальные файлы для пользователей без соответствующего уровня доступа.
local-infile = 0
# Отключение обработки символических ссылок, тоже в целях безопасности.
symbolic-links = 0
# Раскоментируйте, если на сервере мало памяти.
# performance_schema = off
Проверка настроек MySQL:
/usr/sbin/mysqld --help --verbose --skip-networking 1>/dev/null
Если ответ пустой, то всё хорошо. Полезно проверять после внесения изменений в конфиг, чтобы избежать ошибки перезапуска.
Перезапуск MySQL:
service mysql restart
MySQL должен проработать непрерывно хотя бы пару дней. Должна накопиться статистика именно по вашей базе, нагрузке и т.д. После этого можно запустить mysqltuner.pl и посмотреть его рекомендации:
wget http://mysqltuner.pl/ -O mysqltuner.pl
perl ./mysqltuner.pl
Чтобы работать на сервере с MySQL и не вводить каждый раз пароль, удобно создать файл ~/.my.cnf
, в котором прописать необходимое:
[mysql]
user = пользователь
password = пароль
[mysqldump]
user = пользователь
password = пароль
Установка прав доступа на файл:
chmod 0600 ~/.my.cnf
phpMyAdmin
Установим Сomposer. Он всегда может пригодиться.
cd /usr/src
apt install curl
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
И конкретно сейчас он будет нужен для установки новейшего phpMyAdmin.
Лучше создать отдельный сайт для использования подобного рода утилит, что-то вроде dev.pctuner.club
. Выше вся информация есть. Конечно это должен быть HTTPS-сайт, плюс можно добавить дополнительную защиту в виде basic-auth.
Переходим в подготовленный каталог сайта и запускаем установку:
cd /var/www/dev.pctuner.club
composer create-project phpmyadmin/phpmyadmin --repository-url=https://www.phpmyadmin.net/packages.json --no-dev
Он установится по пути /var/www/dev.pctuner.club/phpmyadmin
и можно уже обращаться к нему соответствующим образом.
При авторизации внизу будет сообщение:
Хранилище конфигурации phpMyAdmin не полностью настроено, некоторые расширенные функции были отключены. Узнайте причину.
Или перейдите на вкладку 'Операции' любой базы данных, чтобы настроить хранилище в ней.
Ничего страшного. Просто нужно создать базу, в которую phpMyAdmin будет сохранять свои настройки. Следуем по ссылке «Узнайте причину». И там нажимаем ссылку «Создать».
Еще одно уведомление внизу:
В конфигурационном файле необходимо задать парольную фразу (blowfish_secret).
Создаем файл конфигурации из файла-примера (копируем):
cp /var/www/dev.pctuner.club/phpmyadmin/config.sample.inc.php /var/www/dev.pctuner.club/phpmyadmin/config.inc.php
В файле редактируем параметр:
$cfg['blowfish_secret'] = 'nf4eDr5uFf6n7GfH......';
В качестве значения вписываете любые свои символы, порядка 40 знаков.
Теперь phpMyAdmin готов к полноценному использованию.
Настройка локали
Просмотр установленных локалей:
locale -a
Мастер настройки:
dpkg-reconfigure locales
Сначала вы можете выбрать необходимые локали. У меня все необходимое уже было, поэтому на первом шаге я оставил все без изменений. На втром шаге можно выбрать локаль по умолчанию.
Сервер необходимо перезапустить, чтобы увидеть изменения в действии.
Что еще?
Выполнена лишь базовая настройка. Сайты на таком веб-сервере будут работать, но для лучшего результата необходимо выполнить оптимизацию. Настроить кэширование. Также рекомендую обратить внимание на некоторые другие настройки:
- Обязательно настройте Logrotate.
- По желанию: отправку почты, синхронизацию времени, часовой пояс, sudo.