--- date: 2026-06-26 type: decision tags: [dttb, sso, authentik, oidc, mfa, security] --- # authentik — SSO/IdP для home lab (LXC 144) > **Статус:** платформа развёрнута и здорова, пилот OIDC на Open WebUI + Gitea работает (серверная часть). Остался один ручной шаг Олега — первый вход + enrollment 2FA (см. ниже). > **Домен:** https://auth.dttb.ru · **Контейнер:** LXC 144 (10.0.0.144) ## Зачем Единый вход (SSO) + обязательная 2FA на сервисы home lab. Self-hosted IdP, без облака — в линию с уходом от big-tech [[project_deapple_migration]]. ## Ключевое архитектурное решение: «2FA на всё, но через нужную дверь» Олег хотел завести **все** сервисы за SSO с 2FA. Лобовой «всё за forward-auth» отвергнут — сломал бы не-браузерные клиенты (которых у нас много). Принято разделение: | Схема | Для чего | Почему | |---|---|---| | **OIDC/SAML** (вход в веб-морду через authentik+2FA, машинные пути живут штатно) | сервисы с родной поддержкой SSO: Gitea, Nextcloud, Proxmox, Portainer, Open WebUI, Grafana, Home Assistant | не ломает API, git push, WebDAV, мобилки | | **Forward-auth** (outpost + advanced-config сниппет в NPM) | голые дашборды без логина / на Basic Auth (german, KasmVNC) | NPM не имеет родного auth-поля | | **Родной 2FA** | Proxmox (встроенный TOTP/WebAuthn), NPM | не закрывать себе путь восстановления через IdP | | **Не за SSO вообще** | API (OmniRoute omni:20128/v1), webhooks (bot.dttb.ru), не-HTTP (RustDesk, IMAP/SMTP, Matrix federation), Vaultwarden (свой мастер-пароль+2FA) | forward-auth их убьёт / антипаттерн | **Почему forward-auth-везде плох именно у нас:** Nextcloud (мобилка/WebDAV/**rclone-bisync KB-синк**), Gitea (git push), OmniRoute API (openclaw/german/swarmclaw/open-webui/code-server), bot webhooks, Mailcow IMAP/SMTP, RustDesk 21115-21119, Home Assistant/Matrix/Plex клиенты — всё это не проходит SSO-редирект. ## Развёртывание (что сделано) ### Контейнер LXC 144 - Debian 12, unprivileged + nesting/keyctl, onboot=1 - 2 vCPU / 4 GB / swap 2 GB / rootfs 20 GB на storage `work` (local-lvm забит 94%) - IP статика **10.0.0.144/24**, gw 10.0.0.1, **nameserver 1.1.1.1** (против FakeIP при pull с ghcr — урок [[2026-06-22-open-webui-deploy]]) - root-пароль LXC: см. credentials - Docker 29.6 + compose (official get.docker.com) ### Стек (официальный compose, `/opt/authentik/`) - `ghcr.io/goauthentik/server:2026.5.3` — **server + worker + postgresql:16-alpine** - ⚠️ **2026.5.3 ушёл от Redis** — теперь postgres-backed cache (django_postgres_cache). Compose БЕЗ redis. Проще. - AVX-граблю (как Mongo для UniFi [[2026-06-15-unifi-controller-homelab]]) authentik **не задевает** — Python/PG/нет Mongo. - `.env`: `PG_PASS`, `AUTHENTIK_SECRET_KEY` (сгенерированы), `AUTHENTIK_BOOTSTRAP_PASSWORD`/`_EMAIL`, порты 9000/9443. Бэкап секретов — в самом `.env` контейнера. - Миграции БД при первом старте ~3 мин (health 503 в это время — норма, не паниковать). ### Домен auth.dttb.ru - **Публичная A-запись** добавлена на Spaceweb: `auth → 176.62.183.186` (нет wildcard — у каждого поддомена своя запись). - NPM proxy host **id 41** → `10.0.0.144:9000`, **LE cert id 133**, Force SSL + HTTP/2 + WSS. - Локально/в NetBird `*.dttb.ru` = 10.0.0.195 (wildcard на роутере) — SSO работает и внутри. ### 2FA — обязательна на уровне IdP Стейдж `default-authentication-mfa-validation` переведён `not_configured_action: skip → configure`, `configuration_stages = [TOTP-setup, WebAuthn-setup]`. Любой вход без устройства **принуждает** к установке TOTP или passkey. Действует на ВСЕ OIDC-логины (они идут через default-authentication-flow). ### Пилот OIDC (работает серверно) | Сервис | authentik app/slug | client_id | redirect_uri | как подключён | |---|---|---|---|---| | **Open WebUI** (chat.dttb.ru, LXC 142) | `open-webui` | `1G7PLkPU…` | `https://chat.dttb.ru/oauth/oidc/callback` | контейнер пересоздан с OAuth env, скрипт `/root/recreate-owui.sh`. Локальный логин СОХРАНЁН (`ENABLE_LOGIN_FORM` не трогали), `OAUTH_MERGE_ACCOUNTS_BY_EMAIL=true` | | **Gitea** (git.dttb.ru, LXC 136) | `gitea` | `AYl8jNZv…` | `https://git.dttb.ru/user/oauth2/authentik/callback` | auth source «authentik» (id 1) через `gitea admin auth add-oauth`. **ROOT_URL изменён** `http://10.0.0.189:3000/ → https://git.dttb.ru/` (иначе callback не совпадал). Бэкап `app.ini.bak-preauthentik-20260626`. git push/SSH не затронуты | Секреты client_secret — в credentials. ## ⚠️ Остался ручной шаг Олега (1 раз) SSO-вход нельзя докрутить headless — нужен браузер Олега: 1. Зайти на **https://auth.dttb.ru**, логин `akadmin` / пароль (см. credentials). 2. Система **сама предложит установить 2FA** (TOTP — отсканировать QR в Google Authenticator/2FAS, или passkey). Установить. 3. Проверить вход через SSO: на chat.dttb.ru кнопка «Continue with authentik», на git.dttb.ru «Sign in with authentik». 4. (Опц.) создать личного пользователя `oleg` вместо akadmin, akadmin оставить как break-glass. ## Плюсы / минусы **Плюсы:** единый вход + 2FA на все совместимые сервисы; централизованное управление (можно выдавать семье/клиентам скоуп-доступ); forward-auth прикроет голые панели; self-hosted; журнал входов. **Минусы/риски (и митигация):** - **SPOF/lockout:** упал authentik → нет SSO-входа. → критичную инфру (Proxmox/NPM/Vaultwarden) НЕ гейтим, у сервисов сохраняем родной admin-логин как fallback. - **Публичный IdP = поверхность атаки.** → обязательная 2FA (включена), сильные пароли. Опц. позже: geo/fail2ban, ограничить admin LAN-only. - **Лок единственного админа** при кривом MFA-flow. → recovery через API-токен (минует flow) и `ak shell` (см. ниже). ## Recovery / управление - API-токен (минует login-flow): `claude-bootstrap` — в credentials. `curl https://auth.dttb.ru/api/v3/core/users/me/ -H "Authorization: Bearer "`. - Сбросить пароль akadmin: `pct exec 144 -- bash -c "cd /opt/authentik && echo 'akadmin ' | docker compose exec -T server ak change_password akadmin"` (или через `ak shell`). - Снять обязательную 2FA (если залочило): PATCH стейджа `f3808685-…` `not_configured_action=skip` через API-токен. - Логи: `cd /opt/authentik && docker compose logs server|worker`. - Обновление: бампить `AUTHENTIK_TAG` в `/opt/authentik/.env` → `docker compose pull && up -d`. ## Spaceweb DNS — найден read-метод API К [[../projects/dttb/spaceweb-dns]]: метод чтения зоны = **`info`** (`params {domain}`), возвращает все записи с `index`/`category`. Существующие методы: `editMain`, `editMx`, `editTxt`, `info`. Добавление одной A-записи `editMain {action:"add",name,type:"A",value,prefix:""}` — безопасно (ломает зону только цикл). ## Дальше (отдельными задачами, по согласованию) Полный OIDC-роллаут: Proxmox (realm OpenID Connect), Nextcloud (app `user_oidc`/`sociallogin`), Portainer, Home Assistant, Grafana. Forward-auth demo на german.dttb.ru (Basic Auth → outpost). См. раздел «нужная дверь» выше.