Хостинг на VDS CookBook

Ставить всё буду на Debian 10, первое, что я сделаю - это пересоберу ядро с минимальным набором модулей, сократив размер ядра с 200 до 14 мегабайт, второе - удалю все лишние локали, ну и в конце почищу кеши apt, но об этом будет отдельная статья...

Чтобы хостить всякие разные сайты не всегда первой свежести потребуется использовать разные версии PHP, иногда нужно и nodejs или еще какие штуки, да еще и между разными контейнерами желательно разграничить пространство, поэтому самое оптимальное - это использовать докер для контейнеризации.

При этом база данных будет общая на всех и не будет контейнеризироваться, т.е. будет стоять  на самом хосте, может я что-то недопонял, но mysql в контейнере хоть немного но просаживается, VDS не такой уж мощный, поэтому не вижу ничего плохого что сервис предоставляющий БД будет на самом хосте.

Помимо всего нам нужно реализовать настройку почтового сервера, он будет сконфигурирован так, чтобы почта из контенеров пересылалась во внешнюю сеть, это для всяких уведомлений с сайтов.

И самым главным звеном всей этой кухни будет nginx, он будет все входящие запросы маршрутизировать по контейнерам.

Настройка почтовика

Настройка DNS PTR

Для того, чтобы от вашего сервера почтовики брали хоть какую-то почту - нужно обратиться в техподдержку хостера или откопать в кабинете такую опцию, прописать, нужно чтобы команда

nslookup 1.2.3.4

Возвращало домен к которому привязан этот айпи, допустим у нас домен

srv1.mydomain.ru, помимо этого, нужно прописать и прямую зону A на этот поддомен...

Примерно так должно быть

pavelbelaev@Mac-mini-Pavel ~ % nslookup 5.181.255.66

Non-authoritative answer:
66.255.181.5.in-addr.arpa	name = vm-2a9e742.na4u.ru.




pavelbelaev@Mac-mini-Pavel ~ % nslookup vm-2a9e742.na4u.ru

Non-authoritative answer:
Name:	vm-2a9e742.na4u.ru
Address: 5.181.255.66
ip ссылается на домен, а домен на айпи

После прописывания записей у регистратора домена и у хостера нужно подождать пару часов, пока всё применится, а то вдруг до гугла это сразу не дойдет и будет блочить.

Установка POSTFIX

apt install postfix

При установке выбираем интернет-сайт, нам не надо получать входящую, только исходящую слать

Далее указать тот самый домен, на который прописана обратная зона к IP

srv1.mydomain.ru надо заменить на свое, несуществующий домен работать не будет

На этом пока всё, отдельно по настройке отправки из докеров можете почитать вот тут, но мы к этому вернемся еще в нашей статье.

Установка Docker

По установке докера на дебиан написано на официальном сайте

Переходим под рутом и выполняем следующее

apt update && apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release;
    
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  
apt update && apt install docker-ce docker-ce-cli containerd.io

Установка NGINX

apt install nginx

Накидываем конфиг, примерно такой etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;

	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 32 8k;
	gzip_http_version 1.1;
	gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	client_max_body_size 1000M;
	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

Установка Certbot

certbot необходим для раздачи беспалтных ssl для наших сайтов и их автоматического обновления...

apt install certbot

про настройку сертификатов будет ниже при конфигурировании первого сайта...

Установка MariaDB

Практика показала, что mysql8 значительно медленнее 7.5. mariadb 10.3 примерно равна mysql 7.5, а mariadb 10.6  даже слегка быстрее...

инструкция по установке

apt-get install software-properties-common dirmngr apt-transport-https
apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
add-apt-repository 'deb [arch=amd64,arm64,ppc64el] https://mirror.surf/mariadb/repo/10.6/debian buster main'

apt update && apt install mariadb-server

Дальше надо задать пароль

mariadb-secure-installation 

А потом надо создать такого рута, который все может

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password';
grant all privileges on *.* to 'root'@'%' with grant option;
flush privileges;

Управление доступом

По-умолчанию mysql пускает подключения только с локалхоста, это не подходит для контейнеризации

Сперва нам нужно узнать ip нашего моста с докер-контейнерами

ip addr| grep docker0

У меня это 172.17.0.1

отредактируем файлик /etc/mysql/mariadb.conf.d/50-server.cnf

Разрешим прослушивание моста докеров, вместо локального интерфейса

bind-address            = 172.17.0.1

После этого доступ будет из докеров, но не будет извне...

Нужно только перезапустить mysql

service mysql restart

Из докеров PHP надо настраивать подключение тоже на адрес 172.17.0.1 вместо локалхоста...

Соответственно и пользователей mysql нужно создавать не user@%, а user@172.17.% контейнерам будут выдаваться динамические адреса, но все они будут в пределах подсети /16 (255.255.0.0)

Тонким тюннингом mariaDB займемся позже, вероятно в конце этой статьи, а вероятно в отдельной статейке

Создание первого хоста (сайта)

Сперва создадим папку для нашего сайта, это /www/sitename/web

Всё что выше по уровню от папки web недоступно веб-серверу, там будут файлы для конкретного сайта - всякие временные файлы, конфиги, сессии.

Итак, допустим у меня сайт example.ru

sitename="example.ru"

mkdir -p /www/$sitename/web && cd /www/$sitename

