diff --git a/projects/benilux/umny-server-concept.md b/projects/benilux/umny-server-concept.md index cfce63c..c0e4404 100644 --- a/projects/benilux/umny-server-concept.md +++ b/projects/benilux/umny-server-concept.md @@ -194,35 +194,74 @@ Nextcloud, медиасервер (Plex/«Flex»), торрент-клиент, **После этих шагов коробка автономна:** свой вход (Cloudflare), свои мозги (свой ключ), своя память (своя KB), свой сторож. Олег — только админ-доступ для поддержки. -> ⚠️ Cloudflare Tunnel vs текущий VPS-шлюз — это развилка по входу. Cloudflare бесплатен и автономен, но трафик идёт через Cloudflare (для домашнего сервиса ок). Решить при внедрении (раздел 8). +> ⚠️ Cloudflare Tunnel vs текущий VPS-шлюз — это развилка по входу. Cloudflare бесплатен и автономен, но трафик идёт через Cloudflare (для домашнего сервиса ок). Решить при внедрении (раздел 9). --- -## 7. План внедрения (по шагам, с проверками) +## 7. Доступ и креды — удобно и безопасно + +Требование: клиент и семья заходят в сервисы **просто**, но без дыр. Урок коробки уже оплачен — компрометация 2026-05-20 случилась именно из-за общего слабого пароля `1qaz!QAZ` ([[../../decisions/2026-05-20-benelux-compromise]]). Поэтому: **никаких общих паролей на сервисы, уникальный секрет на каждый, выдача через защищённые каналы.** + +### Модель доступа: один вход → все сервисы (SSO) + +Большинство сервисов клиент не логинит по отдельности — **единый вход**: + +- **Cosmos SSO / forward-auth** на периметре: один аккаунт Александра (логин + **обязательная 2FA/TOTP**) открывает все веб-сервисы за прокси (Nextcloud, Plex-веб, qBittorrent, Open WebUI, Homepage). Зашёл один раз — внутри ходит свободно. +- Где у сервиса свой обязательный аккаунт (Plex-приложения на ТВ, Nextcloud-клиент на телефоне) — заводим **отдельный пароль на сервис**, генерируется, не переиспользуется. +- **Семья/персонал/гости — отдельные ограниченные учётки**, не админ Александра. Ложится на уже запланированную сегментацию Wi-Fi ([[wifi-segmentation-concept]]): хозяева/персонал/гости и в сети, и в сервисах. + +### Хранение: Vaultwarden как «сейф» семьи + +- **Vaultwarden** (лёгкий, ~128 МБ) — единое хранилище паролей на дом. Все сгенерированные креды сервисов лежат там, клиент открывает по одному мастер-паролю + 2FA. +- Приложения Bitwarden на всех устройствах семьи (iOS/Android/браузер) — автозаполнение, делиться доступом без пересылки паролей в мессенджерах. +- Это и «удобно» (автозаполнение, один сейф), и «безопасно» (уникальные пароли, шифрование, не в переписке). + +### Выдача через бота — безопасно + +Бот не только ставит сервис, но и **отдаёт доступ правильно**: + +- При деплое `cosmos-deploy.sh` **генерирует пароль** (`openssl rand`), кладёт его в **Vaultwarden** через API и навешивает на сервис — пароль нигде не печатается «по умолчанию». +- Боту клиент пишет «дай доступ к облаку» → бот отвечает **ссылкой на запись в Vaultwarden** (или одноразово показывает логин). Реквизиты не оседают в истории Telegram навсегда. +- Если показывать прямо в чат — то **самоудаляющимся сообщением** и только владельцу (проверка Telegram user-id, как в approval-гейте). +- Полный реестр секретов админ-уровня (root, токены) остаётся у Олега в [[../dttb/ai-assistant-pilot/credentials]] — клиенту туда доступа нет. + +### Базовая гигиена (закрыть сразу) + +- **Сменить общий `1qaz!QAZ`** на хосте/Proxmox и в сервисах на уникальные — этот пароль «утёк» в инцидент и до сих пор живёт (root pve, Basic Auth pve). Включить 2FA на Proxmox UI. +- Внутренние сервисы **не светить в интернет** без нужды — только через SSO/Cloudflare Access; всё остальное по NetBird/LAN. +- Секреты сервисов — в `.env` (chmod 600), не в git, не в KB. + +> Итог цепочки: **деплой ботом → пароль сгенерирован → лёг в Vaultwarden → клиент входит по SSO+2FA, а где нужно — берёт из сейфа**. Удобно для семьи, при этом ни одного общего/слабого пароля. + +--- + +## 8. План внедрения (по шагам, с проверками) **Шаг 0 — замер + аудит KB.** `free -m`, `df -h /mnt/pve/Work`, `pct list` + RAM каждого LXC. **Проверить, что сейчас в памяти бота Алекс** — нет ли там общей инфры Олега (раздел 4). ✅ свободно ≥3 ГБ ОЗУ и KB понятна. **Шаг 1 — Cosmos Cloud (движок).** Поставить на хост (или LXC с nesting). Настроить, проверить API. ✅ через API поднимается тестовый контейнер. -**Шаг 2 — деплой-инструмент бота.** Написать `cosmos-deploy.sh ` с каталогом алиасов, добавить в tools агента Алекс через approval-гейт. ✅ команда боту «поставь тест» поднимает контейнер с подтверждением в TG. +**Шаг 2 — Vaultwarden + SSO периметр.** Поднять Vaultwarden («сейф» семьи) и включить Cosmos SSO/forward-auth с обязательной 2FA для Александра. ✅ один вход открывает защищённый тестовый сервис, креды лежат в сейфе. -**Шаг 3 — общая медиа-папка + торрент.** Создать `/mnt/pve/Work/media`. Бот ставит qBittorrent (volume = эта папка). ✅ тестовая закачка появляется в папке. +**Шаг 3 — деплой-инструмент бота.** Написать `cosmos-deploy.sh `: ставит сервис + **генерирует пароль (`openssl rand`) и кладёт в Vaultwarden через API**, отдаёт клиенту ссылку на запись. Добавить в tools агента через approval-гейт. ✅ «поставь тест» → контейнер поднят, пароль в сейфе, бот прислал ссылку (не сам пароль в чат). -**Шаг 4 — Plex.** Библиотека на `/mnt/Work/media`. ✅ тестовый файл играет Direct Play на ТВ/телефоне клиента. +**Шаг 4 — общая медиа-папка + торрент.** Создать `/mnt/pve/Work/media`. Бот ставит qBittorrent (volume = эта папка). ✅ тестовая закачка появляется в папке. -**Шаг 5 — Nextcloud (light).** External Storage → `/mnt/Work/media`. ✅ скачанный торрент виден и в облаке, и в Plex (сквозная интеграция — ядро ТЗ). +**Шаг 5 — Plex.** Библиотека на `/mnt/Work/media`. ✅ тестовый файл играет Direct Play на ТВ/телефоне клиента. -**Шаг 6 — изоляция KB.** Создать репозиторий `kb-benelux` в Gitea Александра (LXC104), наполнить только инфрой Бенелюкса, переключить синк/память бота на него. ✅ бот отвечает по Бенелюксу, не знает про НИИКН/dttb. +**Шаг 6 — Nextcloud (light).** External Storage → `/mnt/Work/media`. ✅ скачанный торрент виден и в облаке, и в Plex (сквозная интеграция — ядро ТЗ). -**Шаг 7 — автономный вход (Cloudflare Tunnel).** Поставить `cloudflared` на коробку, перевести `umnybot.ru` на Cloudflare DNS, опубликовать сервисы. ✅ домены работают без VPS-шлюза Олега. +**Шаг 7 — изоляция KB.** Создать репозиторий `kb-benelux` в Gitea Александра (LXC104), наполнить только инфрой Бенелюкса, переключить синк/память бота на него. ✅ бот отвечает по Бенелюксу, не знает про НИИКН/dttb. -**Шаг 8 — Open WebUI + Hermes (GLM 5.2).** Проверить баланс GLM, поставить. Open WebUI `chat.*`, Hermes — TG + `hermes.*`. ✅ оба отвечают на своём ключе. +**Шаг 8 — автономный вход (Cloudflare Tunnel).** Поставить `cloudflared` на коробку, перевести `umnybot.ru` на Cloudflare DNS, опубликовать сервисы. ✅ домены работают без VPS-шлюза Олега. -**Шаг 9 — Homepage как «рабочий стол».** Плитки на всё, живые виджеты, стартовая. ✅ клиент с одной страницы попадает в любой сервис, а бот ставит новые по запросу. +**Шаг 9 — Open WebUI + Hermes (GLM 5.2).** Проверить баланс GLM, поставить. Open WebUI `chat.*`, Hermes — TG + `hermes.*`. ✅ оба отвечают на своём ключе. + +**Шаг 10 — Homepage как «рабочий стол».** Плитки на всё, живые виджеты, стартовая. ✅ клиент с одной страницы попадает в любой сервис, а бот ставит новые по запросу. --- -## 8. Открытые вопросы (уточнить у Олега/клиента) +## 9. Открытые вопросы (уточнить у Олега/клиента) - [ ] **Аудит KB пилота** — что сейчас в памяти бота Алекс? Если там общая инфра Олега — вычистить (требование автономности/безопасности). - [ ] **Вход: Cloudflare Tunnel или остаёмся на VPS-шлюзе?** Cloudflare = автономность от Олега + работа за динамич. WAN; минус — трафик через Cloudflare. Рекомендация — Cloudflare.