LEMP-стек (Linux, Nginx, MySQL, PHP) является одним из самых популярных и эффективных решений для разработки и развертывания современных веб-приложений. В отличие от классического LAMP-стека, использующего Apache, LEMP использует более легкий и производительный веб-сервер Nginx, что делает его идеальным выбором для высоконагруженных проектов.
В этой статье я поделюсь полным пошаговым руководством по настройке LEMP-стека от чистой установки Linux до полностью готовой к production среды. Мы уделим особое внимание безопасности, производительности и отказоустойчивости — ключевым аспектам любой production-системы.
Настройка production-сервера — это не просто установка компонентов по умолчанию, а тщательно спланированный процесс, учитывающий особенности проекта, ожидаемую нагрузку и требования к безопасности. Инвестиция времени в правильную настройку окупится многократно в будущем.
Данное руководство ориентировано на Ubuntu 22.04 LTS, но большинство команд и принципов применимы и к другим современным дистрибутивам Linux. Для максимальной эффективности рекомендую выполнять каждый шаг последовательно, так как многие настройки взаимосвязаны.
1. Подготовка сервера
Правильная подготовка сервера закладывает фундамент для стабильной и безопасной работы всего LEMP-стека. Начнем с базовой настройки свежеустановленной системы Ubuntu 22.04 LTS.
Обновление системы
Первым делом необходимо обновить все пакеты системы до последних версий:
# Обновление списка пакетов sudo apt update # Установка обновлений sudo apt upgrade -y # Перезагрузка сервера при необходимости sudo reboot
Настройка имени хоста и часового пояса
Установим правильное имя хоста и настроим часовой пояс:
# Установка имени хоста sudo hostnamectl set-hostname your-server-name # Настройка часового пояса sudo timedatectl set-timezone Europe/Moscow # Замените на ваш часовой пояс # Проверка настроек времени timedatectl
Создание непривилегированного пользователя
Для повышения безопасности создадим отдельного пользователя с правами sudo:
# Создание нового пользователя sudo adduser webadmin # Добавление пользователя в группу sudo sudo usermod -aG sudo webadmin # Проверка доступа su - webadmin sudo whoami # Должно вернуть "root"
Совет
Для дополнительной безопасности настройте аутентификацию по SSH-ключам вместо паролей. Это значительно снижает риск несанкционированного доступа к вашему серверу.
# На локальном компьютере (если ключа еще нет) ssh-keygen -t ed25519 -C "ваш_email@example.com" # Копирование публичного ключа на сервер ssh-copy-id webadmin@your_server_ip # На сервере - отключение парольной аутентификации sudo nano /etc/ssh/sshd_config # Установите следующие параметры: # PasswordAuthentication no # PubkeyAuthentication yes # PermitRootLogin no # Перезапуск SSH-сервера sudo systemctl restart sshd
Настройка брандмауэра
Установим и настроим UFW (Uncomplicated Firewall) для контроля сетевого доступа:
# Установка UFW, если он еще не установлен sudo apt install ufw # Настройка базовых правил sudo ufw default deny incoming sudo ufw default allow outgoing # Разрешение SSH для предотвращения потери доступа sudo ufw allow ssh # Разрешение веб-трафика sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Включение брандмауэра sudo ufw enable # Проверка статуса sudo ufw status verbose
Настройка swap-файла
Для серверов с ограниченным объемом RAM полезно настроить swap-пространство:
# Проверка текущего swap sudo swapon --show # Создание swap-файла (2GB в данном примере) sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # Настройка автоматического монтирования при загрузке echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab # Настройка оптимальных параметров использования swap sudo sysctl vm.swappiness=10 sudo sysctl vm.vfs_cache_pressure=50 # Для сохранения настроек при перезагрузке echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf echo 'vm.vfs_cache_pressure=50' | sudo tee -a /etc/sysctl.conf
Важно!
На виртуальных серверах с SSD-дисками вместо fallocate рекомендуется использовать dd для создания swap-файла, чтобы избежать проблем с разреженными файлами:
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
Установка базовых инструментов мониторинга
Установим необходимые утилиты для наблюдения за работой сервера:
# Установка базовых инструментов sudo apt install -y htop iotop iftop ncdu net-tools dnsutils curl wget unzip
2. Установка и настройка Nginx
Nginx — высокопроизводительный веб-сервер, обратный прокси-сервер и балансировщик нагрузки. Его асинхронная архитектура делает его более эффективным при обработке множества одновременных соединений по сравнению с Apache.
Установка Nginx из официального репозитория
Для получения наиболее свежих версий установим Nginx из официального репозитория:
# Добавление официального репозитория Nginx sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null # Добавление стабильного репозитория echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list # Обновление списка пакетов и установка Nginx sudo apt update sudo apt install -y nginx # Запуск Nginx и включение автозапуска sudo systemctl start nginx sudo systemctl enable nginx # Проверка статуса sudo systemctl status nginx
Базовая конфигурация Nginx
Настроим основной конфигурационный файл Nginx с оптимальными параметрами для production:
# Создание резервной копии конфигурации sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup # Редактирование основной конфигурации sudo nano /etc/nginx/nginx.conf
Заменим содержимое файла на следующую оптимизированную конфигурацию:
user nginx;
worker_processes auto;
pid /var/run/nginx.pid;
# Оптимизация количества одновременных подключений на рабочий процесс
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
# Основные настройки
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# Размер буфера и таймауты
client_max_body_size 100M;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# Буферизация
client_body_buffer_size 10K;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
# Включаем сжатие для экономии трафика
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
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/vtt
text/x-component
text/x-cross-domain-policy;
# Кеш открытых файловых дескрипторов
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors on;
# Логирование
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# MIME-типы
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Включение виртуальных хостов
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Проверка конфигурации и перезапуск Nginx
После внесения изменений важно проверить конфигурацию на наличие ошибок перед перезапуском:
# Проверка синтаксиса конфигурации sudo nginx -t # Если ошибок нет, перезапускаем Nginx sudo systemctl restart nginx
Создание структуры каталогов для сайтов
Подготовим структуру каталогов для наших будущих сайтов:
# Создание основного каталога для веб-сайтов
sudo mkdir -p /var/www/sites
# Создание каталога для стандартного сайта
sudo mkdir -p /var/www/sites/default/public
# Установка корректных прав доступа
sudo chown -R nginx:nginx /var/www/sites
sudo chmod -R 755 /var/www/sites
# Создание тестовой страницы
echo '<!DOCTYPE html>
<html>
<head>
<title>Welcome to LEMP Stack</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
line-height: 1.6;
}
h1 {
color: #336699;
}
</style>
</head>
<body>
<h1>Welcome to your LEMP Stack</h1>
<p>If you see this page, Nginx is successfully installed and working.</p>
<p>This is the default test page.</p>
<p>Server time: <?php echo date("Y-m-d H:i:s"); ?></p>
<p>PHP Version: <?php echo phpversion(); ?></p>
</body>
</html>' | sudo tee /var/www/sites/default/public/index.php
Настройка базового виртуального хоста
Создадим базовую конфигурацию виртуального хоста:
# Создание конфигурационного файла sudo nano /etc/nginx/conf.d/default.conf
Содержимое базового конфигурационного файла:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/sites/default/public;
index index.php index.html index.htm;
# Логи для данного виртуального хоста
access_log /var/log/nginx/default.access.log;
error_log /var/log/nginx/default.error.log;
# Настройка для статических файлов
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# Основная обработка PHP
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock; # Будет настроено позже
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
# Защита от доступа к скрытым файлам
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Обработка основных запросов
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Совет
Эта базовая конфигурация будет служить шаблоном для всех ваших сайтов. На данном этапе она не будет полностью работать, так как мы еще не настроили PHP-FPM. Но создание структуры конфигурации сейчас поможет нам избежать проблем в дальнейшем.
Проверим конфигурацию и перезапустим Nginx:
sudo nginx -t sudo systemctl restart nginx
3. Установка и защита MySQL
MySQL — одна из самых популярных реляционных систем управления базами данных. Она обеспечивает надежное хранение данных для ваших веб-приложений и отлично интегрируется с PHP.
Установка MySQL
Установим MySQL Server из стандартных репозиториев:
# Установка MySQL sudo apt install -y mysql-server # Проверка статуса сервиса sudo systemctl status mysql # Включение автозапуска sudo systemctl enable mysql
Безопасная настройка MySQL
Запустим скрипт безопасной настройки для удаления тестовых баз данных, анонимных пользователей и настройки безопасного доступа:
# Запуск мастера безопасной настройки sudo mysql_secure_installation
При запуске скрипта вам будет предложено выполнить следующие шаги:
- Настроить компонент проверки надежности паролей (рекомендуется выбрать политику STRONG)
- Установить надежный пароль для пользователя root
- Удалить анонимных пользователей (рекомендуется выбрать "Да")
- Запретить удаленный вход для пользователя root (рекомендуется выбрать "Да")
- Удалить тестовую базу данных (рекомендуется выбрать "Да")
- Перезагрузить таблицы привилегий (рекомендуется выбрать "Да")
Оптимизация конфигурации MySQL
Теперь настроим основные параметры производительности MySQL. Создадим конфигурационный файл:
# Создание конфигурационного файла sudo nano /etc/mysql/conf.d/mysql-optimization.cnf
Содержимое файла оптимизации (параметры подходят для сервера с 4 ГБ RAM):
[mysqld] # Оптимизация производительности innodb_buffer_pool_size = 1G innodb_log_file_size = 256M innodb_flush_method = O_DIRECT innodb_flush_log_at_trx_commit = 2 query_cache_type = 1 query_cache_size = 64M query_cache_limit = 2M max_connections = 150 table_open_cache = 2000 tmp_table_size = 64M max_heap_table_size = 64M join_buffer_size = 4M read_buffer_size = 3M read_rnd_buffer_size = 4M sort_buffer_size = 4M # Оптимизация для InnoDB innodb_file_per_table = 1 innodb_buffer_pool_instances = 4 innodb_read_io_threads = 4 innodb_write_io_threads = 4 innodb_io_capacity = 1000 # Настройки журнала slow_query_log = 1 slow_query_log_file = /var/log/mysql/mysql-slow.log long_query_time = 2 log_queries_not_using_indexes = 1 log_error = /var/log/mysql/error.log # Безопасность max_allowed_packet = 16M symbolic-links = 0 local_infile = 0
Важно!
Параметры MySQL сильно зависят от доступных ресурсов сервера и характера нагрузки. Указанные значения подойдут для стандартных веб-приложений на сервере с 4 ГБ RAM. Для высоконагруженных проектов или серверов с другими характеристиками необходима дополнительная настройка.
Применим настройки, перезапустив MySQL:
sudo systemctl restart mysql
Создание пользователя и базы данных для приложения
Вместо использования пользователя root, создадим отдельного пользователя для работы с базой данных:
# Подключение к MySQL sudo mysql # В командной строке MySQL выполним: CREATE DATABASE example_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # Создание пользователя с доступом только с localhost CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'StrongPassword123!'; # Предоставление привилегий пользователю только для созданной базы данных GRANT ALL PRIVILEGES ON example_db.* TO 'example_user'@'localhost'; # Применение изменений FLUSH PRIVILEGES; # Выход из MySQL EXIT;
Совет
Используйте уникальные, случайно генерируемые пароли для каждой базы данных. Для их генерации можете использовать команду:
openssl rand -base64 24
Настройка мониторинга производительности
Для отслеживания производительности MySQL установим инструмент MySQLTuner:
# Скачивание MySQLTuner sudo mkdir -p /opt/mysql-tools cd /opt/mysql-tools sudo wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl sudo chmod +x mysqltuner.pl # Создание символической ссылки для удобства использования sudo ln -s /opt/mysql-tools/mysqltuner.pl /usr/local/bin/mysqltuner # Проверка и получение рекомендаций (запускать после нескольких дней работы) # sudo mysqltuner
4. Установка и оптимизация PHP-FPM
PHP-FPM (FastCGI Process Manager) — это альтернативная реализация PHP FastCGI с дополнительными возможностями, полезными для высоконагруженных сайтов. В отличие от mod_php для Apache, PHP-FPM работает как отдельный процесс и хорошо интегрируется с Nginx.
Установка PHP-FPM и необходимых модулей
Установим PHP 8.1 и основные модули, необходимые для большинства веб-приложений:
# Установка PHP-FPM и основных модулей sudo apt install -y php8.1-fpm php8.1-mysql php8.1-curl php8.1-gd php8.1-intl php8.1-mbstring php8.1-xml php8.1-zip php8.1-bcmath php8.1-cli # При необходимости можно установить дополнительные модули sudo apt install -y php8.1-soap php8.1-ldap php8.1-imagick php8.1-redis php8.1-memcached # Проверка статуса службы sudo systemctl status php8.1-fpm # Включение автозапуска sudo systemctl enable php8.1-fpm
Оптимизация PHP-FPM
Настроим конфигурацию PHP-FPM для оптимальной производительности:
# Создание резервной копии конфигурации sudo cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/www.conf.backup # Редактирование конфигурации пула www sudo nano /etc/php/8.1/fpm/pool.d/www.conf
Отредактируйте следующие параметры в конфигурационном файле:
; Изменение пользователя и группы на nginx user = nginx group = nginx ; Использование Unix-сокета вместо TCP/IP для большей производительности listen = /run/php-fpm/php-fpm.sock listen.owner = nginx listen.group = nginx listen.mode = 0660 ; Настройка динамического управления процессами pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 ; Логирование slowlog = /var/log/php-fpm/www-slow.log request_slowlog_timeout = 10s php_admin_value[error_log] = /var/log/php-fpm/www-error.log php_admin_flag[log_errors] = on ; Ограничения ресурсов php_admin_value[memory_limit] = 256M php_admin_value[upload_max_filesize] = 50M php_admin_value[post_max_size] = 50M php_admin_value[max_execution_time] = 60 php_admin_value[max_input_time] = 60
Настройка PHP.ini
Оптимизируем основные настройки PHP для повышения безопасности и производительности:
# Создание резервной копии конфигурации sudo cp /etc/php/8.1/fpm/php.ini /etc/php/8.1/fpm/php.ini.backup # Редактирование конфигурационного файла sudo nano /etc/php/8.1/fpm/php.ini
Найдите и измените следующие параметры:
; Безопасность expose_php = Off display_errors = Off display_startup_errors = Off log_errors = On error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT error_log = /var/log/php/error.log ; Производительность realpath_cache_size = 4M realpath_cache_ttl = 600 opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 10000 opcache.revalidate_freq = 2 opcache.save_comments = 1 opcache.enable_file_override = 1 ; Сессии session.gc_maxlifetime = 1440 session.gc_probability = 1 session.gc_divisor = 1000 ; Дата и время date.timezone = Europe/Moscow
Создание необходимых директорий и настройка прав доступа
Создадим директории для сокета PHP-FPM и логов:
# Создание директорий sudo mkdir -p /run/php-fpm sudo mkdir -p /var/log/php-fpm sudo mkdir -p /var/log/php # Установка прав доступа sudo chown nginx:nginx /run/php-fpm sudo chown nginx:nginx /var/log/php-fpm sudo chown nginx:nginx /var/log/php
Перезапуск PHP-FPM и проверка работоспособности
Перезапустим службу PHP-FPM для применения всех настроек:
# Перезапуск PHP-FPM sudo systemctl restart php8.1-fpm # Проверка статуса sudo systemctl status php8.1-fpm # Проверка наличия сокета ls -la /run/php-fpm/
Совет
В production-среде рекомендуется создавать отдельные пулы PHP-FPM для каждого крупного веб-приложения. Это позволяет более гибко настраивать ресурсы и изолировать приложения друг от друга.
# Создание отдельного пула для приложения sudo cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/example-app.conf # Редактирование нового пула sudo nano /etc/php/8.1/fpm/pool.d/example-app.conf # Измените следующие параметры: # [www] -> [example-app] # listen = /run/php-fpm/example-app.sock
5. Настройка SSL/TLS с Let's Encrypt
Шифрование соединений с помощью SSL/TLS сертификатов стало стандартом безопасности для современных веб-сайтов. Let's Encrypt предоставляет бесплатные сертификаты с автоматическим обновлением.
Установка Certbot
Certbot — это клиент Let's Encrypt, который значительно упрощает получение и обновление сертификатов:
# Установка Certbot и плагина для Nginx sudo apt install -y certbot python3-certbot-nginx
Получение SSL-сертификата
Перед получением сертификата необходимо настроить DNS для вашего домена и убедиться, что он указывает на ваш сервер:
# Получение сертификата с автоматической настройкой Nginx sudo certbot --nginx -d example.com -d www.example.com # Или для ручной настройки (только получение сертификата) sudo certbot certonly --nginx -d example.com -d www.example.com
Во время выполнения команды вам потребуется:
- Ввести адрес электронной почты для уведомлений об истечении срока действия сертификата
- Принять условия использования
- Решить, хотите ли вы делиться своим адресом электронной почты с EFF
- Выбрать, следует ли перенаправлять HTTP на HTTPS (рекомендуется)
Ручная настройка Nginx для использования SSL
Если вы выбрали режим "certonly", вам потребуется вручную настроить Nginx:
# Создание или редактирование виртуального хоста sudo nano /etc/nginx/conf.d/example.com.conf
Пример конфигурации с SSL и перенаправлением с HTTP на HTTPS:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# Перенаправление на HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL-сертификаты
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# Настройки SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
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_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Настройки OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Заголовки безопасности
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
# Корневая директория сайта
root /var/www/sites/example.com/public;
index index.php index.html index.htm;
# Логи
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# Настройка для статических файлов
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# Обработка PHP
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
# Защита от доступа к скрытым файлам
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Основная обработка запросов
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Настройка автоматического обновления сертификатов
Certbot автоматически устанавливает задание cron для обновления сертификатов. Проверим его наличие и корректность:
# Проверка заданий cron для certbot systemctl list-timers | grep certbot # Ручная проверка процесса обновления (без фактического обновления) sudo certbot renew --dry-run
Важно!
Сертификаты Let's Encrypt действительны только 90 дней. Хотя Certbot настраивает автоматическое обновление, регулярно проверяйте его работоспособность, особенно после обновления операционной системы или Nginx.
Тестирование безопасности SSL-настроек
После настройки SSL рекомендуется проверить безопасность вашей конфигурации:
# Используйте онлайн-инструмент SSL Labs
# https://www.ssllabs.com/ssltest/analyze.html?d=example.com
# Или инструмент командной строки testssl.sh
sudo apt install -y git
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh https://example.com
6. Настройка виртуальных хостов
Виртуальные хосты позволяют размещать несколько сайтов на одном сервере. Правильная настройка виртуальных хостов — важный шаг для организации production-среды.
Организация файловой структуры
Для каждого сайта рекомендуется использовать следующую структуру каталогов:
# Создание структуры для нового сайта
sudo mkdir -p /var/www/sites/example.com/{public,logs,backup,cache}
# Настройка прав доступа
sudo chown -R nginx:nginx /var/www/sites/example.com
sudo chmod -R 755 /var/www/sites/example.com
Шаблон конфигурации виртуального хоста
Создадим шаблон для быстрого добавления новых сайтов:
# Создание шаблона
sudo nano /etc/nginx/templates/vhost-template.conf
Содержимое шаблона:
server {
listen 80;
listen [::]:80;
server_name DOMAIN_NAME www.DOMAIN_NAME;
# Перенаправление на HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name DOMAIN_NAME www.DOMAIN_NAME;
# SSL-сертификаты
ssl_certificate /etc/letsencrypt/live/DOMAIN_NAME/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/DOMAIN_NAME/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/DOMAIN_NAME/chain.pem;
# Настройки SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
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_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Настройки OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Заголовки безопасности
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
# Корневая директория сайта
root /var/www/sites/DOMAIN_NAME/public;
index index.php index.html index.htm;
# Логи
access_log /var/www/sites/DOMAIN_NAME/logs/access.log;
error_log /var/www/sites/DOMAIN_NAME/logs/error.log;
# Настройка для статических файлов
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# Обработка PHP
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
# Защита от доступа к скрытым файлам
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Отключение доступа к чувствительным файлам
location ~* \.(env|log|git|htaccess|tpl|twig|ini|sql)$ {
deny all;
return 404;
}
# Основная обработка запросов
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
Скрипт для быстрого создания нового виртуального хоста
Создадим удобный скрипт для автоматизации процесса добавления новых сайтов:
# Создание скрипта
sudo nano /usr/local/bin/create-vhost.sh
Содержимое скрипта:
#!/bin/bash
# Проверка наличия доменного имени
if [ -z "$1" ]; then
echo "Не указано доменное имя!"
echo "Использование: create-vhost.sh example.com"
exit 1
fi
DOMAIN=$1
TEMPLATE_FILE="/etc/nginx/templates/vhost-template.conf"
CONFIG_FILE="/etc/nginx/conf.d/${DOMAIN}.conf"
# Проверка существования шаблона
if [ ! -f "$TEMPLATE_FILE" ]; then
echo "Файл шаблона не найден: $TEMPLATE_FILE"
exit 1
fi
# Создание структуры каталогов
echo "Создание структуры каталогов для $DOMAIN..."
mkdir -p /var/www/sites/${DOMAIN}/{public,logs,backup,cache}
chown -R nginx:nginx /var/www/sites/${DOMAIN}
chmod -R 755 /var/www/sites/${DOMAIN}
# Создание тестовой страницы
echo "<!DOCTYPE html>
<html>
<head>
<title>Welcome to ${DOMAIN}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
line-height: 1.6;
}
h1 {
color: #336699;
}
</style>
</head>
<body>
<h1>Welcome to ${DOMAIN}</h1>
<p>This is the default page for ${DOMAIN}.</p>
<p>Server time: <?php echo date('Y-m-d H:i:s'); ?></p>
<p>PHP Version: <?php echo phpversion(); ?></p>
</body>
</html>" > /var/www/sites/${DOMAIN}/public/index.php
# Создание конфигурации виртуального хоста
echo "Создание конфигурации виртуального хоста..."
cp $TEMPLATE_FILE $CONFIG_FILE
sed -i "s/DOMAIN_NAME/${DOMAIN}/g" $CONFIG_FILE
# Проверка синтаксиса конфигурации
echo "Проверка синтаксиса конфигурации Nginx..."
nginx -t
if [ $? -eq 0 ]; then
echo "Конфигурация успешно проверена."
echo "Перезапуск Nginx..."
systemctl reload nginx
echo "Получение SSL-сертификата..."
certbot --nginx -d ${DOMAIN} -d www.${DOMAIN}
echo "Виртуальный хост для ${DOMAIN} успешно создан!"
echo "Теперь вы можете загрузить ваши файлы в /var/www/sites/${DOMAIN}/public/"
else
echo "Ошибка в конфигурации Nginx. Виртуальный хост не активирован."
fi
Сделаем скрипт исполняемым:
sudo chmod +x /usr/local/bin/create-vhost.sh
Совет
Теперь добавление нового сайта выполняется простой командой:
sudo create-vhost.sh example.com
Скрипт создаст все необходимые каталоги, настроит виртуальный хост и запросит SSL-сертификат.
Настройка специализированных виртуальных хостов
Для различных CMS и фреймворков могут потребоваться дополнительные настройки:
Пример конфигурации для WordPress
# Дополнительные настройки для WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
# Защита файлов WordPress
location ~* wp-config.php|wp-admin/includes {
deny all;
}
# Кеширование статических файлов
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires max;
log_not_found off;
}
Пример конфигурации для Laravel
# Laravel настройки
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Защита от доступа к .env и другим критичным файлам
location ~ \.env {
deny all;
return 404;
}
# Кеширование для Laravel Mix (собранные ресурсы)
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
7. Оптимизация производительности
Оптимизация производительности LEMP-стека позволяет сайтам работать быстрее и обрабатывать больше запросов без необходимости в дополнительных ресурсах.
Настройка кеширования Nginx
Правильно настроенное кеширование может значительно снизить нагрузку на сервер:
# Создание директории для кеша
sudo mkdir -p /var/cache/nginx
# Настройка прав доступа
sudo chown -R nginx:nginx /var/cache/nginx
sudo chmod -R 755 /var/cache/nginx
# Создание конфигурации кеширования
sudo nano /etc/nginx/conf.d/cache.conf
Содержимое конфигурационного файла кеширования:
# Определение зон кеширования
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=proxy_cache:10m max_size=1g inactive=60m;
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2 keys_zone=fastcgi_cache:10m max_size=1g inactive=60m;
# Настройка параметров FASTCGI кеширования
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
Добавление кеширования в конфигурацию виртуального хоста (пример для WordPress):
# Настройка FASTCGI-кеширования (добавить в server блок)
set $skip_cache 0;
# Пропуск кеша для админки, входа, авторизованных пользователей и т.д.
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# В location блоке для PHP добавить:
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Настройки кеширования
fastcgi_cache fastcgi_cache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_background_update on;
# Добавление заголовка для отладки
add_header X-Cache $upstream_cache_status;
}
Установка и настройка Redis для кеширования сессий и данных
Redis — быстрое хранилище данных в памяти, которое можно использовать для кеширования и хранения сессий:
# Установка Redis
sudo apt install -y redis-server php8.1-redis
# Настройка Redis
sudo nano /etc/redis/redis.conf
Основные настройки для Redis:
# Базовая настройка безопасности
protected-mode yes
port 6379
bind 127.0.0.1 ::1
# Производительность
maxmemory 256mb
maxmemory-policy allkeys-lru
# Персистентность (если нужна)
save 900 1
save 300 10
save 60 10000
Настройка PHP для использования Redis:
# Редактирование php.ini
sudo nano /etc/php/8.1/fpm/php.ini
# Добавить настройки для Redis
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379"
Перезапуск сервисов:
sudo systemctl restart redis-server
sudo systemctl restart php8.1-fpm
Оптимизация баз данных MySQL
Для оптимизации производительности баз данных:
# Создание скрипта для автоматической оптимизации
sudo nano /usr/local/bin/optimize-mysql.sh
Содержимое скрипта:
#!/bin/bash
# Файл для логов
LOG_FILE="/var/log/mysql/optimization.log"
# Дата выполнения
DATE=$(date +"%Y-%m-%d %H:%M:%S")
# Запись начала в лог
echo "[$DATE] Starting MySQL optimization" >> $LOG_FILE
# Получение списка баз данных
DATABASES=$(mysql -B -N -e "SHOW DATABASES;" | grep -v "information_schema" | grep -v "performance_schema" | grep -v "mysql" | grep -v "sys")
# Перебор баз данных
for DB in $DATABASES; do
echo "[$DATE] Optimizing database: $DB" >> $LOG_FILE
# Получение списка таблиц
TABLES=$(mysql -B -N -e "SHOW TABLES FROM \`$DB\`;")
# Перебор таблиц
for TABLE in $TABLES; do
echo "[$DATE] Optimizing table: $DB.$TABLE" >> $LOG_FILE
# Анализ таблицы
mysql -e "ANALYZE TABLE \`$DB\`.\`$TABLE\`;" >> $LOG_FILE 2>&1
# Оптимизация таблицы
mysql -e "OPTIMIZE TABLE \`$DB\`.\`$TABLE\`;" >> $LOG_FILE 2>&1
done
done
echo "[$DATE] MySQL optimization completed" >> $LOG_FILE
Сделаем скрипт исполняемым и добавим его в планировщик cron:
# Установка прав на исполнение
sudo chmod +x /usr/local/bin/optimize-mysql.sh
# Добавление задания в cron для выполнения каждое воскресенье в 3:00
echo "0 3 * * 0 root /usr/local/bin/optimize-mysql.sh" | sudo tee -a /etc/cron.d/mysql-optimization
Настройка мониторинга производительности
Установим простой инструмент для мониторинга производительности — Netdata:
# Установка зависимостей
sudo apt install -y autoconf automake gcc make git python3 python3-pip
# Установка Netdata
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# Проверка статуса
sudo systemctl status netdata
После установки Netdata доступен через веб-интерфейс по адресу http://ваш_сервер:19999. Для повышения безопасности рекомендуется настроить базовую HTTP-аутентификацию или проксирование через Nginx с SSL.
Совет
Для максимальной производительности в production-среде также рассмотрите:
- Использование CDN (Content Delivery Network) для статического контента
- Настройку HTTP/2 для всех сайтов
- Применение WebP и оптимизацию изображений
- Минификацию и объединение CSS/JavaScript файлов
- Внедрение отложенной загрузки (lazy loading) для изображений
8. Повышение безопасности
Production-сервер требует особого внимания к безопасности. Рассмотрим дополнительные меры для защиты LEMP-стека от распространенных угроз.
Установка и настройка Fail2ban
Fail2ban помогает защититься от брутфорс-атак, блокируя IP-адреса после определенного количества неудачных попыток:
# Установка Fail2ban
sudo apt install -y fail2ban
# Создание конфигурационного файла
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
Основные настройки для Fail2ban:
[DEFAULT]
# Время бана в секундах (24 часа)
bantime = 86400
# Время в секундах, за которое отслеживаются попытки (10 минут)
findtime = 600
# Количество попыток до бана
maxretry = 5
# Игнорирование локальных IP
ignoreip = 127.0.0.1/8 ::1
# Настройка для SSH
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
# Настройка для Nginx (защита от сканирования сайта)
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/*error.log
# Настройка для защиты PHP-FPM от брутфорса
[php-url-fopen]
enabled = true
port = http,https
filter = php-url-fopen
logpath = /var/log/nginx/*error.log
Создание дополнительного фильтра для обнаружения атак на веб-приложения:
# Создание фильтра для обнаружения сканирования уязвимостей
sudo nano /etc/fail2ban/filter.d/nginx-scanners.conf
Содержимое фильтра:
[Definition]
failregex = ^<HOST> .* "(?:GET|POST|HEAD) (?:/\.env|/wp-login\.php|/administrator|/admin/|/wp-content/|/phpMyAdmin|/phpmyadmin|/myadmin|/mysql|/mysqladmin|/sqladmin|/MyAdmin|/pma/|/PMA/|/joomla/|/wordpress/) .*$
ignoreregex =
Добавление нового фильтра в конфигурацию:
# Добавить в /etc/fail2ban/jail.local
[nginx-scanners]
enabled = true
port = http,https
filter = nginx-scanners
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
Запуск и включение автозапуска Fail2ban:
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
# Проверка статуса
sudo fail2ban-client status
Настройка ModSecurity WAF
ModSecurity — это межсетевой экран веб-приложений (WAF), который обеспечивает защиту от распространенных атак на веб-приложения:
# Установка зависимостей
sudo apt install -y git build-essential libpcre3-dev libxml2-dev libyajl-dev liblmdb-dev libgeoip-dev libcurl4-openssl-dev libmaxminddb-dev
# Клонирование репозитория ModSecurity
cd /opt
sudo git clone --depth 1 -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
# Компиляция ModSecurity
cd ModSecurity
sudo git submodule init
sudo git submodule update
sudo ./build.sh
sudo ./configure
sudo make
sudo make install
# Клонирование коннектора для Nginx
cd /opt
sudo git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
# Определение версии Nginx
NGINX_VERSION=$(nginx -v 2>&1 | sed 's/^nginx version: nginx\///g')
# Загрузка исходников Nginx той же версии
cd /opt
sudo wget http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
sudo tar zxvf nginx-$NGINX_VERSION.tar.gz
# Компиляция и установка модуля
cd /opt/nginx-$NGINX_VERSION
sudo ./configure --with-compat --add-dynamic-module=/opt/ModSecurity-nginx
sudo make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
# Создание директории для правил ModSecurity
sudo mkdir -p /etc/nginx/modsecurity
cd /etc/nginx/modsecurity
# Клонирование OWASP Core Rule Set
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
# Настройка базовой конфигурации ModSecurity
sudo cp /opt/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsecurity/modsecurity.conf
# Редактирование конфигурации
sudo sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/nginx/modsecurity/modsecurity.conf
# Создание основного конфигурационного файла включения
sudo nano /etc/nginx/modsecurity/main.conf
Содержимое файла main.conf:
Include /etc/nginx/modsecurity/modsecurity.conf
Include /etc/nginx/modsecurity/coreruleset/crs-setup.conf
Include /etc/nginx/modsecurity/coreruleset/rules/*.conf
Настройка Nginx для использования ModSecurity:
# Редактирование nginx.conf
sudo nano /etc/nginx/nginx.conf
Добавьте в начало блока http следующие строки:
load_module modules/ngx_http_modsecurity_module.so;
http {
# Настройки ModSecurity
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/main.conf;
Перезапуск Nginx:
sudo nginx -t
sudo systemctl restart nginx
Важно!
ModSecurity может вызывать ложные срабатывания и блокировать легитимный трафик. Рекомендуется сначала запустить его в режиме обнаружения (SecRuleEngine DetectionOnly) и тщательно проанализировать логи перед включением в производственной среде.
Защита важных файлов и каталогов
Настройка защиты для критически важных файлов системы:
# Настройка защиты критических файлов
sudo chattr +i /etc/passwd
sudo chattr +i /etc/shadow
sudo chattr +i /etc/group
sudo chattr +i /etc/gshadow
# Для временного редактирования этих файлов используйте:
# sudo chattr -i /etc/passwd
# ... внесите изменения ...
# sudo chattr +i /etc/passwd
Установка и настройка Maldet (Linux Malware Detect)
Maldet — это инструмент для обнаружения вредоносного ПО в Linux:
# Загрузка и установка Maldet
cd /opt
sudo wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
sudo tar -xzf maldetect-current.tar.gz
cd maldetect-*
sudo ./install.sh
# Настройка Maldet
sudo nano /usr/local/maldetect/conf.maldet
Основные параметры для настройки:
# Включение e-mail уведомлений
email_alert="1"
email_addr="your-email@example.com"
# Автоматическое сканирование каталогов
autoupdate_signatures="1"
autoupdate_version="1"
# Карантин для зараженных файлов
quarantine_hits="1"
# Сканирование оперативной памяти
scan_user_access="1"
Создание задания для регулярного сканирования:
# Создание скрипта для еженедельного сканирования
echo '#!/bin/bash
/usr/local/maldetect/maldet -b -r /var/www /home /tmp /var/tmp /var/log' | sudo tee /etc/cron.weekly/maldet-scan
sudo chmod +x /etc/cron.weekly/maldet-scan
Аудит безопасности с помощью Lynis
Lynis — инструмент для аудита безопасности и проверки соответствия стандартам:
# Установка Lynis
sudo apt install -y lynis
# Запуск аудита безопасности
sudo lynis audit system
# Создание еженедельного отчета
echo '#!/bin/bash
REPORT_FILE="/var/log/security-audit-$(date +%Y%m%d).log"
echo "Security Audit Report - $(date)" > $REPORT_FILE
echo "===================================" >> $REPORT_FILE
echo "" >> $REPORT_FILE
lynis audit system --quiet >> $REPORT_FILE
echo "" >> $REPORT_FILE
echo "Recommendations:" >> $REPORT_FILE
echo "===================================" >> $REPORT_FILE
lynis show suggestions >> $REPORT_FILE
echo "" >> $REPORT_FILE
echo "Warnings:" >> $REPORT_FILE
echo "===================================" >> $REPORT_FILE
lynis show warnings >> $REPORT_FILE
# Отправка отчета на email
mail -s "Security Audit Report for $(hostname) - $(date +%Y-%m-%d)" your-email@example.com < $REPORT_FILE' | sudo tee /etc/cron.weekly/security-audit
sudo chmod +x /etc/cron.weekly/security-audit
Совет
Регулярно проверяйте отчеты аудита безопасности и внедряйте рекомендуемые меры. Безопасность — это непрерывный процесс, а не одноразовое мероприятие.
9. Мониторинг и логирование
Комплексный мониторинг и логирование — ключевые компоненты для надежной работы production-сервера. Они позволяют своевременно обнаруживать проблемы и принимать меры до того, как они повлияют на пользователей.
Настройка централизованного логирования
Объединение логов в одном месте упрощает их анализ и поиск проблем:
# Установка rsyslog
sudo apt install -y rsyslog
# Настройка централизованного хранения логов
sudo mkdir -p /var/log/centralized
sudo chown syslog:adm /var/log/centralized
# Конфигурация rsyslog
sudo nano /etc/rsyslog.d/30-centralized.conf
Содержимое конфигурационного файла:
# Nginx логи
$InputFileName /var/log/nginx/access.log
$InputFileTag nginx-access:
$InputFileStateFile stat-nginx-access
$InputFileSeverity info
$InputFileFacility local6
$InputRunFileMonitor
$InputFileName /var/log/nginx/error.log
$InputFileTag nginx-error:
$InputFileStateFile stat-nginx-error
$InputFileSeverity error
$InputFileFacility local6
$InputRunFileMonitor
# PHP-FPM логи
$InputFileName /var/log/php-fpm/www-error.log
$InputFileTag php-error:
$InputFileStateFile stat-php-error
$InputFileSeverity error
$InputFileFacility local5
$InputRunFileMonitor
# MySQL логи
$InputFileName /var/log/mysql/error.log
$InputFileTag mysql-error:
$InputFileStateFile stat-mysql-error
$InputFileSeverity error
$InputFileFacility local4
$InputRunFileMonitor
# Шаблон для сохранения логов
$template CentralizedLogs,"/var/log/centralized/%$YEAR%/%$MONTH%/%$DAY%/%syslogfacility-text%-%syslogseverity-text%.log"
# Правила для записи логов
local4.* -?CentralizedLogs
local5.* -?CentralizedLogs
local6.* -?CentralizedLogs
Перезапуск rsyslog:
sudo systemctl restart rsyslog
Настройка ротации логов
Правильная ротация логов предотвращает заполнение диска старыми логами:
# Настройка logrotate для всех компонентов LEMP
sudo nano /etc/logrotate.d/lemp
Содержимое файла конфигурации ротации:
# Nginx логи
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 nginx adm
sharedscripts
postrotate
[ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
endscript
}
# PHP-FPM логи
/var/log/php-fpm/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 nginx adm
sharedscripts
postrotate
[ -s /run/php-fpm/php-fpm.pid ] && kill -USR1 `cat /run/php-fpm/php-fpm.pid`
endscript
}
# MySQL логи
/var/log/mysql/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 mysql adm
sharedscripts
postrotate
[ -s /run/mysqld/mysqld.pid ] && kill -USR1 `cat /run/mysqld/mysqld.pid`
endscript
}
Установка и настройка Prometheus и Grafana
Для комплексного мониторинга всего стека настроим Prometheus (сбор метрик) и Grafana (визуализация):
# Создание пользователя для Prometheus
sudo useradd --no-create-home --shell /bin/false prometheus
# Создание директорий
sudo mkdir -p /etc/prometheus
sudo mkdir -p /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus
# Загрузка и установка Prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.40.0/prometheus-2.40.0.linux-amd64.tar.gz
tar -xvf prometheus-2.40.0.linux-amd64.tar.gz
cd prometheus-2.40.0.linux-amd64
sudo cp prometheus /usr/local/bin/
sudo cp promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus
sudo chown prometheus:prometheus /usr/local/bin/promtool
sudo cp -r consoles/ /etc/prometheus
sudo cp -r console_libraries/ /etc/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus/consoles
sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries
# Настройка конфигурации Prometheus
sudo nano /etc/prometheus/prometheus.yml
Базовая конфигурация Prometheus:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
scrape_interval: 5s
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
scrape_interval: 5s
static_configs:
- targets: ['localhost:9100']
- job_name: 'mysql_exporter'
scrape_interval: 5s
static_configs:
- targets: ['localhost:9104']
- job_name: 'nginx_exporter'
scrape_interval: 5s
static_configs:
- targets: ['localhost:9113']
Создание systemd-сервиса для Prometheus:
sudo nano /etc/systemd/system/prometheus.service
Содержимое файла сервиса:
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
--config.file /etc/prometheus/prometheus.yml \
--storage.tsdb.path /var/lib/prometheus/ \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries
[Install]
WantedBy=multi-user.target
Установка экспортеров для сбора метрик:
# Node Exporter для системных метрик
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.4.0/node_exporter-1.4.0.linux-amd64.tar.gz
tar -xvf node_exporter-1.4.0.linux-amd64.tar.gz
cd node_exporter-1.4.0.linux-amd64
sudo cp node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
# Сервис для Node Exporter
sudo nano /etc/systemd/system/node_exporter.service
Содержимое файла сервиса Node Exporter:
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.target
Установка и настройка Grafana:
# Установка зависимостей
sudo apt install -y apt-transport-https software-properties-common
# Добавление GPG ключа Grafana
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
# Добавление репозитория Grafana
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
# Установка Grafana
sudo apt update
sudo apt install -y grafana
# Запуск и включение автозапуска
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
Запуск всех служб мониторинга:
sudo systemctl daemon-reload
sudo systemctl start prometheus
sudo systemctl enable prometheus
sudo systemctl start node_exporter
sudo systemctl enable node_exporter
Совет
После настройки откройте Grafana (http://ваш_сервер:3000) и импортируйте готовые дашборды для мониторинга. Рекомендуемые ID дашбордов:
- 1860 — Node Exporter Full
- 7362 — MySQL Overview
- 9614 — NGINX Exporter Dashboard
Настройка оповещений
Создание системы оповещений о критических событиях:
# Установка Alertmanager
cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz
tar -xvf alertmanager-0.24.0.linux-amd64.tar.gz
cd alertmanager-0.24.0.linux-amd64
sudo cp alertmanager /usr/local/bin/
sudo cp amtool /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false alertmanager
sudo chown alertmanager:alertmanager /usr/local/bin/alertmanager
sudo chown alertmanager:alertmanager /usr/local/bin/amtool
sudo mkdir -p /etc/alertmanager
sudo chown alertmanager:alertmanager /etc/alertmanager
# Конфигурация Alertmanager
sudo nano /etc/alertmanager/alertmanager.yml
Базовая конфигурация Alertmanager:
global:
resolve_timeout: 5m
smtp_from: 'alerts@example.com'
smtp_smarthost: 'smtp.example.com:587'
smtp_auth_username: 'alerts@example.com'
smtp_auth_password: 'your-password'
smtp_require_tls: true
route:
group_by: ['alertname', 'instance', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'email-notifications'
receivers:
- name: 'email-notifications'
email_configs:
- to: 'admin@example.com'
send_resolved: true
Создание systemd-сервиса для Alertmanager:
sudo nano /etc/systemd/system/alertmanager.service
Содержимое файла сервиса:
[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target
[Service]
User=alertmanager
Group=alertmanager
Type=simple
ExecStart=/usr/local/bin/alertmanager \
--config.file=/etc/alertmanager/alertmanager.yml \
--storage.path=/var/lib/alertmanager
[Install]
WantedBy=multi-user.target
Запуск Alertmanager:
sudo systemctl daemon-reload
sudo systemctl start alertmanager
sudo systemctl enable alertmanager
10. Автоматизация обслуживания
Автоматизация рутинных задач позволяет экономить время и снижает риск человеческих ошибок. Рассмотрим автоматизацию основных процессов обслуживания LEMP-стека.
Автоматизация резервного копирования
Создадим скрипт для полного резервного копирования всех компонентов LEMP-стека:
# Создание скрипта для резервного копирования
sudo nano /usr/local/bin/lemp-backup.sh
Содержимое скрипта:
#!/bin/bash
# Настройки
BACKUP_DIR="/var/backups/lemp"
MYSQL_USER="root"
MYSQL_PASSWORD="" # Если используется аутентификация через socket
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
LOG_FILE="/var/log/lemp-backup.log"
KEEP_DAYS=7 # Количество дней хранения резервных копий
# Создание директории для резервных копий
mkdir -p $BACKUP_DIR
mkdir -p $BACKUP_DIR/databases
mkdir -p $BACKUP_DIR/websites
mkdir -p $BACKUP_DIR/config
# Логирование начала процесса
echo "$(date): Начало процесса резервного копирования" >> $LOG_FILE
# Резервное копирование MySQL базы данных
echo "$(date): Резервное копирование баз данных MySQL" >> $LOG_FILE
databases=$(mysql -u $MYSQL_USER --skip-column-names -e "SHOW DATABASES;" | grep -v "information_schema" | grep -v "performance_schema" | grep -v "mysql" | grep -v "sys")
for db in $databases; do
echo "$(date): Копирование базы данных $db" >> $LOG_FILE
mysqldump -u $MYSQL_USER --single-transaction --quick --lock-tables=false $db | gzip > $BACKUP_DIR/databases/$db-$DATE.sql.gz
if [ $? -eq 0 ]; then
echo "$(date): База данных $db успешно скопирована" >> $LOG_FILE
else
echo "$(date): Ошибка при копировании базы данных $db" >> $LOG_FILE
fi
done
# Резервное копирование веб-сайтов
echo "$(date): Резервное копирование веб-сайтов" >> $LOG_FILE
for website_dir in /var/www/sites/*; do
if [ -d "$website_dir" ]; then
website_name=$(basename $website_dir)
echo "$(date): Копирование сайта $website_name" >> $LOG_FILE
tar -czf $BACKUP_DIR/websites/$website_name-$DATE.tar.gz -C /var/www/sites $website_name
if [ $? -eq 0 ]; then
echo "$(date): Сайт $website_name успешно скопирован" >> $LOG_FILE
else
echo "$(date): Ошибка при копировании сайта $website_name" >> $LOG_FILE
fi
fi
done
# Резервное копирование конфигурации
echo "$(date): Резервное копирование конфигурационных файлов" >> $LOG_FILE
tar -czf $BACKUP_DIR/config/nginx-config-$DATE.tar.gz /etc/nginx
tar -czf $BACKUP_DIR/config/php-config-$DATE.tar.gz /etc/php
tar -czf $BACKUP_DIR/config/mysql-config-$DATE.tar.gz /etc/mysql
# Удаление старых резервных копий
echo "$(date): Удаление устаревших резервных копий (старше $KEEP_DAYS дней)" >> $LOG_FILE
find $BACKUP_DIR -type f -name "*.gz" -mtime +$KEEP_DAYS -delete
# Установка прав доступа
chown -R root:root $BACKUP_DIR
chmod -R 600 $BACKUP_DIR
echo "$(date): Процесс резервного копирования завершен" >> $LOG_FILE
# Опционально: отправка уведомления о завершении
# mail -s "LEMP Backup Completed on $(hostname)" your-email@example.com < $LOG_FILE
Настройка прав доступа и добавление задания в cron:
# Установка прав на исполнение
sudo chmod +x /usr/local/bin/lemp-backup.sh
# Добавление задания в cron для ежедневного резервного копирования в 2:00
echo "0 2 * * * root /usr/local/bin/lemp-backup.sh" | sudo tee -a /etc/cron.d/lemp-backup
Автоматизация обновлений безопасности
Настроим автоматические обновления безопасности для системы:
# Установка пакета unattended-upgrades
sudo apt install -y unattended-upgrades apt-listchanges
# Настройка автоматических обновлений
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Основные настройки для автоматических обновлений:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::Package-Blacklist {
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
Включение автоматических обновлений:
sudo nano /etc/apt/apt.conf.d/20auto-upgrades
Содержимое конфигурационного файла:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";
Скрипт для проверки состояния LEMP-стека
Создадим скрипт для комплексной проверки работоспособности всего стека:
# Создание скрипта
sudo nano /usr/local/bin/check-lemp-stack.sh
Содержимое скрипта:
#!/bin/bash
# Файл для логов
LOG_FILE="/var/log/lemp-health-check.log"
# Очистка лог-файла
echo "LEMP Stack Health Check - $(date)" > $LOG_FILE
echo "=====================================" >> $LOG_FILE
echo "" >> $LOG_FILE
# Проверка состояния Nginx
echo "Проверка состояния Nginx:" >> $LOG_FILE
if systemctl is-active --quiet nginx; then
echo "✅ Nginx работает" >> $LOG_FILE
nginx -v >> $LOG_FILE 2>&1
else
echo "❌ Nginx не запущен!" >> $LOG_FILE
fi
# Проверка синтаксиса конфигурации Nginx
echo "" >> $LOG_FILE
echo "Проверка конфигурации Nginx:" >> $LOG_FILE
nginx -t >> $LOG_FILE 2>&1
# Проверка состояния MySQL
echo "" >> $LOG_FILE
echo "Проверка состояния MySQL:" >> $LOG_FILE
if systemctl is-active --quiet mysql; then
echo "✅ MySQL работает" >> $LOG_FILE
mysql --version >> $LOG_FILE 2>&1
else
echo "❌ MySQL не запущен!" >> $LOG_FILE
fi
# Проверка подключения к MySQL
echo "" >> $LOG_FILE
echo "Проверка соединения с MySQL:" >> $LOG_FILE
if mysql -e "SELECT 1;" &>/dev/null; then
echo "✅ Соединение с MySQL успешно" >> $LOG_FILE
else
echo "❌ Ошибка соединения с MySQL!" >> $LOG_FILE
fi
# Проверка состояния PHP-FPM
echo "" >> $LOG_FILE
echo "Проверка состояния PHP-FPM:" >> $LOG_FILE
if systemctl is-active --quiet php8.1-fpm; then
echo "✅ PHP-FPM работает" >> $LOG_FILE
php-fpm8.1 -v >> $LOG_FILE 2>&1
else
echo "❌ PHP-FPM не запущен!" >> $LOG_FILE
fi
# Проверка доступности сокета PHP-FPM
echo "" >> $LOG_FILE
echo "Проверка сокета PHP-FPM:" >> $LOG_FILE
if [ -S /run/php-fpm/php-fpm.sock ]; then
echo "✅ Сокет PHP-FPM доступен" >> $LOG_FILE
else
echo "❌ Сокет PHP-FPM отсутствует!" >> $LOG_FILE
fi
# Проверка использования диска
echo "" >> $LOG_FILE
echo "Проверка использования диска:" >> $LOG_FILE
df -h / >> $LOG_FILE
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//g')
if [ "$DISK_USAGE" -gt 90 ]; then
echo "❌ Предупреждение! Использование диска превышает 90%" >> $LOG_FILE
else
echo "✅ Использование диска в норме ($DISK_USAGE%)" >> $LOG_FILE
fi
# Проверка использования памяти
echo "" >> $LOG_FILE
echo "Проверка использования памяти:" >> $LOG_FILE
free -h >> $LOG_FILE
MEM_USAGE=$(free | awk 'NR==2 {print int($3*100/$2)}')
if [ "$MEM_USAGE" -gt 90 ]; then
echo "❌ Предупреждение! Использование памяти превышает 90%" >> $LOG_FILE
else
echo "✅ Использование памяти в норме ($MEM_USAGE%)" >> $LOG_FILE
fi
# Проверка загрузки системы
echo "" >> $LOG_FILE
echo "Проверка загрузки системы:" >> $LOG_FILE
uptime >> $LOG_FILE
LOAD=$(uptime | awk -F'[a-z]:' '{ print $2}' | awk -F',' '{print $1}' | tr -d ' ')
CORES=$(nproc)
LOAD_PER_CORE=$(echo "$LOAD / $CORES" | bc -l)
if (( $(echo "$LOAD_PER_CORE > 1.5" | bc -l) )); then
echo "❌ Предупреждение! Высокая загрузка системы" >> $LOG_FILE
else
echo "✅ Загрузка системы в норме" >> $LOG_FILE
fi
# Проверка виртуальных хостов Nginx
echo "" >> $LOG_FILE
echo "Проверка виртуальных хостов Nginx:" >> $LOG_FILE
for config in /etc/nginx/conf.d/*.conf; do
if [ -f "$config" ]; then
SERVER_NAME=$(grep -E '^\s*server_name' "$config" | head -1 | sed 's/server_name//g' | sed 's/;//g' | tr -d ' ' | cut -d' ' -f1)
if [ ! -z "$SERVER_NAME" ]; then
echo " - $SERVER_NAME ($(basename $config))" >> $LOG_FILE
fi
fi
done
# Проверка SSL-сертификатов
echo "" >> $LOG_FILE
echo "Проверка SSL-сертификатов:" >> $LOG_FILE
for cert in /etc/letsencrypt/live/*/cert.pem; do
if [ -f "$cert" ]; then
DOMAIN=$(echo "$cert" | sed -E 's/.*live\/([^/]+)\/cert.pem/\1/')
EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$cert" | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt 10 ]; then
echo "❌ $DOMAIN: Сертификат истекает через $DAYS_LEFT дней ($EXPIRY_DATE)" >> $LOG_FILE
else
echo "✅ $DOMAIN: Сертификат действителен ($DAYS_LEFT дней до истечения)" >> $LOG_FILE
fi
fi
done
# Проверка сетевых соединений
echo "" >> $LOG_FILE
echo "Активные сетевые соединения:" >> $LOG_FILE
netstat -tulpn | grep -E '(nginx|mysql|php)' >> $LOG_FILE
# Сбор метрик производительности
echo "" >> $LOG_FILE
echo "Метрики производительности:" >> $LOG_FILE
echo " - Nginx Active Connections: $(curl -s http://localhost/nginx_status 2>/dev/null | grep "Active connections" | awk '{print $3}' || echo "N/A")" >> $LOG_FILE
echo " - PHP-FPM Active Processes: $(ps aux | grep php-fpm | grep -v master | grep -v grep | wc -l)" >> $LOG_FILE
echo " - MySQL Active Connections: $(mysql -e "SHOW STATUS LIKE 'Threads_connected';" 2>/dev/null | tail -1 | awk '{print $2}' || echo "N/A")" >> $LOG_FILE
# Отправка отчета на email (опционально)
#mail -s "LEMP Health Check Report - $(hostname) - $(date +"%Y-%m-%d")" your-email@example.com < $LOG_FILE
# Вывод пути к файлу отчета
echo "" >> $LOG_FILE
echo "Отчет сохранен в $LOG_FILE"
echo "Отчет сохранен в $LOG_FILE"
Настройка прав доступа и добавление в cron:
# Установка прав на исполнение sudo chmod +x /usr/local/bin/check-lemp-stack.sh # Добавление задания в cron для ежедневной проверки в 8:00 echo "0 8 * * * root /usr/local/bin/check-lemp-stack.sh" | sudo tee -a /etc/cron.d/lemp-health-check
Скрипт для быстрого развертывания проектов
Создадим скрипт для автоматического развертывания проектов на базе LEMP-стека:
# Создание скрипта sudo nano /usr/local/bin/deploy-project.sh
Содержимое скрипта:
#!/bin/bash
# Проверка аргументов
if [ "$#" -lt 3 ]; then
echo "Использование: $0 "
echo "Поддерживаемые типы проектов: wordpress, laravel, php-static"
exit 1
fi
DOMAIN=$1
PROJECT_TYPE=$2
GIT_REPO=$3
WWW_DIR="/var/www/sites/$DOMAIN"
WWW_PUBLIC="$WWW_DIR/public"
LOG_FILE="/var/log/project-deploy-$DOMAIN.log"
# Запись начала процесса
echo "Начало развертывания проекта $DOMAIN ($(date))" > $LOG_FILE
# Создание директории для проекта
echo "Создание директории проекта..." >> $LOG_FILE
sudo mkdir -p $WWW_DIR
sudo mkdir -p $WWW_PUBLIC
sudo mkdir -p $WWW_DIR/logs
sudo mkdir -p $WWW_DIR/backup
# Клонирование репозитория
echo "Клонирование репозитория $GIT_REPO..." >> $LOG_FILE
git clone $GIT_REPO $WWW_PUBLIC 2>> $LOG_FILE
# Настройка прав доступа
echo "Настройка прав доступа..." >> $LOG_FILE
sudo chown -R nginx:nginx $WWW_DIR
sudo chmod -R 755 $WWW_DIR
# Создание виртуального хоста
echo "Создание виртуального хоста..." >> $LOG_FILE
sudo create-vhost.sh $DOMAIN
# Настройка в зависимости от типа проекта
case $PROJECT_TYPE in
wordpress)
echo "Настройка WordPress..." >> $LOG_FILE
# Создание базы данных и пользователя
DB_NAME=$(echo ${DOMAIN/./_} | sed 's/-/_/g')
DB_USER=$(echo ${DOMAIN/./_} | sed 's/-/_/g' | cut -c 1-12)
DB_PASS=$(openssl rand -base64 12 | tr -d "=+/")
echo "Создание базы данных $DB_NAME и пользователя $DB_USER..." >> $LOG_FILE
mysql -e "CREATE DATABASE IF NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
mysql -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
# Создание wp-config.php
cd $WWW_PUBLIC
if [ -f wp-config-sample.php ]; then
cp wp-config-sample.php wp-config.php
sed -i "s/database_name_here/$DB_NAME/" wp-config.php
sed -i "s/username_here/$DB_USER/" wp-config.php
sed -i "s/password_here/$DB_PASS/" wp-config.php
# Генерация ключей безопасности
for i in $(seq 1 8); do
key=$(openssl rand -base64 48 | tr -d "=+/" | cut -c 1-64)
sed -i "/AUTH_KEY/,/NONCE_SALT/ s/'put your unique phrase here'/'$key'/1" wp-config.php
done
# Настройка дополнительных параметров
echo "/** Настройки для повышения безопасности */" >> wp-config.php
echo "define('DISALLOW_FILE_EDIT', true);" >> wp-config.php
echo "define('WP_AUTO_UPDATE_CORE', true);" >> wp-config.php
echo "define('WP_POST_REVISIONS', 5);" >> wp-config.php
else
echo "ОШИБКА: Файл wp-config-sample.php не найден. Возможно, это не проект WordPress." >> $LOG_FILE
fi
;;
laravel)
echo "Настройка Laravel..." >> $LOG_FILE
# Создание базы данных и пользователя
DB_NAME=$(echo ${DOMAIN/./_} | sed 's/-/_/g')
DB_USER=$(echo ${DOMAIN/./_} | sed 's/-/_/g' | cut -c 1-12)
DB_PASS=$(openssl rand -base64 12 | tr -d "=+/")
echo "Создание базы данных $DB_NAME и пользователя $DB_USER..." >> $LOG_FILE
mysql -e "CREATE DATABASE IF NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
mysql -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
# Настройка Laravel
cd $WWW_PUBLIC
cp .env.example .env
sed -i "s/DB_DATABASE=laravel/DB_DATABASE=$DB_NAME/" .env
sed -i "s/DB_USERNAME=root/DB_USERNAME=$DB_USER/" .env
sed -i "s/DB_PASSWORD=/DB_PASSWORD=$DB_PASS/" .env
# Установка зависимостей и настройка приложения
composer install --no-interaction --no-dev --optimize-autoloader
php artisan key:generate
php artisan storage:link
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Миграция базы данных
php artisan migrate --force
# Настройка прав доступа для Laravel
sudo chown -R nginx:nginx $WWW_DIR/storage
sudo chown -R nginx:nginx $WWW_DIR/bootstrap/cache
;;
php-static)
echo "Настройка статического PHP проекта..." >> $LOG_FILE
# Для статических сайтов дополнительная настройка не требуется
;;
*)
echo "ОШИБКА: Неизвестный тип проекта: $PROJECT_TYPE" >> $LOG_FILE
exit 1
;;
esac
# Запись информации о проекте
echo "Сохранение информации о проекте..." >> $LOG_FILE
cat > $WWW_DIR/project-info.txt << EOF
Домен: $DOMAIN
Тип проекта: $PROJECT_TYPE
Репозиторий: $GIT_REPO
Дата развертывания: $(date)
EOF
if [ $PROJECT_TYPE == "wordpress" ] || [ $PROJECT_TYPE == "laravel" ]; then
cat >> $WWW_DIR/project-info.txt << EOF
База данных: $DB_NAME
Пользователь БД: $DB_USER
Пароль БД: $DB_PASS
EOF
fi
# Защита файла с информацией
sudo chmod 600 $WWW_DIR/project-info.txt
sudo chown root:root $WWW_DIR/project-info.txt
echo "Проект успешно развернут!" >> $LOG_FILE
echo ""
echo "Проект $DOMAIN успешно развернут!"
echo "Тип проекта: $PROJECT_TYPE"
echo "Информация о проекте сохранена в $WWW_DIR/project-info.txt"
echo "Лог установки: $LOG_FILE"
Установка прав на исполнение:
sudo chmod +x /usr/local/bin/deploy-project.sh
Совет
Использование скрипта очень простое:
sudo deploy-project.sh example.com wordpress https://github.com/username/wordpress-project.git
Скрипт автоматически создаст виртуальный хост, базу данных, настроит права доступа и выполнит базовую настройку проекта в зависимости от его типа.
Заключение
Настройка и оптимизация LEMP-стека для production-среды — это многогранный процесс, который требует внимания ко множеству аспектов от безопасности до производительности. В этой статье мы прошли полный путь от чистой установки Linux до полностью настроенного стека, готового для размещения высоконагруженных веб-приложений.
Мы рассмотрели:
- Подготовку сервера — базовую настройку безопасности системы
- Установку и оптимизацию Nginx — настройку веб-сервера для максимальной производительности
- Настройку MySQL — оптимизацию базы данных и обеспечение ее безопасности
- Установку PHP-FPM — настройку интерпретатора PHP для эффективной работы с Nginx
- Настройку SSL/TLS — защиту передаваемых данных с помощью шифрования
- Настройку виртуальных хостов — организацию размещения нескольких сайтов на одном сервере
- Оптимизацию производительности — повышение скорости работы всех компонентов стека
- Повышение безопасности — защиту от распространенных угроз и атак
- Мониторинг и логирование — отслеживание работы системы и выявление проблем
- Автоматизацию обслуживания — минимизацию рутинных операций с помощью скриптов
Важно понимать, что настройка production-сервера — это не одноразовое событие, а непрерывный процесс. Регулярное обновление всех компонентов, мониторинг, аудит безопасности и оптимизация производительности должны стать частью вашей повседневной работы.
Основные принципы работы с production-средой
С правильно настроенным LEMP-стеком вы получаете надежную, производительную и защищенную платформу для размещения практически любых веб-приложений — от простых сайтов до сложных высоконагруженных систем.
Заключительный совет
Сохраните все скрипты и команды из этого руководства в личном репозитории. Это позволит вам быстро восстановить настроенную среду в случае необходимости или развернуть аналогичную конфигурацию на новых серверах. В идеале перейдите к полностью автоматизированному развертыванию инфраструктуры с помощью таких инструментов, как Ansible, Chef или Terraform.
Максим Орлов
27 января 2025Потрясающая статья! Я уже давно занимаюсь администрированием веб-серверов, но нашел здесь множество полезных советов, о которых раньше не задумывался. Особенно понравился раздел по автоматизации - скрипты очень удобные и практичные.