docs(agent): R1.11-R1.13 — podman ports, x-ui.db rollback, panel TLS

Also fixes R1 numbering: two items were both labelled '8', so reality443Forwarding counted as ninth while AGENTS.md, traps and f2e70bb already referenced it as R1.10. Verification commands were executed against the live host: '{{json .Ports}}' and 'exec xray version' both fail, corrected to .NetworkSettings.Ports and /app/bin/xray-linux-amd64.
This commit is contained in:
2026-10-10 21:43:00 +03:00
parent 31f13ae365
commit 6a5b075039
3 changed files with 82 additions and 21 deletions
+70 -14
View File
@@ -35,26 +35,57 @@
7. **sops-пути — через `config.sops.secrets.<name>.path`.** Любой
`path =` override на sops-блоке делает хардкод-потребителя молча
сломанным: rebuild зелёный, сервис стартует, контент пустой. См. ADR-0001.
8. **Backups: external/unknown — accepted risk.** На 2026-10-10 open question
8. **Версия ядра Xray — состояние UI-панели 3x-ui, не Nix.** Ядро
ставится через UI панели (UI → xray version) и хранится в её
sqlite-БД. Перед любым деплоем/ребутом 3x-ui — проверить версию
ядра в панели. Nix декларирует панель (`:latest`), но не ядро.
9. **Backups: external/unknown — accepted risk.** На 2026-10-10 open question
5.6 («где бэкапы, как проверяются?») не отвечен владельцем. В этом
репозитории **не декларируется** ни одна бэкап-стратегия. Failure modes
(потеря `/dev/sdc1` = потеря всех 9 сервисов на sapphira) перечислены
в `.agent/decisions/0002-backups-external.md`. Если в будущем
бэкап-система появится — отменить этот R1.9 и зафиксировать R1.x
про регулярную верификацию.
8. **Версия ядра Xray — состояние UI-панели 3x-ui, не Nix.** Ядро
ставится через UI панели (UI → xray version) и хранится в её
sqlite-БД. Перед любым деплоем/ребутом 3x-ui на sapphira —
проверить версию ядра в панели. Nix декларирует панель (`:latest`),
но не ядро.
9. **`reality443Forwarding = true` на VDS обязателен, НЕ удалять.**
`modules/vds/nginx.nix` маршрутизирует реальный `443` через stream:
`pubray1.zeroq.su → 127.0.0.1:2049` (панель), всё остальное
(в т.ч. SNI `media.mediavitrina.ru` для REALITY-клиентов) →
`127.0.0.1:15380 → container:443`. Маппинг `127.0.0.1:15380:443/tcp`
публикует опция `reality443Forwarding` (T10/C5 «погасил» её 2026-10-10 —
Xray REALITY стал недоступен при живых SSH и pubray1.zeroq.su;
восстановлено `07a0437`, manifest T10 → status `pending`).
10. **`reality443Forwarding = true` на VDS обязателен, НЕ удалять.**
`modules/vds/nginx.nix` маршрутизирует реальный `443` через stream:
`pubray1.zeroq.su → 127.0.0.1:2049` (панель), всё остальное
(в т.ч. SNI `media.mediavitrina.ru` для REALITY-клиентов) →
`127.0.0.1:15380 → container:443`. Маппинг `127.0.0.1:15380:443/tcp`
публикует опция `reality443Forwarding` (T10/C5 «погасил» её 2026-10-10 —
Xray REALITY стал недоступен при живых SSH и pubray1.zeroq.su;
восстановлено `07a0437`, manifest T10 → status `pending`).
**Сигнатура отказа НЕ выглядит как «Xray упал»** (2026-10-10, T10):
контейнер здоров, `restarts=0`, ядро 26.7.28 на месте, SSH жив, панель по
SNI `pubray1.zeroq.su` отвечает валидным сертификатом — но в журнале nginx
`connect() to 127.0.0.1:15380 failed (111: Connection refused)` и масса
`worker_connections are not enough`. Диагностировать «панель/Xray» надо
**пробой порта 15380 и `podman inspect .NetworkSettings.Ports`**, а не по симптому.
11. **Декларация портов ≠ runtime.** `ports` в
`virtualisation.oci-containers.containers."3xui_app"`
(`modules/containers/3x-ui.nix:26-35,68`) применяются **только при
пересоздании контейнера**. Правка Nix без `nixos-rebuild switch` не меняет
ничего; проверка после деплоя — обязательна:
```bash
sudo podman inspect 3xui_app --format '{{json .NetworkSettings.Ports}}' # ждём 15380
```
Любой ребилд, пересоздающий `3xui_app`, = окно недоступности REALITY
(2026-10-10: `07a0437` 17:54:18 → контейнер пересоздан 17:55:38).
Клиенты в это окно уходят в ретрай-флуд (см. R1.12 и ADR-0003).
12. **`x-ui.db` не откатывать на `x-ui.db.bak.1787862834`.** Живая БД —
`/mnt/services/nodes/otreca/3x-ui/db/x-ui.db` (в контейнере
`/etc/x-ui/x-ui.db`), схема **v3**, колонка `stream_settings`.
Бэкап от 2026-08-27 (311296 B) — **другая конфигурационная эпоха**:
инбаунды `id` 3/39/15/33 на портах **14380/14480/14910/14920**
(tcp/xhttp/xhttp/grpc), 7 клиентов, без `dest media.mediavitrina.ru`.
Текущая БД: `id` 42/45/46 на **443/8443/18443** (xhttp+reality), 11 клиентов.
Откат заменит рабочие инбаунды и обесценит все 11 клиентских конфигов.
13. **TLS терминирует панель 3x-ui, не nginx.** На otreca nginx в `stream`
делает только `ssl_preread` и проксирует сырой TCP; TLS живёт **внутри**
контейнера. Сертификат: хост `/var/lib/acme/pubray1.zeroq.su/{fullchain,key}.pem`
→ bind-mount `ro` в `/root/cert/*`; в настройках панели
`webCertFile=/root/cert/fullchain.pem`, `webKeyFile=/root/cert/key.pem`.
**Не добавлять** TLS-терминирующий `server {}` для `pubray1.zeroq.su` —
перекроет stream-SNI карту и убьёт и панель, и REALITY.
### R2. home-manager `Service` ≠ `serviceConfig`
@@ -111,6 +142,8 @@ nix build .#nixosConfigurations.<хост>.config.system.build.toplevel --dry-ru
| `users.nix:66` | `uid = if hostname == "sapphira" then 1001 else …` | Костыль под 1000 = удалённый `yuyus`; удалять только после миграции ФС |
| `3x-ui.nix:54` | `image = …:latest` | Панель намеренно latest; ядро Xray — состояние панели, см. R1.8 |
| `3x-ui.nix:33-35` | `reality443Forwarding = true` на VDS | **Обязательно, НЕ удалять** (R1.10). nginx stream (`vds/nginx.nix`) маршрутизирует `443 → 127.0.0.1:15380 → container:443`; без маппинга Xray REALITY мёртв. Удаление T10/C5 сломало — восстановлено `07a0437` |
| `vds/nginx.nix`, `events {}` | Пустой блок → `worker_connections` = **512** (дефолт) | Не баг, но и не запас: при окне недоступности REALITY клиенты дают ретрай-флуд и исчерпывают 512 → «не работает всё» даже после починки первопричины (2026-10-10: 1668 ошибок за ~40 мин). Известный пробел, задача не заведена |
| Настройки панели, `webBasePath = /pubray/` | `GET https://pubray1.zeroq.su/` → **404, 0 байт** | Панель жива, корень не корень. Реальный URL — `https://pubray1.zeroq.su/pubray/` (HTTP 200). `/subs/` без токена тоже 404 — это норма. Не «чинить» nginx под `/` |
| `server/default.nix:37-50` | 14 закомментированных модулей (13 архивировано, 1 stirling-pdf удалён в 5dd7a58) | Отключены осознанно, см. задачу T16 |
| `opencode.nix:339` | `systemd.user.services.opencode-web.Service` | `serviceConfig` рендерится в секцию `[serviceConfig]`, systemd молча игнорирует (`c73a698`); см. R2 |
| `vds.nix:73-91` | nftables без финального правила | Известный пробел, см. задачу A3 |
@@ -159,8 +192,31 @@ systemctl show postgresql -p Requires -p After | tr ' ' '\n' | grep -E 'mnt-|hom
# sops
sops --version
# цепочка 3x-ui REALITY на otreca (после любого деплоя, трогающего 3x-ui/nginx)
sudo podman inspect 3xui_app --format '{{json .NetworkSettings.Ports}}' # есть 15380->443
sudo podman exec 3xui_app /app/bin/xray-linux-amd64 version # ожидаем 26.7.x
curl -ks --resolve pubray1.zeroq.su:443:127.0.0.1 -o /dev/null \
-w '%{http_code}\n' https://pubray1.zeroq.su/pubray/ # ожидаем 200
sudo journalctl -u nginx --since '-10 min' | grep -cE 'worker_connections|Connection refused' # ожидаем 0
```
## Диагностика «REALITY на otreca не работает» (порядок, 2026-10-10)
1. `sudo podman inspect 3xui_app --format '{{json .NetworkSettings.Ports}}'` — есть ли `15380->443`.
Нет → R1.10/R1.11 (декларация разошлась с runtime), контейнер не пересоздан.
2. `sudo podman exec 3xui_app /app/bin/xray-linux-amd64 version` — должно быть
26.7.x (R1.8). Не 26.9.x. **В `$PATH` контейнера бинаря нет** — только
полный путь.
3. `sudo podman exec 3xui_app python3 -c "import sqlite3;…"` — `inbounds` в
`x-ui.db` (колонка `stream_settings`): порты 443/8443, `network=xhttp`,
`security=reality`, `enable=1`. Сверить с `/app/bin/config.json` внутри контейнера.
4. Проба 443 снаружи: TLS с SNI `media.mediavitrina.ru` должен вернуть
steal-сертификат `*.mediavitrina.ru`; SNI `pubray1.zeroq.su` — валидный
сертификат панели.
5. Только если 1–4 зелёные, а пользователь всё ещё видит отказ — проблема
клиентская (старый конфиг, клиент без поддержки `xhttp`).
## Конвенции проекта
- `xlib` (в `lib/xlib/`) — чистые данные: identity (`device`), capability flags,