Files
knowledge-base/decisions/2026-06-27-homepage-dashboard-lxc145.md
dttb 3fe379f12c Homepage дашборд на dash.dttb.ru (LXC 145): live-виджеты Proxmox/NPM/Gitea/NC, Basic Auth
- LXC 145 homepage, Docker, 22 сервиса в 5 группах
- read-only доступы: PVEAuditor токен, Gitea PAT, NC app-password
- грабли: docker.io SNI-блок РКН (зеркало Яндекса), split-DNS hosts, NPM+authentik forward-auth
- authentik forward-auth отложен (localhost в authorize) → пока NPM Basic Auth

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 00:23:13 +03:00

69 lines
6.2 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.
---
date: 2026-06-27
type: decision
tags: [dttb, dashboard, homepage, proxmox, authentik, npm]
---
# Homepage — единый дашборд home lab (LXC 145)
## Контекст
Зоопарк сервисов dttb разросся (42 VM/LXC). Нужна одна точка входа — карта инфраструктуры с живыми метриками. Выбран [Homepage](https://gethomepage.dev) (`gethomepage/homepage`) — нативные виджеты под бо́льшую часть стека.
## Что развёрнуто
- **LXC 145 `homepage`** — Debian 12, unprivileged + nesting/keyctl, 2 vCPU / 1 GB / 8 GB на `work`, статика **10.0.0.145**, nameserver 1.1.1.1.
- Docker `ghcr.io/gethomepage/homepage:latest`, `-p 3000:3000`, `--env-file /opt/homepage/.env`, volume `/opt/homepage/config`.
- Веб: **https://dash.dttb.ru** (NPM proxy host **id 42**, LE cert **id 134** до 2026-09-24) за **NPM Basic Auth** (access-list id 5, `oleg`/`OL260380eg`). LAN/NetBird — `http://10.0.0.145:3000` без авторизации.
- ⚠️ **authentik forward-auth НЕ боевой** (отложен) — см. грабли #4. Enforcement работал (unauth→302 в authentik), но embedded-outpost строит authorize-URL как `http://localhost` (игнорит `authentik_host_browser`, а `authentik_host=https://auth.dttb.ru` упирается в зависший hairpin LXC144→NPM). Плюс Олег ещё не прошёл 2FA-enrollment в authentik. Объекты (provider/app/outpost) оставлены готовыми, гейт пока Basic Auth.
- 5 групп / 22 сервиса: Инфраструктура, Облако и данные, AI-боты и инструменты, Доступ и безопасность, Дом-сеть-медиа.
## Live-виджеты (read-only доступы — не мастер-креды)
| Сервис | Виджет | Доступ |
|--------|--------|--------|
| Proxmox VE | proxmox | API-токен `homepage@pve!homepage` (роль **PVEAuditor**, privsep 0) |
| Nginx Proxy Manager | nginxproxymanager | логин it5870@yandex.ru (виджет сам берёт JWT) |
| Gitea | gitea | read-only PAT `homepage-dashboard` (scopes read:repository/issue/user/org/notification/misc) |
| Nextcloud | nextcloud | admin + **app-password** (serverinfo API) |
Остальное — ping-плитки (siteMonitor на внутренний IP): UniFi, Vaultwarden, LinkWarden, ZimaOS, Антошка, SwarmClaw, German, Open WebUI, OmniRoute, code-server, authentik, RustDesk, Mailcow, Amnezia, Home Assistant, WatchYourLAN, PBS, pve-147.
## Секреты
`/opt/homepage/.env` (chmod 600, **НЕ в vault, не в git**): `HOMEPAGE_VAR_*` (proxmox token, npm/nc creds, gitea token) + `HOMEPAGE_ALLOWED_HOSTS=dash.dttb.ru,10.0.0.145:3000,localhost:3000`. В `services.yaml` — только плейсхолдеры `{{HOMEPAGE_VAR_*}}`.
## Грабли (за них наступали)
1. **`download.docker.com` SNI-блок РКН** (`tlsv1 unrecognized name`) — DNS отдаёт реальный CloudFront, но РКН режет по SNI. Фикс: `docker.io` из репо Debian, а сам apt переключён на **`mirror.yandex.ru`** (deb.debian.org=Fastly тоже троттлится из РФ).
2. **Nextcloud-виджет и split-DNS**`dttb.ru` из контейнера (DNS 1.1.1.1) резолвится в публичный 176.62.183.186 → хайрпин через WAN. Фикс: `/etc/hosts``10.0.0.195 dttb.ru` (идёт прямо на NPM).
3. **NPM + authentik forward-auth, duplicate `location /`** — NPM кладёт `advanced_config` ПОСЛЕ своего `location /` (стр. 72 vs 96 в `42.conf`). Свой `location /` в сниппет = nginx duplicate location → конфиг не сохранится. Решение: `auth_request` на уровне **server** (наследуется в NPM-овский `location /`), а в `location /outpost.goauthentik.io` и `@goauthentik_proxy_signin`**`auth_request off;`** (иначе рекурсия auth-сабреквеста сам в себя).
4. **`http://localhost` в authorize-redirect** — embedded outpost не знал внешний URL. Фикс: outpost config **`authentik_host_browser=https://auth.dttb.ru`** + рестарт `server`/`worker` (config подхватывается рестартом, не сразу).
5. authentik objects: proxy provider pk **3** (`forward_single`, external_host https://dash.dttb.ru), application slug **`dash`**, привязан к embedded outpost `88286dc5-…`.
## NPM advanced_config (server-level auth_request)
```nginx
location /outpost.goauthentik.io {
auth_request off;
proxy_pass http://10.0.0.144:9000/outpost.goauthentik.io;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
location @goauthentik_proxy_signin {
internal; auth_request off;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
}
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
```
## TODO / можно докрутить
- **authentik forward-auth → боевой**: починить `localhost` в authorize (embedded outpost). Варианты: standalone-outpost контейнер на dash-LXC; либо разобраться, почему `authentik_host_browser` не применяется в 2026.5.3; нужен живой браузерный тест + 2FA-enrollment Олега. Тогда снять Basic Auth (access-list 5).
- UniFi/Vaultwarden можно перевести из плиток в live-виджеты (нужны read-only креды/токены).
См. [[../projects/dttb/proxmox-inventory#LXC 145 — homepage Dashboard]], [[2026-06-26-authentik-sso-deploy]].