Files
veilix.app/docs/09-infrastructure.md
T
andreypr207andClaude Opus 5.5 515acfb69d Документация: этапы по фазам, решения D-026…D-033
- Новый порядок этапов (D-026): фаза 1 — концепт на dev без внешних
  сервисов (1b сайт, 1c вход, 1d ключи, 1e счёт и демо-оплата,
  1f демо-выдача, 1g продления, 1h рефералы); фаза 2 — Telegram;
  фаза 3 — ALTCHA, ЮKassa, почта, Twenty, Chatwoot, Umami, выдача
  через API и публичный запуск; фаза 4 — звёзды и эквайринги.
- Решения: демо-оплата по списку IP (D-027), выдача ключей через
  адаптер manual/demo/api (D-028), страницы сайта из блоков Payload
  (D-029), пересборка через revalidatePath (D-030), RU-адрес у mass
  (D-031), счётчик свободных серверов (D-032), переводы на 5 языков
  в каждом этапе (D-033).
- Тексты описывают работающий продукт; Вейликс — выделенный IP на
  общем сервере; Telegram поддержки — @veilix_support; сроки ответа
  не обещаем; VPN-серверы не ведут журналов.
- Ссылки на этапы во всех документах, Q-12 решён (ЮKassa для RUB),
  R-19 (библиотеки для headless Chromium) сделано.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 03:48:10 +02:00

15 KiB
Raw Blame History

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). Домашние папки всех пользователей — 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 на 127.0.0.1:3100 из /home/vx_dev/veilix_dev, перезапуск при сбое. Файл юнита — ops/systemd/veilix-dev.service в репозитории, подключён через systemctl --user link.
  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, раздел 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.* (этап 2a) разрешить показ во фрейме Telegram Web (frame-ancestors для доменов telegram.org).
  9. Пути трекера Umami на доменах брендов проксируются на 127.0.0.1:3300 (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 include:<почтовый хостинг> -all. Хостинг нужен, потому что ответы поддержки уходят через него (пункт 5); плюс SMTP-провайдер, если используем; b. DKIM: TXT mail._domainkey.<домен> с открытым ключом; c. DMARC: _dmarc.<домен> — сначала v=DMARC1; p=none; rua=mailto:…, после проверки — p=quarantine.
  4. Проверить, что хостер не закрывает исходящий порт 25 и что 169.58.76.183 нет в чёрных списках.
  5. Почта поддержки (Q-16): ящики help@veilix.app и help@veilixvpn.com — на внешнем почтовом хостинге, MX-записи доменов указывают на него (пользователь, R-18). На этапе 3e Chatwoot забирает письма по IMAP и отвечает через SMTP хостинга. Доменов брендов в mydestination Postfix нет и быть не должно: тогда письма администраторам на help@… уходят на хостинг, а не остаются на этом сервере.

7. Бэкапы

  1. Prod-база: каждую ночь pg_dump -Fc veilix_prod, хранить 14 ежедневных и 8 еженедельных, копия на другой сервер (куда — Q-14). Раз в месяц — проверочное восстановление в отдельную базу.
  2. shared/media — синхронизация на тот же внешний сервер.
  3. Dev не бэкапим: код — в git, данные dev — тестовые.

8. Задачи для root по этапам

№ Этап Задача Статус на 22.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) vx_dev — сделано: origin — ssh://git@gte.apr.sh:26789/andreypr207/veilix.app.git, ключ ~/.ssh/veilix_gitea_ed25519 добавлен в Gitea как deploy key с правом записи, main отправлен. Ключ vx_prod — на этапе 1h
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) сделано: опечатка исправлена, X-Robots-Tag на всех dev-хостах
R-06 1a MaxMind: geoipupdate (ключ в /etc/GeoIP.conf, база в /var/lib/GeoIP, таймер geoipupdate.timer); отключить старый модуль GeoIP v1; блок geoip2 (раздел 4, пункт 4) сделано
R-07 3c Postfix, OpenDKIM, DNS-записи SPF, DKIM, DMARC — или данные SMTP-провайдера
R-08 3h PostgreSQL для prod — если не сделано вместе с R-02 сделано в R-02
R-09 3h nginx и сертификаты для prod-хостов сделано вместе с R-05
R-10 3f Umami: nginx и сертификат для umi.veilix.cc (DNS уже есть; база — в R-02)
R-11 3h Бэкапы prod-базы и media на внешний сервер (Q-14)
R-12 3d, 3e VPS с Chatwoot и Twenty, ключи API; 2 бота поддержки в BotFather
R-13 2a Боты в BotFather: 2 основных и тестовые; домен для Telegram Login; адреса MiniApp
R-14 3b, 4b Аккаунты платёжных систем (сначала тестовые), адреса вебхуков
R-15 3h По желанию (Q-18): sudo-правило, разрешающее vx_dev запускать от имени vx_prod только команду выкладки
R-16 3h По желанию: правило nftables — к 127.0.0.1:3000 подключаются только www-data (nginx) и vx_prod (10-security.md, раздел 7)
R-17 1a nginx dev: отдельный location /_next/hmr с proxy_read_timeout 1h во всех трёх server-блоках dev на 443: dev.plc.veilix.cc, сайты и кабинеты, dev.tg.*. В Next 16.4 WebSocket горячей перезагрузки — /_next/hmr, и сервер может молчать дольше 30 секунд, а nginx.conf закрывает соединение после 30 секунд тишины (proxy_read_timeout 30) сделано: на всех семи dev-хостах соединение держится 70 секунд без сообщений
R-18 3c Почта поддержки (Q-16): ящики help@veilix.app и help@veilixvpn.com на почтовом хостинге, MX-записи доменов; хостинг — в SPF (раздел 6). До этого письма администраторам и заявки видны только в админке и журнале писем
R-19 1b Библиотеки для headless Chromium — сверка страниц с макетами по скриншотам и Lighthouse: libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 libasound2t64 libxcomposite1 libxdamage1 libxfixes3 libxrandr2. Сам браузер (Chrome for Testing) лежит в папке vx_dev, без root сделано 22.10.2026: скриншоты снимаются