German: веб-дашборд Hermes на german.dttb.ru (NPM #40, LE id130)

Подняли родную панель hermes dashboard на LXC 141 за NPM с basic_auth.
Грабля: флаг --insecure отключает cookie-gate (включает легаси _SESSION_TOKEN)
→ login ok, но всё внутри 401. Фикс: бинд 0.0.0.0 БЕЗ --insecure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
dttb
2026-06-26 17:15:19 +03:00
parent 14249577bc
commit 12705f148f
4 changed files with 25 additions and 2 deletions

View File

@@ -65,6 +65,16 @@ tags: [decision, ai, hermes, telegram, lxc, assistant]
- **Enroll с `--disable-dns`**: `netbird up --setup-key <KEY> --disable-dns --hostname german`. Это сознательно — на LXC 132/137 NetBird-DNS (resolv.conf через wt0) уже ломал связность; German держит свой `1.1.1.1`/`8.8.8.8` и ходит по IP. Magic-DNS `*.netbird.cloud` в контейнере НЕ резолвится (`search dttb.ru` хайджачит) — **только по IP 100.70.x**.
- Проверено: openclaw `100.70.167.54:18789` → 200; github/telegram/OmniRoute/DNS целы; `netbird` autostart enabled; hermes-german не пострадал.
## Веб-дашборд `german.dttb.ru` (добавлено 2026-06-26)
Родная веб-панель Hermes (`hermes dashboard`: чат + config + sessions + встроенный PTY-терминал), не путать с Open WebUI.
- **systemd `hermes-dashboard.service`** (рядом с gateway, не вместо): `hermes dashboard --host 0.0.0.0 --port 9119 --skip-build --no-open`, Restart=always, бинд `0.0.0.0:9119`.
- **Фронт пришлось собрать**: `web/dist` отсутствовал. `cd /usr/local/lib/hermes-agent/web && npm install && npm run build` → vite кладёт в `../hermes_cli/web_dist` (outDir в vite.config, НЕ `web/dist`), оттуда `--skip-build` и отдаёт. node v22 (warning EBADENGINE про node≥24 — не критично).
- **NPM** #40 (10.0.0.195) `german.dttb.ru``10.0.0.141:9119`, force-SSL+WSS+HTTP2, block-exploits. LE-серт **id130** (HTTP-01, до 24.09.2026). NPM v2.14: cert-create только `meta:{}` (email/agree/dns_challenge = «additional properties»).
- **DNS**: публичный A `german.dttb.ru``176.62.183.186` добавлен через Spaceweb API (`editMain` `action:add`, один вызов — циклом ломает зону). Локально wildcard `*.dttb.ru``10.0.0.195` уже резолвил. Проверять пропагацию только DoH (8.8.8.8/resolve), `dig` хайджачится локальным DNS.
- **Аутентификация — `dashboard.basic_auth`** в `/root/.hermes/config.yaml`: `username: oleg`, `password_hash` (scrypt, через `plugins.dashboard_auth.basic.hash_password`), `secret` (32 байта hex), `session_ttl_seconds: 43200`, `public_url: https://german.dttb.ru`. Плейнтекст-пароль не хранится. Креды в [[../projects/dttb/credentials.md]]. Бэкап `config.yaml.bak-dashboard-20260626`.
- ⚠️ **ГЛАВНАЯ ГРАБЛЯ — `--insecure` отключает gate.** `should_require_auth(host, allow_public)`: non-loopback + `--insecure``auth_required=False` → активен легаси `_SESSION_TOKEN`-middleware (ephemeral токен, инжектится в loopback-HTML), basic-cookie-gate `gated_auth_middleware` становится no-op. Симптом: `/auth/password-login``{"ok":true}` (кука минтится), но `/api/auth/me` + все данные→401. Провайдер/секрет/токен/куки исправны (доказано: офлайн `_unsign(live_token, _resolve_secret(cfg))`→payload ок; round-trip провайдера→ok). **Фикс = убрать `--insecure`** (бинд `0.0.0.0` без него: `auth_required=True`, провайдер `basic`, и `0.0.0.0` принимает любой Host — иначе явный бинд на IP даёт 400 «Invalid Host header» на NPM-домен). Hermes сам это документирует: `dashboard_register.py:218` «To require login (LAN/public): hermes dashboard --host 0.0.0.0». Лог-маркер: `Dashboard binding to 0.0.0.0 with OAuth auth gate enabled. Providers: basic`.
- Проверено end-to-end через NPM: `https://german.dttb.ru` login `oleg``/api/auth/me`→200, `/api/sessions`→200; http→301; серт CN german.dttb.ru. Telegram-gateway не задет (оба сервиса active+enabled).
## TODO / на будущее
- Fallback-цепочка (cc/sonnet-4-6, kr/sonnet-4.5, cx/gpt-5.4) — формат `fallback_providers` с `api_key_env` (НЕ `${VAR}` — путь резолва фолбэков не делает env-подстановку). Пока не ставил (primary надёжен).
- Настоящий web-search через self-hosted SearXNG (`SEARXNG_URL`) или ключ Tavily/Firecrawl — если ddgs будет мало.

View File

@@ -146,6 +146,16 @@ cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-admin-pwd <new-pw>
| Email | `it5870@yandex.ru` |
| Пароль | `1qaz!QAZ` |
## German Hermes Dashboard (LXC 141)
| Параметр | Значение |
|----------|----------|
| URL | https://german.dttb.ru (NPM #40 → 10.0.0.141:9119) |
| Логин | `oleg` / `German-ecddc1edea-2026` |
| Механизм | `dashboard.basic_auth` в `/root/.hermes/config.yaml` (scrypt `password_hash` + `secret`, plaintext не хранится) |
| systemd | `hermes-dashboard.service` = `hermes dashboard --host 0.0.0.0 --port 9119 --skip-build --no-open` |
| ⚠️ Грабля | **БЕЗ `--insecure`!** `--insecure` отключает cookie-gate (включает легаси `_SESSION_TOKEN`) → login проходит, но всё внутри 401. Бинд `0.0.0.0` без `--insecure` = `auth_required=True` + принимает любой Host (для NPM-домена). См. [[../../decisions/2026-06-18-german-hermes-agent-deploy]] |
## SSH-ключи и доступы
| Хост | Порт | Метод |

View File

@@ -9,7 +9,7 @@ tags: [dttb, npm]
> **NPM LXC:** 103 (10.0.0.195)
> **Панель:** https://npm.dttb.ru
>
> Последнее обновление: 2026-06-15 (добавлен unifi.dttb.ru → UniFi LXC 140)
> Последнее обновление: 2026-06-26 (добавлен german.dttb.ru → Hermes Dashboard LXC 141)
---
@@ -17,7 +17,7 @@ tags: [dttb, npm]
| Всего хостов | С SSL | Без SSL | Активных |
|--------------|-------|---------|----------|
| 22 | 18 | 4 | 22 |
| 23 | 19 | 4 | 23 |
---
@@ -53,6 +53,7 @@ tags: [dttb, npm]
| 34 | `rustdesk.umnybot.ru` | 10.0.0.190:3005 | ✅ Let's Encrypt | ✅ | ✅ | ❌ | RustDesk client web (KasmVNC, ZimaOS) — Basic Auth ACL `umnybot-kasm` |
| 36 | `unifi.dttb.ru` | 10.0.0.196:8443 (HTTPS) | ✅ Let's Encrypt | ✅ | ✅ | ✅ | **UniFi Network Application** (LXC 140) |
| 39 | `chat.dttb.ru` | 10.0.0.142:3000 | ✅ Let's Encrypt (id129) | ✅ | ✅ | ✅ | **Open WebUI** (LXC 142) — веб-клиент поверх OmniRoute |
| 40 | `german.dttb.ru` | 10.0.0.141:9119 | ✅ Let's Encrypt (id130) | ✅ | ✅ | ✅ | **Hermes Dashboard** (LXC 141) — веб-панель German; basic_auth `oleg`, см. credentials |
---
@@ -91,6 +92,7 @@ location /.well-known/matrix/client {
| 10.0.0.10 | 9443 | porteiner.dttb.ru |
| 10.0.0.43 | 21114 | remot.dttb.ru |
| 10.0.0.112 | 8840 | ip.dttb.ru |
| 10.0.0.141 | 9119 | german.dttb.ru (Hermes Dashboard) |
| 10.0.0.142 | 3000 | chat.dttb.ru (Open WebUI) |
| 10.0.0.155 | 8123 | home.dttb.ru |
| 10.0.0.169 | 8080 | office.dttb.ru |

View File

@@ -224,6 +224,7 @@ tags: [dttb, proxmox]
| ОС/рантайм | Debian 12, unprivileged + nesting, Hermes Agent v0.16.0 (Python, `/usr/local/lib/hermes-agent`, данные `/root/.hermes`) |
| Ресурсы | 2 vCPU / 3 GB / 12 GB (rootfs на local-lvm) |
| Telegram | бот **«Герман Непомнящий»** @german_dttb_bot — заперт на Олега (`TELEGRAM_ALLOWED_USERS=1292155421`) |
| Веб-дашборд | **https://german.dttb.ru** (NPM #40`:9119`, родная панель Hermes: чат+config+sessions+PTY). systemd `hermes-dashboard.service` (`--host 0.0.0.0` БЕЗ `--insecure`!). basic_auth `oleg`, креды в credentials. См. decision 2026-06-18 (раздел дашборд) |
| Модель | **`cc/claude-opus-4-8`** (Opus 4.8 via Max) через OmniRoute (`http://10.0.0.179:20128/v1`), fallback `kr/claude-sonnet-4.5` (free), auxiliary→main. ⚠️ 400 «out of extra usage» бывает **транзиентным** (краткий 5-час кап Max при общей нагрузке me/German/openclaw/swarmclaw/code-server) — само отпускает; проверка `curl cc/claude-opus-4-8` (small+8KB) = 200. Если 400 участятся — включить overflow на claude.ai/settings/usage |
| Workspace | `/root/german` (KB-зеркало `knowledge-base/` RO, cron `*/15` pull; `notes/` writable) |
| Сервис | systemd `hermes-german.service` (`hermes gateway run --replace`) |