Архитектура
Один сервер вместо десяти
Сервер держит несколько проектов и не смешивает их между собой. Ниже — то, что можно перепроверить: хост, изоляция, путь изменения, проверки, бэкапы.
01Хост
Железо и базовый слой
- Расположение
- Амстердам, Нидерланды, один VPS (провайдер VDSina)
- ОС
- Ubuntu 24.04 LTS
- Ресурсы
- 2 vCPU · 4 ГБ RAM · 79 ГБ SSD
- Веб-сервер
- Caddy 2.11, TLS выпускается автоматически (Let's Encrypt)
- Запуск сервисов
- systemd, отдельный юнит на проект
02Изоляция
Проекты не знают друг о друге
Изоляция — не настройка «на будущее», а условие запуска: проект без неё просто не принимается.
Статику сайтов пишет только суперпользователь, сервисы проектов не ходят по чужим каталогам. Поэтому проект без рамки на схеме просто не принимается — это условие запуска, а не настройка «на будущее».
03Путь изменения
Push → гейт → доставка
Один маршрут для всех проектов. Ручных копирований на сервер нет: всё, что попадает в прод, прошло проверку.
Красный гейт — это норма. Он ловит ошибку до сервера; цена такой остановки — минуты, цена ошибки в проде — часы.
04Проверки
Что проверяется само
Четыре вида проверок идут без участия человека. Их задача — заметить проблему раньше, чем она станет заметной снаружи.
Самопроверка хоста
Состояние самого сервера и его юнитов: что запущено, что упало, что перезапускалось.
Аудит дрейфа
Сверка фактической конфигурации с ожидаемой. Всё, что изменилось в обход правил, видно отдельным отчётом.
Свежесть бэкапов
Снимки делаются по расписанию — и проверяется, что последний не устарел.
Сторож
Health-проверки проектов и уведомления в Telegram: сообщение приходит, когда что-то сломалось, а не после жалобы.
05Бэкапы
Снимок, который проверяли
Каждый день по каждому проекту снимаются данные. К снимку прикладывается контрольная сумма sha256, а его пригодность проверяется восстановлением: снимок, из которого ни разу не разворачивались, — это надежда, а не бэкап.
Проверка свежести бэкапов идёт в том же автоматическом режиме, что и остальные проверки, — её результат виден, даже если о ней никто не вспомнил.
06Несколько сайтов
Один адрес на сайт, общие порты
Caddy слушает 80 и 443 и различает сайты по домену. У каждого сайта свой блок конфигурации и свой сертификат, который выпускается автоматически. Отдельный IP-адрес для нового сайта не нужен.
Ошибка в конфигурации одного сайта не задевает остальные: проверка конфигурации не применяет сломанное изменение, а рабочие сайты продолжают работать на прежней версии.
07Заголовки
Строже, чем принято по умолчанию
Сайт отдаётся с заголовками безопасности: скрипты запрещены полностью, страница не может быть встроена в чужой фрейм.
- Content-Security-Policy
default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'none'- Strict-Transport-Security
max-age=31536000; includeSubDomains- X-Content-Type-Options
nosniff- X-Frame-Options
DENY- Referrer-Policy
strict-origin-when-cross-origin
Поэтому у сайта нет ни одного скрипта и ни одного инлайнового стиля — только внешний файл стилей с того же домена. И ни одного запроса на чужой сервер.