From 2806307c5054d369473e5a58bd2597450a83539f Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Wed, 23 Sep 2026 21:48:02 +0600 Subject: [PATCH] [2026-09-23] eagle: family/how-to/kraken-network.md family/projects/watchlist-automation.md personal/plans/lampac-watched-to-watchlist.md --- family/how-to/kraken-network.md | 67 ++++++++++- family/projects/watchlist-automation.md | 31 ++++- personal/plans/lampac-watched-to-watchlist.md | 108 ++++++++++++++++-- 3 files changed, 188 insertions(+), 18 deletions(-) diff --git a/family/how-to/kraken-network.md b/family/how-to/kraken-network.md index 12aac2c1..c4c3b517 100644 --- a/family/how-to/kraken-network.md +++ b/family/how-to/kraken-network.md @@ -1,7 +1,7 @@ --- title: Kraken Network & Infra created: '2026-05-23' -updated: '2026-09-04' +updated: '2026-09-23' type: tech namespace: personal tags: @@ -16,17 +16,74 @@ related: # Kraken Network & Infra +## 🔴 SSH-доступ: ходим по `.14` (провод). `.15` — WiFi (обновлено 2026-09-23) + +``` +ssh kraken # → DNS отдаёт .15 (WiFi) — работает, пока wlan0 UP +ssh kraken@192.168.1.14 # → провод, основной путь +``` + +**Alex (2026-09-23): «`.15` это wifi, мы по `.14` ходим».** + +| Интерфейс | IP | MAC | Роль | +|---|---|---|---| +| **eth0** | `192.168.1.14/24` | `2c:cf:67:64:03:f3` | primary, default metric 100 | +| **wlan0** | `192.168.1.15/24` | `2c:cf:67:64:03:f4` | fallback, metric 600 | + +🔴 **`192.168.1.15` НЕ мёртвый** — прежний вывод «`.15` мёртвый» был ложным (один +таймаут принят за факт). Причина обрывов ssh — **не адрес**: +1. перегрузка sshd после ребута (`load average: 4.69`); +2. 🔴 **`sudo` без `< /dev/null` рвёт соединение** — любая sudo-команда по SSH; +3. тяжёлый `jq` в одной строке с `ssh` (json 180 KB) — обрыв. + +Обход: короткие команды, тяжёлое — файлом-скриптом, `sudo … < /dev/null`. + +### 🔴 DNS-имя `kraken` указывало на WiFi — ИСПРАВЛЕНО на роутере + +Причина: `dhcp_staticlist` нёс имя `kraken` у **обоих** интерфейсов, плюс +`/jffs/configs/dnsmasq.conf.add` имел `address=/kraken/192.168.1.15`. + +``` +БЫЛО: <2C:CF:67:64:03:F3>192.168.1.14>kraken> ← eth0 + <2C:CF:67:64:03:F4>192.168.1.15>kraken> ← wlan0, дубль имени + address=/kraken/192.168.1.15 ← жёстко на WiFi + +СТАЛО: <2C:CF:67:64:03:F3>192.168.1.14>kraken> + <2C:CF:67:64:03:F4>192.168.1.15> ← имя снято + address=/kraken/192.168.1.14 ← на провод +``` + +🔴 **Питфолл: активная DHCP-лиза (`/var/lib/misc/dnsmasq.leases`) ПЕРЕБИВАЕТ +`address=`.** Удаление строки лизы не помогает — dnsmasq пересоздаёт её. +Правки в nvram применятся **после перезагрузки роутера** (не делали — ждёт +решения Alex). Как проверить: +```bash +ssh -i ~/.ssh/id_rsa admin@192.168.1.1 'grep kraken /etc/dnsmasq.conf' # применённый +ssh -i ~/.ssh/id_rsa admin@192.168.1.1 'cat /var/lib/misc/dnsmasq.leases' # кто держит имя +dig +short kraken @192.168.1.1 +``` +Бэкапы: `/jffs/dhcp_staticlist.bak.20260923-214309`, +`/jffs/configs/dnsmasq.conf.add.bak.20260923-214309`. +Полный разбор — [[personal/plans/lampac-watched-to-watchlist]] §8.3.1. + +✅ **ASUS `192.168.1.1` по SSH работает:** `ssh -i ~/.ssh/id_rsa admin@192.168.1.1` +(не `root@`). Правки DNS/nvram — по SSH, веб-UI не нужен. + ## SSH Access ``` -ssh kraken +ssh kraken@192.168.1.14 ``` -SSH alias `kraken` resolves via `~/.ssh/config`. +SSH alias `kraken` резолвится через `~/.ssh/config` (proxy-команда: если есть +`10.99.0.2` — идём на `10.99.1.2`, иначе `nc kraken 22` → DNS → `.15`). +⚠️ WG-туннель с Mac сейчас **не поднят** (`10.99.0.2` нет) → уходит в LAN-ветку. -## Актуальная сеть (проверено 2026-09-22) +## Актуальная сеть (уточнено 2026-09-23) -> ⚠️ **Кра́кен теперь достаётся по двум адресам на ОДНОМ MAC.** ARP на роутере: и `192.168.1.14`, и `192.168.1.15` → `lladdr 2c:cf:67:64:03:f3` (один и тот же eth0 MAC). То есть `.15` числится за eth0, отдельного WiFi-MAC в ARP нет. Два default route (eth0 metric 100, wlan0 metric 600) **сосуществуют** — часть трафика может утечь в Wi-Fi. `ping` с самого Кра́кена уходил через **wlan0**, не через кабель. +> ✅ **У Кра́кена ДВА MAC — по одному на интерфейс.** Прежняя запись «`.15` +> числится за eth0, отдельного WiFi-MAC в ARP нет» **неверна**: eth0 = `…:f3`, +> wlan0 = `…:f4` (подтверждено `ip -br addr` и `dhcp_staticlist`). | Интерфейс | IP | MAC | Uplink role | |---|---|---|---| diff --git a/family/projects/watchlist-automation.md b/family/projects/watchlist-automation.md index bfb5f0fb..d048bcaa 100644 --- a/family/projects/watchlist-automation.md +++ b/family/projects/watchlist-automation.md @@ -52,10 +52,35 @@ SQLite-БД модуля `TimeCode`: План реализации синка `timecodes` → `[x]`: [[personal/plans/lampac-watched-to-watchlist]]. -### 🔴 `ssh kraken` резолвится в мёртвый `.15` — работать через `.14` +### ✅ `.14` = провод, `.15` = WiFi. Оба — один Кра́кен (Alex, 2026-09-23) -Все обрывы этой сессии — маршрут ssh, не сервисы. Детали и обход: -[[personal/tech/home-network-config]] → «Питфоллы доступа». +🔴 **Ранее в этом доке было «`ssh kraken` резолвится в мёртвый `.15`» — ЭТО НЕВЕРНО.** +`.15` не мёртвый: это **WiFi** (`wlan0`), `.14` — **провод** (`eth0`), ходим по `.14`. + +``` +eth0 UP 192.168.1.14/24 metric 100 ← основной, default route +wlan0 UP 192.168.1.15/24 metric 600 +``` + +**Настоящие причины обрывов ssh** (обе воспроизведены 2026-09-23): +1. **Перегрузка sshd** — падало при `load average: 4.69` (после ребута поднимались + контейнеры). Симптом: `Connection closed by UNKNOWN port 65535` / + `Connection timed out during banner exchange`. Лечится повтором и короткими + командами, не сменой адреса. +2. 🔴 **`sudo` через SSH без `< /dev/null` рвёт соединение.** Проверено многократно: + ```bash + ssh kraken 'sudo docker restart x && sudo docker ps' # ❌ рвётся + ssh kraken 'sudo docker restart x < /dev/null && … < /dev/null' # ✅ + ``` + Надёжнее — весь скрипт файлом: `scp` → `sudo bash /tmp/x.sh < /dev/null`. +3. **Тяжёлый `jq` в одной строке с `ssh`** (json 180 KB) — обрыв. Разбивать, тяжёлое — файлом. + +**DNS-имя `kraken` — ИСПРАВЛЕНО на роутере.** Было: `dhcp_staticlist` нёс имя `kraken` +у **обоих** интерфейсов, плюс `dnsmasq.conf.add` имел `address=/kraken/192.168.1.15` +(жёстко на WiFi). Стало: `address=/kraken/192.168.1.14`, имя у wlan0-лиза снято. +🔴 **Питфолл: живая DHCP-лиза перебивает `address=`** — поэтому DNS пока отдаёт `.15`, +правка применится после перезагрузки роутера. Полный разбор и бэкапы: +[[personal/plans/lampac-watched-to-watchlist]] §8.3, §8.3.1. ### Состояние стека после ребута (замер 2026-09-23) diff --git a/personal/plans/lampac-watched-to-watchlist.md b/personal/plans/lampac-watched-to-watchlist.md index 112af99a..13f81d27 100644 --- a/personal/plans/lampac-watched-to-watchlist.md +++ b/personal/plans/lampac-watched-to-watchlist.md @@ -177,9 +177,20 @@ KP-ID (`kinopoisk.ru/film/`, 68 штук в `.md`) в цепочке **не уч Почему так, а не «писать в Jellyfin»: Jellyfin не источник просмотров и не имеет файлов для большинства позиций. Единственный честный источник — Lampa. -**Статус на конец сессии:** план готов, код **не написан**. Разведка закрыта -(цепочка проверена, одна живая запись прогнана — матч дал 0, потому что фильм -вне вотчлиста; это ожидаемо, не баг). +**Статус на конец сессии 2026-09-23:** +- ✅ Разведка закрыта, цепочка матча проверена живой записью. +- ✅ План написан, исправлен по фактам (порог, хостовый путь БД, `.14`/`.15`). +- ✅ Закоммичены висевшие незакоммиченными фиксы сирот (`ffe7974`). +- ❌ **Код `sync_from_lampac.py` НЕ написан.** +- ⏳ Блокер: точный порог `percent` требует **живого досмотра** в Lampa + (см. §7) — без него шаг 6 не закрыть. +- ⏳ Не сделано: бэкап (шаг 1), `.env` (шаг 4), крон (шаг 5), доки (шаг 7). + +**Порядок следующей сессии:** шаг 8 (прогнать `/tmp/probe_match.py`, убедиться +что матч находит хоть одну позицию) → шаг 1 (бэкап) → шаг 2 (код) → +шаг 3 (dry-run на копии) → шаги 4-7. +⚠️ Шаг 8 стоит ПЕРВЫМ не случайно: если матч даёт 0 совпадений, писать код +бессмысленно — сначала чинить матч. --- @@ -190,8 +201,8 @@ KP-ID (`kinopoisk.ru/film/`, 68 штук в `.md`) в цепочке **не уч 2. **Новый файл** `watchlist_sync/sync_from_lampac.py`: - читает БД по пути из env `LAMPAC_TIMECODE_DB` (default `/lampac/database/TimeCode.sql`; хост-путь подставить в `.env`); - - отбирает `deleted = 0` **И** `percent > 0` **И** `watched_at > 0` - (см. 1.4 — «просмотрено» = `watched_at`, не `percent`); + - отбирает `deleted = 0` **И** `percent >= ПОРОГ` + (см. 1.4 — критерий пересмотрен: **по `percent`, НЕ по `watched_at`**); - `identity` → `tmdb_id`; форматы `movie-674`, `674_movie`, `tv-1851-s1e2`; на этапе 1 только фильмы, `tv-*` пропускать; - `position`/`duration`/`percent` выводить в лог для отладки — по ним видно, @@ -305,19 +316,26 @@ Vault git чистый. Записано в [[family/projects/watchlist-automati в `~/logs/` (`watchlist-catalog.log`, `watchlist-cleanup.log`). Фикс (перенести в `~/logs/`) предложен, ждёт команды Alex. -### 8.3 ✅ Уточнено: `192.168.1.15` НЕ мёртвый — это тот же Кра́кен +### 8.3 ✅ Уточнено: `.14` = провод, `.15` = WiFi. Оба — один Кра́кен 🔴 **Изменено 2026-09-23 (поздняя правка). Предыдущая версия этого раздела утверждала «`.15` мёртвый» — ЭТО НЕВЕРНО, ошибка снятия одного таймаута за факт.** +**Alex уточнил:** `192.168.1.15` — **WiFi** (`wlan0`), `192.168.1.14` — **провод** +(`eth0`). Ходим по `.14`. Термин «мёртвый» был моим ложным выводом. + Проверено: ``` $ ping -c 2 192.168.1.15 → 0% loss, 5.5 ms avg $ ssh kraken@192.168.1.15 → hostname = kraken hostname -I = 192.168.1.14 192.168.1.15 10.99.1.2 172.21.0.1 … +$ ssh kraken@192.168.1.14 → ALIVE_14 + +на Кра́кене: +eth0 UP 192.168.1.14/24 metric 100 ← основной, default route +wlan0 UP 192.168.1.15/24 metric 600 ``` -Кра́кен **имеет оба адреса**, оба живые, это одна и та же машина. -Оба варианта работают: `ssh kraken` (→ `.15`) и `ssh kraken@192.168.1.14`. +Кра́кен **имеет оба адреса**, это одна и та же машина. **Настоящая причина обрывов** — не адрес, а **перегрузка sshd**: первые подключения падали при `load average: 4.69` (после ребута поднимались @@ -325,16 +343,86 @@ $ ssh kraken@192.168.1.15 → hostname = kraken `Connection timed out during banner exchange`. Лечится повтором и короткими командами, а не сменой адреса. +⚠️ **Дополнительный источник обрывов (подтверждён 2026-09-23):** ЛЮБАЯ команда +с `sudo` через SSH требует `< /dev/null`, иначе соединение рвётся. См. +`family/how-to/truenas-infrastructure.md` / skill `home-network-config`. + **Обход, который реально помогает:** - короткие `ssh`-команды, тяжёлое — файлом-скриптом; - не собирать `ssh` + тяжёлый `jq` в одну строку (180 KB json = обрыв); -- `ssh kraken` штатно работает, `192.168.1.14` — равноценный явный путь. +- `sudo` всегда с `< /dev/null`. ⚠️ **WG-туннель до Кра́кена не поднят:** интерфейса с `10.99.0.2` на Mac нет, `nc 10.99.1.2 22` → FAIL. Proxy-команда в `~/.ssh/config` уходит в ветку `nc kraken 22`. Само по себе это не ломает (Кра́кен доступен по LAN), но объясняет, почему прокси не используется. +### 8.3.1 🔴 DNS-имя `kraken` на роутере указывало на WiFi `.15` — ИСПРАВЛЕНО + +**Симптом:** `ssh kraken` (по имени) шёл на `.15` — то есть на WiFi-интерфейс. +Когда он оказывался DOWN, `ssh kraken` переставал работать вовсе. + +**Причина — ДВА конфликтующих источника имени на роутере ASUS RT-AC68U:** + +``` +$ nvram get dhcp_staticlist +<12:42:0C:E6:31:0F>192.168.1.51>orangepizero> +192.168.1.86>htpc> +<84:25:19:74:A6:B3>192.168.1.80>>samsung_printer +<54:77:87:CE:FB:B3>192.168.1.75>lgtv> +<2C:CF:67:64:03:F3>192.168.1.14>kraken> ← eth0, ИМЯ kraken +<2C:CF:67:64:03:F4>192.168.1.15>kraken> ← wlan0, ИМЯ kraken (дубль!) + +$ cat /jffs/configs/dnsmasq.conf.add +address=/kraken/192.168.1.15 ← жёстко на WiFi +``` +Оба интерфейса несли **одно имя** `kraken`, плюс статический `address=` на `.15`. + +🔴 **Ключевой питфолл: живая DHCP-лиза ПЕРЕБИВАЕТ `address=`.** Активная лиза +wlan0 с именем `kraken` (`/var/lib/misc/dnsmasq.leases`) приоритетнее статической +записи. Удаление строки лизы не помогает — dnsmasq перезаписывает её из nvram +при рестарте, а клиент при DHCP-запросе сам представляется `kraken` (hostname +хоста один на оба интерфейса). + +**Что сделано на роутере (2026-09-23):** +```bash +# 1. Бэкапы +nvram get dhcp_staticlist > /jffs/dhcp_staticlist.bak.20260923-214309 +cp /jffs/configs/dnsmasq.conf.add /jffs/configs/dnsmasq.conf.add.bak.20260923-214309 +cp /var/lib/misc/dnsmasq.leases /jffs/dnsmasq.leases.bak. + +# 2. Убрано дублирующее имя у wlan0-лиза (ip остался) +nvram set dhcp_staticlist="…<2C:CF:67:64:03:F3>192.168.1.14>kraken><2C:CF:67:64:03:F4>192.168.1.15>>" +nvram commit + +# 3. Статический address переведён на провод +# /jffs/configs/dnsmasq.conf.add: +address=/kraken/192.168.1.14 ← было .15 +service restart_dnsmasq +``` + +**Результат:** активный `/etc/dnsmasq.conf:46` = `address=/kraken/192.168.1.14` +✅. Но `dig +short kraken @192.168.1.1` **всё ещё отдаёт `.15`** — живая лиза +wlan0 с именем `kraken` держится, пока аренда не истечёт / роутер не +перезагрузится. **Правки в nvram применятся после перезагрузки роутера.** + +⚠️ **Перезагрузку роутера НЕ делал** — ждёт решения Alex (роутер уйдёт из сети +на 1-2 мин, WiFi в доме пропадёт). Сейчас это не мешает: `wlan0` снова UP, +`.15` отвечает, `ssh kraken` работает. + +⚠️ **`netplan` на Кра́кене НЕ правился.** Идея была убрать отправку hostname +у `wlan0` (`dhcp4-overrides: send-hostname: false`) в `/etc/netplan/30-wlan0.yaml`, +но правку отменили — риск потери доступа перевесил. Файл нетронут. + +**Проверка:** +```bash +dig +short kraken @192.168.1.1 # сейчас .15, после ребута роутера → .14 +ssh kraken 'echo OK' # работает через .15 (WiFi) +ssh kraken@192.168.1.14 'echo OK' # работает через провод +``` +Бэкапы на роутере: `/jffs/dhcp_staticlist.bak.20260923-214309`, +`/jffs/configs/dnsmasq.conf.add.bak.20260923-214309`. + ### 8.4 🔴 `TimeCode.sql` НЕ на хосте — только внутри контейнера, и НЕ на volume 🔴 **Критично для реализации. Предыдущая версия плана называла хостовый путь @@ -379,7 +467,7 @@ compose, **без пересоздания контейнера без разр `_mark_watched` в `sync_up.py` **уже содержит** фикс эмодзи-префикса (`_PREFIX` поглощает эмодзи с обеих сторон `⬇️`) — переиспользуется без правок. -### 8.5 Внешний TMDB API с Кра́кена недоступен +### 8.6 Внешний TMDB API с Кра́кена недоступен `curl https://api.themoviedb.org/3/movie/...` без ключа → `Invalid API key`. Ключ живёт в `$WS/.env` (`TMDB_KEY`), прямой вызов из шелла не проходит.