Add legacy ADR

This commit is contained in:
2026-05-24 15:40:20 +03:00
parent 313b1820be
commit 81478c2323
6 changed files with 191 additions and 5 deletions
+50
View File
@@ -0,0 +1,50 @@
# Authelia вместо Keycloak для SSO
- Дата: 2025-05-07
## Контекст
Для SSO/OIDC на сервере стоял Keycloak (заведён годом ранее,
2024-05-25). Проблема — ресурсы: Keycloak съедал больше 500 МБ RAM, что
тяжело для личного сервера c ограниченной оперативной памятью. При этом вся его мощь
избыточна: пользователей меньше десяти, realms / federation / тяжёлый
enterprise-стек не нужны. Изначально взял Keycloak, потому что нужен был
OIDC сервер для настройки Outline: когда настраивал был понятный гайд
по OIDC и Keycloak.
Требовался лёгкий по памяти SSO-провайдер с хорошей документацией,
желательно на Go/Rust.
## Рассмотренные варианты
- **Оставить Keycloak.** Отвергнуто: > 500 МБ RAM ради < 10
пользователей, функционал избыточен для личного сервера.
- **Authelia** (выбран). Лёгкая (Go), малое потребление памяти, хорошая
документация. Умеет и OIDC, и forward-auth.
Критерии отбора замены: минимальный расход RAM, хорошая документация,
стек Go/Rust.
## Решение
Заменили Keycloak на Authelia как провайдер аутентификации
(коммиты `a77fefc`, `d1500ea`, `3a23c08`). Authelia используется в трёх
режимах:
- **OIDC** для приложений, которым он нужен (например, Outline).
- **Forward-auth** агент в Caddy — удобно там, где полноценный OIDC
избыточен.
- **Закрытие чувствительных приложений** за единым логином. Раньше для
этого использовался basic auth в Caddy.
## Последствия
- `+` Резко меньше потребление RAM — критично для сервера с дефицитом
памяти.
- `+` Forward-auth закрывает приложения без OIDC проще, чем поднимать
отдельный OIDC-клиент под каждое.
- `+` Единая точка аутентификации вместо разрозненного basic auth в
Caddy.
- `-` Authelia беднее Keycloak по возможностям (нет полноценного UI
управления пользователями, realms, federation) — но для < 10
пользователей это не нужно.
@@ -0,0 +1,42 @@
# Данные приложений на отдельном диске
- Дата: 2025-12-07
## Контекст
Исторически данные приложений лежали прямо в домашних директориях их
системных пользователей (`/home/<app-user>/…`), то есть на системном
диске рядом с ОС. В конце 2025 встал вопрос обновления ОС (Ubuntu 22.04
уже устарела), и стало ясно: пока данные привязаны к системному диску,
любое обновление или пересборка системы рискует этими данными и тяжело
откатывается.
Возникла мысль развязать данные приложений и жизненный цикл ОС.
## Рассмотренные варианты
- **Данные на системном диске** (как было). Просто, но данные связаны с
ОС: обновление/пересборка системы затрагивает и их.
- **Отдельный диск под данные** (выбран). Данные переживают пересборку
ОС, диск можно отцепить от одного сервера и прицепить к другому.
## Решение
Вынесли все данные приложений на отдельный диск, смонтированный в
`/mnt/applications`; каждое приложение держит там свои `data` / `config`
/ `backups`, а `base_dir`/`data_dir` указывают на этот путь
(коммиты `47a6320`, `7e67409`, `ae7c20a`, `8dfd061`).
## Последствия
- `+` Данные развязаны с жизненным циклом ОС — систему можно обновлять
и пересобирать, не трогая данные.
- `+` Диск можно отцепить от старого сервера и прицепить к новому. Это
легло в основу метода обновления ОС
([ADR-2025-12-13](ADR-2025-12-13-os-upgrade-via-server-rebuild.md)).
- `-` Появилась зависимость от монтирования внешнего диска (UUID,
mount-конфигурация): если диск не смонтирован, приложения не
поднимутся. Позже, при переезде в Timeweb, монтирование пришлось
сделать опциональным
([ADR-2026-05-23](ADR-2026-05-23-migrate-to-timeweb.md), фаза 1 — один
диск, фаза 2 — отдельный «холодный» диск под крупные данные).
@@ -0,0 +1,53 @@
# Обновление ОС пересборкой на свежем сервере
- Дата: 2025-12-13
## Контекст
На сервере стояла Ubuntu 22.04, и к концу 2025 пора было обновляться.
Обновлять живую боевую систему in-place (`do-release-upgrade`) не
хотелось — это рискованно и тяжело откатывается, если что-то пойдёт не
так на работающем сервере.
## Рассмотренные варианты
- **In-place обновление** (`do-release-upgrade` на живой системе).
Отвергнуто: риск сломать рабочий сервер, нет простого отката.
- **Пересборка на свежем сервере** (выбран). Поднять новый сервер с
целевой ОС, накатать ansible, прицепить диск с данными, развернуть
приложения — старый сервер остаётся нетронутым как точка отката.
Заодно почистить мусор от прошлой рабоыт сервера.
## Решение
Обновляем ОС через пересборку на свежем сервере. Метод опирается на три
предпосылки:
- **Деплой без запуска контейнеров.** Сводные плейбуки
(`playbook-all-setup`, `playbook-all-applications`) и тег `run-app`
позволяют раскатать пользователей, каталоги и конфиги, но НЕ запускать
приложения (`--skip-tags run-app`) — данные переносятся в «тихую»
систему (коммиты `5b53cb3`, `48bb8c9`, `67df03e`).
- **Данные на отдельном диске**
([ADR-2025-12-07](ADR-2025-12-07-app-data-on-separate-disk.md)) — диск
с данными прицепляется к новому серверу.
- **Фиксированные uid/gid.** Заранее закрепили uid/gid всех
пользователей приложений (роль `owner`, коммит `c2ea2cd`). Это
критично: иначе при пересоздании пользователей на новом сервере
uid/gid могли бы сдвинуться, и данные приложений на отдельном диске
оказались бы с чужим владельцем.
Порядок: сначала вся подготовка (отдельный диск, перенос данных на него,
фиксация uid/gid), затем пересборка на новом обновлённом сервере. Перенос
прошёл без проблем.
## Последствия
- `+` Обновление ОС без риска для живой системы; откат = вернуться на
старый сервер.
- `+` Получился воспроизводимый процесс миграции — позже переиспользован
при переезде в Timeweb как «cold cutover»
([ADR-2026-05-23](ADR-2026-05-23-migrate-to-timeweb.md)).
- `+` Фиксация uid/gid стала постоянным инвариантом проекта.
- `-` Метод требует заранее подготовленных предпосылок (фикс uid/gid +
данные на отдельном диске); без них он не работает.
@@ -0,0 +1,37 @@
# Apprise как шлюз нотификаций
- Дата: 2026-04-04
## Контекст
В первую очередь нужны были нотификации о бэкапах — знать, что ночной
прогон отработал и не сломался. Уведомления слались напрямую в конкретный
канал, привязка была зашита в каждом источнике. Хотелось единый слой,
который абстрагирует каналы доставки — чтобы добавлять или менять канал в
одном месте, а не править каждый источник.
## Рассмотренные варианты
- **Прямая интеграция per-канал** (как было). Каждый источник знает про
конкретный канал; смена канала — правки во многих местах.
- **Apprise** (выбран). Смотрел разные self-hosted шлюзы нотификаций;
apprise выиграл зрелостью и числом готовых интеграций (десятки каналов
из коробки).
## Решение
Подняли apprise отдельным сервисом-шлюзом: источники шлют уведомление по
HTTP в apprise, а он разводит его по настроенным каналам (коммиты
`a0543e1`, `5f619ea`, `6bfb362`). Под ограниченную память сервера apprise
запущен в один воркер (`5e6df11`).
## Последствия
- `+` Каналы доставки абстрагированы за единым шлюзом — добавить или
сменить канал можно в одном месте, не трогая источники.
- `+` Доступ к десяткам интеграций apprise без отдельного кода под
каждую.
- `-` Ещё один сервис в обслуживании (контейнер, память).
- Окупилось при переезде в Timeweb: провайдер заблокировал Telegram, и
переключение нотификаций (сейчас почта, в планах Matrix) локализовано в
шлюзе ([ADR-2026-05-23](ADR-2026-05-23-migrate-to-timeweb.md)).
@@ -43,7 +43,7 @@
- Стратегия — **cold cutover**: погасить сервисы на источнике, раскатать - Стратегия — **cold cutover**: погасить сервисы на источнике, раскатать
ansible на новом сервере без запуска приложений (сохраняя uid/gid), перенести ansible на новом сервере без запуска приложений (сохраняя uid/gid), перенести
данные `rsync`'ом, запустить, переключить DNS. данные `rsync`'ом, запустить, переключить DNS.
- Диск: фаза 1 — один 80 ГБ NVMe (всего 22 ГБ данных, влезает с - Диск: фаза 1 — один 80 ГБ NVMe (всего 22 ГБ данных + 17 ГБ системных, влезает с
запасом). «Холодный» второй диск под крупные данные — отдельная запасом). «Холодный» второй диск под крупные данные — отдельная
фаза 2, не на критическом пути. фаза 2, не на критическом пути.
- Источник не удаляется сразу после cutover: держим «холодным запасным» - Источник не удаляется сразу после cutover: держим «холодным запасным»
+8 -4
View File
@@ -61,7 +61,11 @@
Новые сверху. Новые сверху.
| Дата | Запись | Статус | | Дата | Запись | Статус |
| ---------- | ------------------------------------------------------------------------------------- | ------ | | ---------- | ---------------------------------------------------------------------------------------------- | ------ |
| 2026-05-23 | [Переезд сервера с Yandex Cloud на Timeweb VPS](ADR-2026-05-23-migrate-to-timeweb.md) | — | | 2026-05-23 | [Переезд сервера с Yandex Cloud на Timeweb VPS](ADR-2026-05-23-migrate-to-timeweb.md) | — |
| 0000-00-00 | [Вести историю решений в виде ADR](ADR-0000-00-00-record-architecture-decisions.md) | — | | 2026-04-04 | [Apprise как шлюз нотификаций](ADR-2026-04-04-apprise-notifications.md) | — |
| 2025-12-13 | [Обновление ОС пересборкой на свежем сервере](ADR-2025-12-13-os-upgrade-via-server-rebuild.md) | — |
| 2025-12-07 | [Данные приложений на отдельном диске](ADR-2025-12-07-app-data-on-separate-disk.md) | — |
| 2025-05-07 | [Authelia вместо Keycloak для SSO](ADR-2025-05-07-authelia-sso.md) | — |
| 0000-00-00 | [Вести историю решений в виде ADR](ADR-0000-00-00-record-architecture-decisions.md) | — |