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

106 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Журнал архитектурных решений
> Фиксируй здесь: что решили, почему, какие альтернативы отвергли.
> Формат: дата | решение | причина | альтернативы
---
## Инфраструктура
### Два сервера (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 правило.
---
## Сервисы
### Outline wiki — email magic link
**Дата:** 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` |