mirror of
https://github.com/oqyude/nixos.git
synced 2026-10-11 14:27:26 +03:00
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:
@@ -17,13 +17,13 @@
|
|||||||
|---|---|
|
|---|---|
|
||||||
| 16:25:52 | `0df9688` (задача T10) — удалён `reality443Forwarding` |
|
| 16:25:52 | `0df9688` (задача T10) — удалён `reality443Forwarding` |
|
||||||
| 17:05:27 | первый `Connection refused` к `127.0.0.1:15380` в журнале nginx |
|
| 17:05:27 | первый `Connection refused` к `127.0.0.1:15380` в журнале nginx |
|
||||||
| 17:07:33 | первое `worker_connections are not enough` (с 37.128.246.126) |
|
| 17:07:33 | первое `worker_connections are not enough` (адрес обезличен) |
|
||||||
| ~17:15 | клиенты уходят в ретрай-петлю: ~1668 ошибок за ~40 мин |
|
| ~17:15 | клиенты уходят в ретрай-петлю: ~1668 ошибок за ~40 мин |
|
||||||
| 17:30:58 | `37b4956` — revert nftables (T3) |
|
| 17:30:58 | `37b4956` — revert nftables (T3) |
|
||||||
| 17:54:18 | `07a0437` — `reality443Forwarding` восстановлен |
|
| 17:54:18 | `07a0437` — `reality443Forwarding` восстановлен |
|
||||||
| 17:55:38 | контейнер `3xui_app` пересоздан с `127.0.0.1:15380:443/tcp` |
|
| 17:55:38 | контейнер `3xui_app` пересоздан с `127.0.0.1:15380:443/tcp` |
|
||||||
| ~18:05+ | флуд прекращается, ошибок 0 за 36 мин |
|
| ~18:05+ | флуд прекращается, ошибок 0 за 36 мин |
|
||||||
| 19:16–19:19 | живые REALITY-сессии, `oqyude` и `snity` online |
|
| 19:16–19:19 | живые REALITY-сессии, клиенты online |
|
||||||
|
|
||||||
Два вывода, которые неочевидны и потому требуют фиксации:
|
Два вывода, которые неочевидны и потому требуют фиксации:
|
||||||
|
|
||||||
@@ -35,11 +35,11 @@
|
|||||||
|
|
||||||
2. **`worker_connections are not enough` — вторичный симптом, а не причина.**
|
2. **`worker_connections are not enough` — вторичный симптом, а не причина.**
|
||||||
nginx имеет пустой `events {}` → `worker_connections` = 512 (дефолт). Пока
|
nginx имеет пустой `events {}` → `worker_connections` = 512 (дефолт). Пока
|
||||||
маршрут на 443 был мёртв, реальные клиенты (37.128.246.126 — lanta-me,
|
маршрут на 443 был мёртв, реальные клиенты слали 517-байтные ClientHello
|
||||||
Тамбов; 213.135.154.225 — Ростелеком, Тамбов) слали 517-байтные
|
в цикле и выедали 512 соединений. Из-за этого «не работало всё» даже там,
|
||||||
ClientHello в цикле и выедали 512 соединений. Из-за этого «не работало
|
где конкретная причина уже была устранена, и создавался флуд в логах,
|
||||||
всё» даже там, где конкретная причина уже была устранена, и создавался
|
уводящий от настоящей причины. Источники флуда — два адреса /24 из
|
||||||
флуд в логах, уводящий от настоящей причины.
|
разных сетей; адреса и провайдеры обезличены (репозиторий публичный).
|
||||||
|
|
||||||
Отдельно: `x-ui.db.bak.1787862834` (2026-08-27) при поверхностном взгляде
|
Отдельно: `x-ui.db.bak.1787862834` (2026-08-27) при поверхностном взгляде
|
||||||
выглядит как «бэкап, который можно откатить». Это **другая конфигурационная
|
выглядит как «бэкап, который можно откатить». Это **другая конфигурационная
|
||||||
|
|||||||
@@ -35,26 +35,57 @@
|
|||||||
7. **sops-пути — через `config.sops.secrets.<name>.path`.** Любой
|
7. **sops-пути — через `config.sops.secrets.<name>.path`.** Любой
|
||||||
`path =` override на sops-блоке делает хардкод-потребителя молча
|
`path =` override на sops-блоке делает хардкод-потребителя молча
|
||||||
сломанным: rebuild зелёный, сервис стартует, контент пустой. См. ADR-0001.
|
сломанным: 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 («где бэкапы, как проверяются?») не отвечен владельцем. В этом
|
5.6 («где бэкапы, как проверяются?») не отвечен владельцем. В этом
|
||||||
репозитории **не декларируется** ни одна бэкап-стратегия. Failure modes
|
репозитории **не декларируется** ни одна бэкап-стратегия. Failure modes
|
||||||
(потеря `/dev/sdc1` = потеря всех 9 сервисов на sapphira) перечислены
|
(потеря `/dev/sdc1` = потеря всех 9 сервисов на sapphira) перечислены
|
||||||
в `.agent/decisions/0002-backups-external.md`. Если в будущем
|
в `.agent/decisions/0002-backups-external.md`. Если в будущем
|
||||||
бэкап-система появится — отменить этот R1.9 и зафиксировать R1.x
|
бэкап-система появится — отменить этот R1.9 и зафиксировать R1.x
|
||||||
про регулярную верификацию.
|
про регулярную верификацию.
|
||||||
8. **Версия ядра Xray — состояние UI-панели 3x-ui, не Nix.** Ядро
|
10. **`reality443Forwarding = true` на VDS обязателен, НЕ удалять.**
|
||||||
ставится через UI панели (UI → xray version) и хранится в её
|
`modules/vds/nginx.nix` маршрутизирует реальный `443` через stream:
|
||||||
sqlite-БД. Перед любым деплоем/ребутом 3x-ui на sapphira —
|
`pubray1.zeroq.su → 127.0.0.1:2049` (панель), всё остальное
|
||||||
проверить версию ядра в панели. Nix декларирует панель (`:latest`),
|
(в т.ч. SNI `media.mediavitrina.ru` для REALITY-клиентов) →
|
||||||
но не ядро.
|
`127.0.0.1:15380 → container:443`. Маппинг `127.0.0.1:15380:443/tcp`
|
||||||
9. **`reality443Forwarding = true` на VDS обязателен, НЕ удалять.**
|
публикует опция `reality443Forwarding` (T10/C5 «погасил» её 2026-10-10 —
|
||||||
`modules/vds/nginx.nix` маршрутизирует реальный `443` через stream:
|
Xray REALITY стал недоступен при живых SSH и pubray1.zeroq.su;
|
||||||
`pubray1.zeroq.su → 127.0.0.1:2049` (панель), всё остальное
|
восстановлено `07a0437`, manifest T10 → status `pending`).
|
||||||
(в т.ч. SNI `media.mediavitrina.ru` для REALITY-клиентов) →
|
**Сигнатура отказа НЕ выглядит как «Xray упал»** (2026-10-10, T10):
|
||||||
`127.0.0.1:15380 → container:443`. Маппинг `127.0.0.1:15380:443/tcp`
|
контейнер здоров, `restarts=0`, ядро 26.7.28 на месте, SSH жив, панель по
|
||||||
публикует опция `reality443Forwarding` (T10/C5 «погасил» её 2026-10-10 —
|
SNI `pubray1.zeroq.su` отвечает валидным сертификатом — но в журнале nginx
|
||||||
Xray REALITY стал недоступен при живых SSH и pubray1.zeroq.su;
|
`connect() to 127.0.0.1:15380 failed (111: Connection refused)` и масса
|
||||||
восстановлено `07a0437`, manifest T10 → status `pending`).
|
`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`
|
### 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`; удалять только после миграции ФС |
|
| `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: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` |
|
| `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 |
|
| `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 |
|
| `opencode.nix:339` | `systemd.user.services.opencode-web.Service` | `serviceConfig` рендерится в секцию `[serviceConfig]`, systemd молча игнорирует (`c73a698`); см. R2 |
|
||||||
| `vds.nix:73-91` | nftables без финального правила | Известный пробел, см. задачу A3 |
|
| `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
|
||||||
sops --version
|
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,
|
- `xlib` (в `lib/xlib/`) — чистые данные: identity (`device`), capability flags,
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ flake.nix
|
|||||||
5. **3x-ui заморожен.** Панель на `:latest`, ядро Xray на 26.7.x. Миграция на 26.9.x провалена. → задачи T6–T10.
|
5. **3x-ui заморожен.** Панель на `:latest`, ядро Xray на 26.7.x. Миграция на 26.9.x провалена. → задачи T6–T10.
|
||||||
6. **nftables на VDS требует явной финальной политики.** Текущий ruleset — без финального правила → неявный accept. → задача T3.
|
6. **nftables на VDS требует явной финальной политики.** Текущий ruleset — без финального правила → неявный accept. → задача T3.
|
||||||
7. **sops-пути — через `config.sops.secrets.<name>.path`.** Любой `path =` override на sops-блоке делает хардкод-потребителя молча сломанным. → ADR-0001.
|
7. **sops-пути — через `config.sops.secrets.<name>.path`.** Любой `path =` override на sops-блоке делает хардкод-потребителя молча сломанным. → ADR-0001.
|
||||||
|
8. **Декларация портов ≠ runtime.** `ports` контейнера `3xui_app` применяются только при пересоздании; правка Nix без `nixos-rebuild` не меняет ничего. Проверка: `podman inspect 3xui_app --format '{{json .NetworkSettings.Ports}}'`. → R1.11, ADR-0003.
|
||||||
|
9. **`x-ui.db` не откатывать на `x-ui.db.bak.1787862834`.** Бэкап от 2026-08-27 — другая эпоха (порты 14380/14480/14910/14920, 7 клиентов). Откат убьёт рабочие 443/8443 и все 11 конфигов. → R1.12, ADR-0003.
|
||||||
|
10. **TLS терминирует панель 3x-ui, не nginx.** nginx делает только `ssl_preread` и проксирует сырой TCP; сертификат смонтирован в контейнер `ro`. TLS-терминирующий `server {}` для `pubray1.zeroq.su` перекроет stream-SNI и убьёт и панель, и REALITY. → R1.13, ADR-0003.
|
||||||
|
|
||||||
## Ловушки (выглядит сломанным, намеренно)
|
## Ловушки (выглядит сломанным, намеренно)
|
||||||
|
|
||||||
@@ -85,6 +88,8 @@ flake.nix
|
|||||||
| `users.nix:66` | `uid = if hostname == "sapphira" then 1001 else …` | Костыль под 1000 = удалённый `yuyus`; удалять только после миграции ФС |
|
| `users.nix:66` | `uid = if hostname == "sapphira" then 1001 else …` | Костыль под 1000 = удалённый `yuyus`; удалять только после миграции ФС |
|
||||||
| `3x-ui.nix:54` | `image = …:latest` | Панель намеренно latest; ядро Xray — на 26.7.x |
|
| `3x-ui.nix:54` | `image = …:latest` | Панель намеренно latest; ядро Xray — на 26.7.x |
|
||||||
| `3x-ui.nix:33-35` | `reality443Forwarding = true` на VDS | **Обязательно, НЕ удалять.** nginx stream (`vds/nginx.nix`) маршрутизирует `443 → 127.0.0.1:15380 → container:443`; без маппинга Xray REALITY мёртв. Удаление T10/C5 сломало — восстановлено `07a0437` |
|
| `3x-ui.nix:33-35` | `reality443Forwarding = true` на VDS | **Обязательно, НЕ удалять.** 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 → «не работает всё» даже после починки первопричины (1668 ошибок за ~40 мин). Известный пробел |
|
||||||
|
| Настройки панели | `GET https://pubray1.zeroq.su/` → **404** | Панель жива: `webBasePath=/pubray/`, реальный URL `https://pubray1.zeroq.su/pubray/`. Не «чинить» nginx под `/` |
|
||||||
| `server/default.nix:37-50` | 14 закомментированных модулей (13 архивировано, 1 stirling-pdf удалён в 5dd7a58) | Отключены осознанно, см. задачу T16 |
|
| `server/default.nix:37-50` | 14 закомментированных модулей (13 архивировано, 1 stirling-pdf удалён в 5dd7a58) | Отключены осознанно, см. задачу T16 |
|
||||||
| `opencode.nix:339` | `systemd.user.services.opencode-web.Service` | `serviceConfig` рендерится в секцию `[serviceConfig]`, systemd молча игнорирует; см. R2 |
|
| `opencode.nix:339` | `systemd.user.services.opencode-web.Service` | `serviceConfig` рендерится в секцию `[serviceConfig]`, systemd молча игнорирует; см. R2 |
|
||||||
| `vds.nix:73-91` | nftables без финального правила | Известный пробел, см. задачу T3 |
|
| `vds.nix:73-91` | nftables без финального правила | Известный пробел, см. задачу T3 |
|
||||||
|
|||||||
Reference in New Issue
Block a user