Настройка LAMP или LEMP на VPS или выделенном сервере
Настройка LAMP или LEMP на VPS или выделенном сервере
- Подготовка сервера
- Установка MariaDB
- Установка выборочных версий PHP
- Apache2 Сервер
- NGINX Сервер
- Включение HTTPS - certbot
- Бекапирование - rsync
- Анализатор логов - Webalizer
- Использование webDAV
- Антивирус Clamav
- Временная точка монтирования TMPFS
- VestaCP
- .htaccess
- Решение проблем
Подготовка сервера
Настройка сети
/etc/network/interfaces
auto eth0
allow-hotplug eth0
iface eth0 inet static
address 172.16.1.3
netmask 255.255.255.0
gateway 172.16.1.1
# post-up route add -net 172.17.0.0/16 gw 172.17.1.1
dns-nameservers 77.88.8.8 8.8.8.8
или, если установлен netplan
/etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: no
addresses: [172.16.3.3/24]
gateway4: 172.16.3.1
nameservers:
search: [domain.com]
addresses: [8.8.8.8, 172.16.3.1]
Установить основные пакеты
$ apt update && apt upgrade && apt install sudo mc curl wget -y
Добавить нового пользователя
$ useradd user2
$ passw user2
Сменить порт SSH и отключить root
/etc/ssh/sshd_config
PermitRootLogin no
Port 2222
Установка MariaDB
MariaDB:
$ apt-get install mariadb-server
Настройка:
$ mysql_secure_installation
$ mysql
CREATE USER 'user2'@'localhost' IDENTIFIED BY 'secret'; CREATE DATABASE user2db; GRANT ALL PRIVILEGES ON user2db.* TO 'user2'@'localhost'; FLUSH PRIVILEGES; # или с доступом по сети
# его надо разрешить в 50-server.cnf: bind-address CREATE USER 'user2'@'%' IDENTIFIED BY 'secret'; CREATE DATABASE user2db; GRANT ALL PRIVILEGES ON user2db.* TO 'user2'@'%'; FLUSH PRIVILEGES;
или/и sqlite3
$ apt-get install sqlite3
Установка выборочных версий PHP
В 2023 актуальная версия PHP- 8.2, но есть проекты, которые не поддерживают эту версию, к тому же дефолтной версией PHP в Debian является 7.4
Для установки других версий требуется подключить проект sury
Если требуется удалить старую версию
apt-get purge php7.4-common
$ sudo apt install lsb-release apt-transport-https ca-certificates software-properties-common -y
$ sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
$ sudo sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
$ sudo apt update
# UPD: в России sury.org не работает, поэтому
$ sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://ftp.mpi-inf.mpg.de/mirrors/linux/mirror/deb.sury.org/repositories/php/apt.gpg $ deb https://ftp.mpi-inf.mpg.de/mirrors/linux/mirror/deb.sury.org/repositories/php/ bookworm main
Установка PHP на примере версии 8.2
$ sudo apt install php8.2 php8.2-{cli,zip,mysql,bz2,curl,mbstring,intl,common,ctype,fpm,dom,fileinfo,GD,JSON,posix,SimpleXML,XMLReader,XMLWriter}
ну и еще на вкус (например для NextCloud)
$ sudo apt install php8.2 php8.2-{ldap,mysql,sqlite3,bz2,intl,imap,exif,apcu,memcached,imagick,opcache, memcached,opcache}
(Можно повторить с другой версией)
Проверка версии и списка модулей
php -v && php -m
Настройка PHP
Если задействован fpm, то конфигурация в /etc/php/8.2/fpm/php.ini для Apache2 в /etc/php/8.2/apache2/php.ini
Установка максимального размера загрузки файлов
upload_max_filesize = 80M
Установка максимального размера памяти для скрипта (например для nextcloud требуется 512М)
memory_limit = 512M
Установка WEB сервера - Apache или NGINX
Apache2 Сервер
$ apt-get install apache2 libapache2-mod-php8.2
$ sudo a2enmod php8.2
Смена fpm
$ sudo a2enconf php8.2-fpm #Enable PHP 8.2 FPM extension
$ sudo a2disconf php7.4-fpm #Disable PHP 7.4 FPM extension
Включение дополнительных модулей(при необходимости)
$ a2enmod rewrite
$ a2enmod headers
$ a2enmod include
Включить сжатие:
$ a2enmod deflate
Модуль itk
для запуска нескольких сайтов от разных пользователей в целях безопасности и распределении нагрузки
$ apt-get install libapache2-mpm-itk
Включение mpm-itk
$ a2enmod mpm_itk
useradd -G www-data -m -d /home/user2 user2
mkdir /home/user2/htdocs && mkdir /home/user2/logs && chown user2:www-data -R /home/user2/
passwd user2
Пример конфига одного из хостингов /etc/nginx/sites-available/user2.conf:
<VirtualHost *:80>
ServerName mydomain.com
ServerAlias www.mydomain.com
DocumentRoot /home/user2/htdocs
<Directory "/home/user2/htdocs">
AllowOverride All
Require all granted
Options +FollowSymlinks +SymLinksIfOwnerMatch
</Directory>
#AssignUserID user2 www-data
<IfModule mpm_itk_module>
AssignUserId user2 www-data
</IfModule>
# работа с PHP через сокет
# <FilesMatch \.php$>
# SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
# </FilesMatch>
ErrorLog /home/user2/logs/error.log
CustomLog /home/user2/logs/access.log combined
</VirtualHost>
Применить конфигурацию
ln -s /etc/apache2/sites-available/user2.conf /etc/apache2/sites-enabled/user2.conf
Перезапустить apache2
# apache2ctl configtest && systemctl reload apache2
Тюнинг производительности apache
Проверить моды и конфигурацию
apachectl -t -D DUMP_MODULES | grep mpm
Проверить мод префорк /etc/apache2/mods-enabled/mpm_prefork.conf
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
Для расчета MaxRequestWorkers (MaxClients)
ps aux |grep apache2
root 10605 0.0 0.1 1282276 16780 ? Ss 02:05 0:01 /usr/sbin/apache2 -k start
www-data 13929 5.6 0.5 1299920 66256 ? S 10:28 2:34 /usr/sbin/apache2 -k start
www-data 14027 5.6 0.6 1318024 83468 ? S 10:43 1:40 /usr/sbin/apache2 -k start
, где найти строку с root - родительский процесс, в данном случае 10605
pmap -d 10605 | tail -1
mapped: 1282276K writeable/private: 16692K shared: 1048648K
, в данном случае - 16,7М
MaxRequestWorkers = (ОбщийОбъемПамяти-ПамятьДляДругихПроцессов)/ПамятьНа1ПроцессАпача = (12000-2000)/16,7=~550
$ apache2ctl configtest && systemctl reload apache2
NGINX Сервер
$ sudo apt install nginx
для запуска нескольких сайтов от разных пользователей в целях безопасности и распределении нагрузки
useradd -G www-data -m -d /home/user2 user2
mkdir /home/user2/htdocs && mkdir /home/user2/logs && chown user2:www-data -R /home/user2/
passwd user2
Создание пула fpm PHP
По умолчанию создан один сокет fpm
/etc/php/8.2/fpm/pool.d/www.conf
Требуется создать дополнительные сокеты
cp /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/user2.conf
Внести изменения в user2.conf
[user2]
user = user2
group = www-data
listen = /run/php/php8.2-fpn-user2.sock
Пример конфига одного из хостингов /etc/apache2/sites-available/user2:
server {
listen 80;
server_name mydomain.com www.mydomain.com;
root /home/user2/htdocs;
index index.php index.html index.htm;
# PHP variables
set $root_path /home/user2/htdocs;
# set user2 socket
set $php_sock unix:/var/run/php/php8.2-fpm-user2.sock;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
try_files $uri $uri/ /index.php?$args;
index index.html index.htm index.php;
}
# pass PHP scripts to FastCGI server
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass $php_sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# показать листинг директории
# location /files/ {
# autoindex on;
# }
# ограничить по IP
# location /tmp/ {
# allow 172.16.30.0/24;
# deny all;
# }
# rewrite по совпадению
# location = /Autodiscover/Autodiscover.xml
# {
# rewrite ^/Autodiscover/Autodiscover.xml$ http://172.16.1.2/autodiscover/autodiscover.php;
# }
# 301 редирект на https
# if ($host = domain.ru) {
# return 301 https://$host$request_uri;
# }
# доступ по логину и паролю в .htpasswd
# location /ddvr {
# auth_basic "Secure Area";
# auth_basic_user_file /home/user2/htdocs/ddvr/.htpasswd;
# }
# проксирование ресурса из подсети
# location / {
# proxy_pass http://172.16.1.2:88;
# }
# проуксирование только на один скрипт
# location = /scripts/c.php { # proxy_pass http://192.168.1.1/c.php; # }
# проксирование ресурса из подсети по флагу с именем сессии
# set $flag 0;
# if (-f /tmp/tmpfs/$cookie_AUTH.flg) {
# set $flag 1;
# }
# location / {
# if ($flag = 1) {
# proxy_pass http://172.16.1.69; }
# передача реального IP веб серверу в подсети
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_pass http://172.16.1.2:88;
# }
# включение пользовательского конфига
# include /home/user/www.inc;
}
включение виртуального хостинга
ln -s /etc/nginx/sites-available/user2 /etc/nginx/sites-enabled/user2
Перезапуск nginx и php-fpm
systemctl restart php8.2-fpm && systemctl restart nginx
Включение HTTPS - certbot
apt-get install certbot
если apache:
apt-get install python3-certbot-apache
certbot run --apache
если nginx:
apt-get install python3-certbot-nginx
certbot run --nginx
Скрипт сам установит Pyton3 и изменить конфиги выбранных виртуальных хостов
Принудительное обновление
certbot renew
Бекапирование - rsync
apt-get install rsync
10.10.10.2 - рабочий сервер
10.10.10.3 - сервер бэкапов (с него коннектимся к рабочему)
1. Создание ключа
На 10.10.10.3:
$ ssh-keygen -f ~/.ssh/id_rsa -q -P "" -b 4096
$ cat ~/.ssh/id_rsa.pub
Вывод скопировать
На 10.10.10.2:
$ mkdir ~/.ssh
$ chmod 0700 ~/.ssh
$ touch ~/.ssh/authorized_keys
$ chmod 0644 ~/.ssh/authorized_keys
В файл ~/.ssh/authorized_keys копируем содержимое публичного ключа, скопированного выше
$ /etc/init.d/sshd restart
Проверка c 10.10.10.3
$ ssh -i /home/user2/.ssh/id_rsa -p 22 user1@10.10.10.2
Пример rsync:
#!/bin/sh
snapshot_dir=/var/backup/snaps-site.ru/`date '+%y-%m-%d'`
mkdir $snapshot_dir
rsync -ahz -r --delete --hard-links \
--delete-excluded --exclude-from=/root/scripts/siteru.exclude \
--backup --backup-dir=$snapshot_dir \
-e "ssh -p22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \
user@10.10.10.2:/var/www/site.ru/ /var/www/site.ru/
Анализатор логов - Webalizer
apt install webalizer
Создать директории вида /hosting/site2/webalizer/ для хранения результатов
Запланировать крон /etc/crontab:
20 0 * * * root webalizer -q -p -n site2 -o /hosting/site2/webalizer /hosting/site2/logs/site2-access.log.1;
, где -q - тихий режим, -p - ротирующиеся логи, -n имя сайта, -o - директория вывода
Использование webDAV
Монтирование yandex диска
apt-get install davfs2
sudo mkdir -p /mnt/yandex
/etc/davfs2/secret:
/mnt/yandex username@yandex.ru password
/etc/fstab:
https://webdav.yandex.ru /mnt/yandex davfs noauto,user 0 0
mount /mnt/yandex
umount /mnt/yandex
Антивирус Clamav
Установка
apt-get install clamav
прописать источник баз
/etc/clamav/freshclam.conf
#DatabaseMirror db.local.clamav.net
DatabaseMirror packages.microsoft.com/clamav
Обновление
freshclam
Проверка рекурсивно в /home, показывать только инфицированные, перемещать в карантин
clamscan -r /home -i --move=/infected_files
Временная точка монтирования TMPFS
Применяется для хранения временных файлов (сессии, флаги и тд), чтобы не тереть "дырку" в SSD
Прописать в /etc/sftab
tmpfs /home/tmp tmpfs noatime,nosuid 0 0
или с фиксированным размером
tmpfs /home/tmp tmpfs rw,noatime,nosuid,size=20M 0 0
mkdir /home/tmp
Смонтировать
mount /home/tmp
ВНИМАНИЕ: Apace2 из соображений безопасности не дает доступ в /tmp
VestaCP
VestaCP - очень достойное решение, чтобы ничего не делать руками - панель управления, для создания хостинга
Желательна чистая установка системы без PHP и вебсерверов - скрипт сам установит и настроит всё под себя
curl -O http://vestacp.com/pub/vst-install.sh
bash vst-install.sh
.htaccess
Сжатие:
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
Реврайты
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
или
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
или
RewriteEngine On
RewriteCond %{HTTPS} =off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L]
Решение проблем:
Ошибка authz_core error
Проверить, чтобы конфигурационные файлы хостингов заканчивались на .conf
Вписать Require all granted в секцию
Отображение сайта в неверной кодировке при cp1251
Прописать в .htaccess
AddDefaultCharset WINDOWS-1251
php_value default_charset cp1251
Ротирование логов в директории пользователя
В конфиг ротатора требуется добавить
su <user> <group>
Разрешить sftp но запретить SSH
/etc/shells +
/bin/false
В /etc/passwd +
test:x:1002:33::/home/test:/bin/false
* 33 - www-data
В /etc/ssh/sshd_config
Match group www-data
ChrootDirectory /home/%u
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
chown root /home/test
chown test:www-data -R /home/test/*
Lisolog / 2024