Menu
Настройка LAMP или LEMP на VPS или выделенном сервере

Настройка LAMP или LEMP на VPS или выделенном сервере

Настройка LAMP или LEMP на VPS или выделенном сервере

Подготовка сервера

Настройка сети

/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