infra/docs/DECISIONS.md
jack 207e1dcff0
All checks were successful
CI/CD / syntax-check (push) Successful in 1m29s
CI/CD / deploy (push) Successful in 16m39s
chore: project cleanup and docs update
- Remove Syncthing mention from authelia comment in docker-compose
- Fix backup.sh.j2 comment: hourly → every 6 hours
- Update CLAUDE.md: add docs update rule, fix backup schedule note
- Update STATUS.md: dash.csrx.ru fixed, PTR pending, backup schedule, mail hostnames
- Update BACKLOG.md: mark DNS/PTR/backup-schedule done, add SnappyMail domain task
- Update DECISIONS.md: fix backup section (no --storage-class COLD, correct schedule)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:00:35 +07:00

7.7 KiB
Raw Permalink Blame History

Журнал архитектурных решений

Фиксируй здесь: что решили, почему, какие альтернативы отвергли. Формат: дата | решение | причина | альтернативы


Инфраструктура

Два сервера (main + tools)

Дата: начало проекта Решение: Разделить сервисы на два VPS: main для ядра, tools для вспомогательных. Причина: main (1 vCPU / 2 GB RAM) перегружен — Plane + Forgejo + мониторинг занимают почти всю память. tools позволяет разгрузить. Итог: Outline, n8n, mail работают на tools. Traefik на main проксирует к tools через IP:PORT.

Traefik вместо nginx/caddy

Дата: начало проекта Решение: Traefik v3 как единственный точка входа. Причина: Автоматический TLS через Let's Encrypt, file provider для маршрутов, удобная интеграция с Docker. Альтернативы: nginx + certbot (ручной renewal), Caddy (проще но меньше гибкости).

Cloudflare proxy + UFW whitelist

Дата: начало проекта Решение: Порты 80/443 открыты только для IP Cloudflare. Причина: Скрывает реальный IP сервера, защита от DDoS на уровне Cloudflare, бесплатный WAF. Важно: Некоторые сервисы (wiki, vault, webmail) должны быть DNS-only (оранжевое облако off) — когда Cloudflare не поддерживает нужные порты или протоколы.

Wildcard TLS через DNS-01

Дата: начало проекта Решение: Один сертификат *.csrx.ru вместо отдельных на каждый поддомен. Причина: Новый сервис — ноль ожидания сертификата. Cloudflare DNS-01 работает без HTTP-challenge. Конфиг: roles/services/templates/traefik/traefik.yml.j2 — certresolver letsencrypt.


Безопасность

Authelia для 2FA

Дата: начало проекта Решение: Authelia + TOTP защищает admin-панели (Traefik dashboard, Plane god-mode). Причина: Одна точка SSO, не нужно настраивать auth в каждом сервисе. Альтернативы: Keycloak (тяжелее, требует больше ресурсов), Authentik (сложнее).

CrowdSec community edition

Дата: начало проекта Решение: CrowdSec без платного API ключа. Причина: Бесплатная tier достаточна. Анализирует логи Traefik + auth.log. Ограничение: Нет расширенных threat feeds — только community reputation.

Syncthing — удалён

Дата: 2026-03 Решение: Удалить Syncthing полностью из инфраструктуры. Причина: Не используется. Открытые порты (22000, 21027) без сервиса — лишняя attack surface. Что убрали: UFW rules, docker image, domain_sync, переменную vault, Authelia правило.


Сервисы

Дата: 2026-02 Решение: Авторизация через email magic link (SMTP → docker-mailserver). Причина: Outline не поддерживает простую login/password аутентификацию без SSO. Проблемы решённые:

  • guestSignin=true в БД обязателен для email auth
  • jwtSecret в БД хранится в зашифрованном виде — при смене SECRET_KEY нужно пересоздать

docker-mailserver вместо внешнего SMTP

Дата: 2026-03 Решение: Self-hosted Postfix + Dovecot на tools-сервере. Причина: Полный контроль, аккаунты @csrx.ru для приёма и отправки, нет зависимости от внешних SMTP. Конфиг: SSL_TYPE=letsencrypt через certbot с Cloudflare DNS-01. DKIM через opendkim. Альтернативы: Mailgun/SendGrid (только отправка, без приёма), Maddy (менее зрелый).

Бэкап в Timeweb S3

Дата: 2026-03 Решение: Backup каждые 6 часов (00/06/12/18) → S3 visual-backup/data/, 7 дней хранения. Причина: 6 часов = баланс между частотой и нагрузкой на сервер. Тип хранилища COLD задаётся на уровне бакета в Timeweb, не через параметр --storage-class (Timeweb S3 не поддерживает этот параметр). Формат архива: единый main_data_YYYY-MM-DD_HH-MM.tar.gz с data/databases/ и data/volumes/.

SnappyMail вместо Roundcube

Дата: 2026-03 Решение: djmaze/snappymail как веб-клиент почты на mail.csrx.ru. Причина: Лёгкий, современный UI, простой Docker образ. Альтернативы: Roundcube (тяжелее, требует MySQL), Rainloop (заброшен).

mx.csrx.ru вместо mail.csrx.ru для MX-сервера

Дата: 2026-03 Решение: docker-mailserver hostname = mx.csrx.ru, веб-клиент = mail.csrx.ru. Причина: Стандарт индустрии — MX-хост называется mx, пользовательский интерфейс — mail. Раньше оба указывали на разные вещи под одним именем, что запутывало. DNS: mx.csrx.ru → 85.193.83.9 (DNS-only, прямые порты SMTP/IMAP). mail.csrx.ru → 87.249.49.32 (Cloudflare proxied, HTTPS вебмейл через Traefik). SPF: v=spf1 mx -all-all жёстче чем ~all, явно запрещает чужие отправители. DMARC: p=quarantine — подозрительные письма в спам (было p=none — только мониторинг).


CI/CD

Forgejo Actions

Дата: начало проекта Решение: Forgejo Actions + act_runner для CI/CD деплоя. Причина: Self-hosted, интегрировано с Forgejo, совместимо с GitHub Actions синтаксисом. Принцип: Push в master → ansible-playbook deploy.yml + tools.yml. Никаких ручных правок на сервере.


Известные компромиссы

Компромисс Почему так Что улучшить
act_runner монтирует /var/run/docker.sock Нужен для запуска job-контейнеров Rootless Docker или ограниченный API
Plane использует :stable тег Plane не публикует версионные теги Мониторить GitHub releases
Мониторинг на main (не на отдельном сервере) mon-сервер пока не задеплоен Создать playbooks/mon.yml
Нет бэкапа tools-сервера Бэкап роль подключена только к main Добавить в tools.yml