infra/docs/DECISIONS.md
jack 66b70827df
Some checks failed
CI/CD / syntax-check (push) Successful in 1m31s
CI/CD / deploy (push) Has been cancelled
chore: full project cleanup + documentation
Syncthing removal (was already decided, now fully removed):
- roles/base/tasks/firewall.yml: remove 3 UFW rules (ports 22000/21027)
- inventory/group_vars/all/main.yml: remove domain_sync, domain_mon, syncthing_basic_auth_htpasswd
- roles/services/templates/env.j2: remove DOMAIN_SYNC
- roles/services/templates/authelia/configuration.yml.j2: remove Syncthing 2FA rule
- roles/services/tasks/directories.yml: remove syncthing/config and syncthing/data dirs
- roles/services/defaults/main.yml: remove syncthing_image
- roles/services/tasks/main.yml: remove syncthing image pull

Security hardening:
- inventory/group_vars/all/main.yml: move cloudflare_zone_id to vault
- inventory/group_vars/all/vault.yml: add vault_cloudflare_zone_id

.gitignore improvements:
- add *.env, acme.json, *.log, editor dirs, venv, temp files

Documentation (new):
- docs/STATUS.md: all services, servers, known issues
- docs/BACKLOG.md: prioritized task list, done/todo
- docs/DECISIONS.md: architecture decisions and rationale
- CLAUDE.md: rewritten with read-first docs, rules, full arch reference

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

6.6 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 как веб-клиент почты. Причина: Лёгкий, современный UI, простой Docker образ. Альтернативы: Roundcube (тяжелее, требует MySQL), Rainloop (заброшен).


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