Этап 0: документация и макеты
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
3400f58a5a
75 files changed
+14283
No files matched your search
@@ -0,0 +1,108 @@
|
||||
# 09. Инфраструктура
|
||||
|
||||
## 1. Сервер (проверено 18–20.10.2026)
|
||||
|
||||
| Что | Значение |
|
||||
|---|---|
|
||||
| ОС | Ubuntu 26.04.1 LTS |
|
||||
| Ресурсы | 4 vCPU, 7.7 ГБ RAM, 8 ГБ swap, 145 ГБ диска (занято 24 ГБ) |
|
||||
| IP | 169.58.76.183 — сайты (PTR `fr-ub2gs3.veilix.cc`, прямая запись совпадает); 173.212.216.183 — основной, через него по умолчанию идёт исходящий трафик (PTR `vmi3593751.contaboserver.net`) |
|
||||
| Установлено | Node 24.22, PostgreSQL 18.6, nginx 1.28 (модули geoip2 и brotli подключены), Redis 8, Postfix 3.10, OpenDKIM, certbot 4.0, Docker 29 (не используем), git |
|
||||
| Нет | pnpm, база GeoLite2 (`.mmdb`), сертификаты TLS, geoipupdate |
|
||||
| DNS | все 15 хостов проекта (вместе с `umi.veilix.cc`) указывают на 169.58.76.183; DNS-хостинг — Gcore |
|
||||
|
||||
## 2. Папки
|
||||
|
||||
```
|
||||
/home/vx_dev/veilix_dev/ — dev (пользователь vx_dev): рабочая копия git, .env, media/
|
||||
/home/vx_prod/veilix/ — prod (пользователь vx_prod), закрыто для остальных
|
||||
releases/<дата-тег>/ — собранные релизы (храним 5 последних)
|
||||
current -> releases/… — симлинк на работающий релиз
|
||||
shared/.env — секреты prod
|
||||
shared/media/ — загруженные файлы prod
|
||||
/home/umami/umami/ — Umami (пользователь umami)
|
||||
```
|
||||
|
||||
vx — личный пользователь администратора, к проекту отношения не имеет. Под vx_prod нет редактора и ИИ-агентов, VSCode Remote под vx_prod не подключаем ([D-004](decisions/D-004-environments.md)). Домашние папки всех пользователей — `750`, владелец — сам пользователь. Пустые папки `/home/vx/veilix.app`, `/home/vx/my.veilix.app`, `/home/vx/tg.veilix.app` проекту не нужны.
|
||||
|
||||
## 3. Процессы
|
||||
|
||||
1. Каждый сервис — под своим пользователем ОС, как systemd user-юнит. Root один раз включает `loginctl enable-linger` для vx_dev, vx_prod и umami, чтобы юниты работали без входа в систему.
|
||||
2. `veilix-dev.service` (vx_dev): `pnpm dev` на порту 3100 из `/home/vx_dev/veilix_dev`, перезапуск при сбое.
|
||||
3. `veilix.service` (vx_prod): `pnpm start` на порту 3000 из `/home/vx_prod/veilix/current`, `NODE_ENV=production`, перезапуск всегда.
|
||||
4. `umami.service` (umami): Umami на порту 3300.
|
||||
5. Фоновые задачи Payload выполняются внутри процессов приложения ([02-architecture.md](02-architecture.md), раздел 7).
|
||||
6. Логи — journald, у каждого пользователя свои (`journalctl --user -u veilix` под vx_prod). Сессии Claude логи prod не видят: при разборе проблем prod их присылает пользователь.
|
||||
7. Проверка живости — `/svc/health` (с проверкой базы).
|
||||
|
||||
## 4. nginx
|
||||
|
||||
| Хосты | Куда | Доступ |
|
||||
|---|---|---|
|
||||
| veilix.app, veilixvpn.com, my.veilix.app, my.veilixvpn.com, tg.veilix.app, tg.veilixvpn.com | 127.0.0.1:3000 | открыт |
|
||||
| plc.veilix.cc | 127.0.0.1:3000 | только разрешённые IP |
|
||||
| dev.veilix.app, dev.my.veilix.app, dev.veilixvpn.com, dev.my.veilixvpn.com | 127.0.0.1:3100 | только разрешённые IP или пароль; `X-Robots-Tag: noindex` |
|
||||
| dev.tg.veilix.app, dev.tg.veilixvpn.com | 127.0.0.1:3100 | открыт для Telegram; приложение пускает только разрешённые Telegram-аккаунты |
|
||||
| dev.plc.veilix.cc | 127.0.0.1:3100 | только разрешённые IP |
|
||||
| umi.veilix.cc | 127.0.0.1:3300 | только разрешённые IP |
|
||||
|
||||
1. Слушает 169.58.76.183, порты 80 (редирект на HTTPS и проверка certbot) и 443. TLS 1.2 и 1.3, HTTP/2, HSTS.
|
||||
2. Сертификаты — certbot, проверка через HTTP.
|
||||
3. Сжатие — brotli и gzip.
|
||||
4. GeoIP: блок `geoip2` в `/etc/nginx/conf/ip.conf`, база `/var/lib/GeoIP/GeoLite2-Country.mmdb` с `auto_reload`. Переменная `$geoip_country_code` уходит приложению заголовком `X-Geo-Country`; такой же заголовок от клиента nginx затирает. Старый модуль GeoIP v1 (`modules-enabled/50-mod-http-geoip.conf`) отключён: он занимает те же имена переменных, и `nginx -t` падает с ошибкой «the duplicate "geoip_country_code" variable».
|
||||
5. Заголовки к приложению — общий файл `/etc/nginx/snippets/veilix_proxy.conf` (плюс `maps/upgrade.conf` для WebSocket), его подключает каждый `location` с `proxy_pass`: `Host`, `X-Real-IP` и `X-Forwarded-For` (оба — `$remote_addr`: nginx стоит первым, цепочку от клиента не принимаем), `X-Forwarded-Proto`, `X-Geo-Country`, заголовки WebSocket (нужны горячей перезагрузке dev). `proxy_set_header` не наследуется в `location` со своими `proxy_set_header`, поэтому файл подключается в каждый такой `location`.
|
||||
6. В `nginx.conf` подключаются только `sites-enabled/*.conf`: файлы сайтов должны заканчиваться на `.conf`. Сайты: `sites-available/02_vx_veilix-prod.conf`, `02_vx_veilix-dev.conf`, `02_vx_plc-prod.conf`, `02_vx_plc-dev.conf`. Сертификаты Let's Encrypt (certbot, проверка через nginx): `veilix.app` (6 prod-хостов брендов), `dev.veilix.app` (6 dev-хостов), `plc.veilix.cc`, `dev.plc.veilix.cc`.
|
||||
a. Доступ по IP — файл `conf/ip_list_admin.conf` со строками `allow …;`, в `location` после него `deny all;`. Подключается на хостах админки и dev, кроме `dev.tg.*`.
|
||||
b. `dev.tg.*` — отдельный `server` без ограничения по IP, с `X-Robots-Tag: noindex`.
|
||||
c. На порту 80 — `location / { return 301 https://$host$request_uri; }`. Именно внутри `location`, а не на уровне `server`: так certbot при продлении может вставить свой `location` для проверки домена.
|
||||
7. Лимиты запросов (`limit_req`) на эндпоинты входа и формы.
|
||||
8. Для tg.* (этап 3) разрешить показ во фрейме Telegram Web (`frame-ancestors` для доменов telegram.org).
|
||||
9. Пути трекера Umami на доменах брендов проксируются на 127.0.0.1:3300 ([08-integrations.md](08-integrations.md), раздел 8).
|
||||
10. Конфигурацию готовит Claude текстом на согласование, применяет root.
|
||||
|
||||
## 5. PostgreSQL
|
||||
|
||||
1. Базы `veilix_dev`, `veilix_prod` и `umami`. Владелец каждой — роль с именем пользователя ОС: `vx_dev`, `vx_prod`, `umami`.
|
||||
2. Вход по Unix-сокету с проверкой пользователя ОС: стандартное правило Ubuntu `local all all peer` в `pg_hba.conf` пускает пользователя ОС только под ролью с тем же именем. Паролей нет, `pg_hba.conf` и `pg_ident.conf` править не нужно.
|
||||
3. У каждой базы снято право подключения для всех (`REVOKE CONNECT … FROM PUBLIC`): войти может только владелец. vx_dev в `veilix_prod` не попадёт.
|
||||
4. Роль владеет своей базой: Payload нужны права на изменение схемы (push в dev, миграции в prod).
|
||||
5. Строка подключения: `postgresql://vx_dev@/veilix_dev?host=/var/run/postgresql` (для prod — `vx_prod@/veilix_prod`).
|
||||
|
||||
## 6. Почта (Postfix)
|
||||
|
||||
1. `smtp_bind_address = 169.58.76.183`, `myhostname = fr-ub2gs3.veilix.cc`: письма уходят с IP, у которого обратная запись совпадает с прямой.
|
||||
2. OpenDKIM: ключи для veilix.app и veilixvpn.com (селектор, напр. `mail`).
|
||||
3. DNS для каждого из двух доменов:
|
||||
a. SPF: `v=spf1 ip4:169.58.76.183 -all` (плюс SMTP-провайдер, если используем);
|
||||
b. DKIM: TXT `mail._domainkey.<домен>` с открытым ключом;
|
||||
c. DMARC: `_dmarc.<домен>` — сначала `v=DMARC1; p=none; rua=mailto:…`, после проверки — `p=quarantine`.
|
||||
4. Проверить, что хостер не закрывает исходящий порт 25 и что 169.58.76.183 нет в чёрных списках.
|
||||
5. Приём почты поддержки (`help@…`) — где ящик, вопрос Q-16.
|
||||
|
||||
## 7. Бэкапы
|
||||
|
||||
1. Prod-база: каждую ночь `pg_dump -Fc veilix_prod`, хранить 14 ежедневных и 8 еженедельных, копия на другой сервер (куда — Q-14). Раз в месяц — проверочное восстановление в отдельную базу.
|
||||
2. `shared/media` — синхронизация на тот же внешний сервер.
|
||||
3. Dev не бэкапим: код — в git, данные dev — тестовые.
|
||||
|
||||
## 8. Задачи для root по этапам
|
||||
|
||||
| № | Этап | Задача | Статус на 21.10.2026 |
|
||||
|---|---|---|---|
|
||||
| R-00 | 0 | Переезд разработки: перенести `/home/vx/veilix_dev` в `/home/vx_dev/veilix_dev` (владелец vx_dev); SSH-ключ vx_dev для VSCode; Claude Code под vx_dev | не сделано |
|
||||
| R-01 | 0 | Репозиторий в Gitea; SSH-ключ vx_dev с правом push; для vx_prod — ключ только на чтение (deploy key) | не сделано |
|
||||
| R-02 | 1a | PostgreSQL: роли `vx_dev`, `vx_prod`, `umami` и их базы (раздел 5) | сделано и проверено: vx_dev входит в `veilix_dev`, в `veilix_prod` — отказ |
|
||||
| R-03 | 1a | pnpm: `corepack enable pnpm` | сделано |
|
||||
| R-04 | 1a | Пользователи vx_dev, vx_prod, umami; `loginctl enable-linger` для них | сделано |
|
||||
| R-05 | 1a | nginx и сертификаты для всех хостов (раздел 4) | работает; осталось исправить опечатку в `conf/ip_list_admin.conf` и добавить `X-Robots-Tag` для `dev.tg.*` |
|
||||
| R-06 | 1a | MaxMind: `geoipupdate` (ключ в `/etc/GeoIP.conf`, база в `/var/lib/GeoIP`, таймер `geoipupdate.timer`); отключить старый модуль GeoIP v1; блок `geoip2` (раздел 4, пункт 4) | сделано |
|
||||
| R-07 | 1c | Postfix, OpenDKIM, DNS-записи SPF, DKIM, DMARC — или данные SMTP-провайдера | |
|
||||
| R-08 | 1h | PostgreSQL для prod — если не сделано вместе с R-02 | сделано в R-02 |
|
||||
| R-09 | 1h | nginx и сертификаты для prod-хостов | сделано вместе с R-05 |
|
||||
| R-10 | 1h | Umami: nginx и сертификат для `umi.veilix.cc` (DNS уже есть; база — в R-02) | |
|
||||
| R-11 | 1h | Бэкапы prod-базы и media на внешний сервер (Q-14) | |
|
||||
| R-12 | 2 | VPS с Chatwoot и Twenty, ключи API; 2 бота поддержки в BotFather | |
|
||||
| R-13 | 3 | Боты в BotFather: 2 основных и тестовые; домен для Telegram Login; адреса MiniApp | |
|
||||
| R-14 | 4 | Аккаунты платёжных систем (сначала тестовые), адреса вебхуков | |
|
||||
| R-15 | 1h | По желанию (Q-18): sudo-правило, разрешающее vx_dev запускать от имени vx_prod только команду выкладки | |
|
||||
| R-16 | 1h | По желанию: правило nftables — к 127.0.0.1:3000 подключаются только `www-data` (nginx) и vx_prod ([10-security.md](10-security.md), раздел 7) | |
|
||||
Reference in new issue
Block a user