infra/docs/DECISIONS.md
jack 1e638055c8
Some checks failed
CI/CD / syntax-check (push) Successful in 1m23s
CI/CD / deploy (push) Has been cancelled
feat(mail): rename mail→mx, webmail→mail.csrx.ru + reliability
Rename:
- docker-mailserver: hostname mail → mx, OVERRIDE_HOSTNAME → mx.csrx.ru
- Traefik route: webmail/domain_webmail → mail/domain_mail
- domain_webmail removed, domain_mail + domain_mx added to main.yml
- certbot cert: mail.csrx.ru → mx.csrx.ru

Email reliability improvements:
- certbot renewal cron (03:15 + 15:15 daily)
- deploy-hook: auto-reload Postfix+Dovecot after cert renewal
- POSTFIX_MESSAGE_SIZE_LIMIT=26214400 (25 MB)
- SPF hardened: ~all → -all
- DMARC hardened: p=none → p=quarantine, added ruf + fo=1 + adkim/aspf strict
- autodiscover/autoconfig CNAME records for mail client setup
- dns-zone.zone fully updated with architecture comments

Docs:
- STATUS.md: full mail architecture section, client settings, DNS table
- BACKLOG.md: rDNS task + DNS migration steps
- DECISIONS.md: mx/mail split rationale

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:07:59 +07:00

7.5 KiB
Raw 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 cold

Дата: 2026-03 Решение: Hourly backup → S3 cold storage visual-backup/data/, 7 дней хранения. Причина: Дешевле горячего хранилища, бэкапы не нужны быстро — приемлемая задержка восстановления. Команда: aws s3 cp ... --storage-class COLD

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