Мы находимся в папке сайта, теперь будем его переносить с другого хостинга, вариант запаковывать, переносить и распаковывать архив не очень, т.к. размер около 40 гигабайт, а место на диске около 60, просто не хватит места чтобы распаковать архив, да и накладно это всё по ресурсам и времени, попробуем просто через rsync копирнуть.

Т.к. на источнике права заданы на пользователя отличного от тех, которые доступны для логина по ssh, то может просто прав не хватить, но на приемнике всё логично, тут пустая папка и пока я не прикрыл логин под рутом. Поэтому я просто залогинюсь на старый хостинг и буду с него засылать всё это...

cd /www/example.ru/
rsync -vtrz . root@example.ru:/www/example.ru/

Если на старом хостинге что-то поменяется, я могу еще раз перед финальным переходом сделать rsync и передадутся только измененные файлы.

У меня есть копии сайтов на личной машине, хоть и не самые актуальные, но там изменилось максимум 5%, во-первых домашний интернет у меня 250 мегабит и на VDS около гигабита, тогда как на старом колокейшн 100 мегабитный тарий, во-вторых не хочется забивать канал на рабочем продакте, поэтому я сперва сделаю rsync с личного пк, а потом повторю с прода, чтобы минимум его нагружать...

Пока всё копируется, можно дальше продолжать настраивать целевую машину....
В итоге перенос 32 гигов с личного пк на сервер у меня занял около 27 минут. Раньше я запаковывал архив минут 15, минут 15 его распаковывал и еще минут 20 тратил на его скачивание. Дальше я за секунд 10 актуализировал с текущего продакта состояние файлов, там буквально штук 100 файликов обновилось... Отныне буду только через rsync заливку делать на виртуалки...

Nginx - новый сайт

Как мы помним, у нас в главном конфиге nginx прописан инклуд из папки /etc/nginx/sites-enabled/, поэтому создадим отдельный файлик для нашего хоста

nano /etc/nginx/sites-enabled/example.ru

Пример конфига пока не самый лучший, но можно примерно такое использовать...

Развертывание базы данных для сайта

Сперва создадим нашего пользователя, помните раздел выше про mariadb? там мы определяли IP

CREATE USER 'user'@'172.17.%' IDENTIFIED BY 'passw***';
GRANT USAGE ON *.* TO 'user'@'172.17.%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; 

Дальше создадим базу и предоставим привелегии уровня бд

CREATE DATABASE `base1`;
GRANT ALL PRIVILEGES ON `base1`.* TO 'user'@'172.17.%' WITH GRANT OPTION;
 
flush privileges;
 
quit

Теперь создадим дамп нашей БД и зальем

Сперва на сервере источника

mysqldump mybase -uroot -p > base1.sql

Потом на новом сервере (опцию -p можно пропустить, если по сокету локально авторизация без пароля)

mysql base1 -uroot -p < /www/base1.sql

ну и в конфиге сайта пропишем

/*DB CONFIGURATION*/
SYSCONF::$DB['db_name'] = 'base1';
SYSCONF::$DB['user'] = 'user';
SYSCONF::$DB['pass'] = '*******';
SYSCONF::$DB['host'] = '172.17.0.1';

Docker

Как вы поняли, мои сайты используют PHP и у меня немного подточенный контейнер с пропатчеными локалями, с предустановленными необходимыми модулями типа поддержки RabbitMQ. Там почти все есть почти для любого проекта и работает на php-fpm, в моем контейнере даже есть почтовый транспорт.

Сперва соберем контейнер из докерфайла

mkdir php_le_docker;
cd php_le_docker;
wget https://raw.githubusercontent.com/TechResearchRu/LE_PHP_Docker/main/Dockerfile
docker build -t php-le .

Настройка почты из Docker

Как я уже говорил, мой контейнер поддерживает работу с почтой, но нам потребуется немножко подкрутить наш Postfix и создать конфиг...

Опять вспомним IP нашего докера и еще вспомним какой домен мы прописали в PTR на этапе установки и настройки Postfix, если забыли, возвращаемся выше и вспоминаем о чем тут речь...

Создадим файлик /etc/postfix/sender_canonical_maps

/.+/    postmaster@srv.mydomain.ru

Далее пропишем в nano /etc/postfix/main.cf

#тут хак для подмены отправителя из докеров
sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps

И еще там же не забудем дописать нашу подсеть из докеров, тут перечислены все сети от которых будет без авторизации почта браться и пересылаться во внешний мир

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16

Почти всё, остается создать конфиг транспорта для контейнера

nano /www/ssmtp.conf

#see ptr
rewriteDomain=srv.mydomain.ru
FromLineOverride=YES
#host ip, see "ip addr|grep docker0"
mailhub=172.17.0.1
UseTLS=YES
UseSTARTTLS=YES

А дальше запустим

docker run -d \
--restart=always \
--name default-fpm \
-p 127.0.0.1:9000:9000 \
-v /www/ssmtp.conf:/etc/ssmtp/ssmtp.conf \
-v /www:/www \
-v /mp:/mp \
php-le

В этом примере я всю папку /www прокинул в контейнер, но можно прокидывать по одному сайту, таким образом изолировать файловую систему отдельного сайта от других, я так делаю на всяких джумлах, особенно слегка устаревших, но там и версия php другая...

Обратите внимание, я указал 127.0.0.1 при пробросе порта, дальше локалхоста никто не сможет забраться в мой контейнер, nginx на локальном компе, ему это всё доступно будет, а большего нам не нужно.

Показать комментарии