Files
obsidian-vault/family/how-to/kraken-access.md
T

22 KiB
Raw Blame History

Kraken — Внешний доступ

✅ 2026-09-20 — НАЙДЕНА ИСТИННАЯ ПРИЧИНА (2026-09-15 поломки): ГОНКА Docker ↔ монтирование USB-диска

Симптом 2026-09-15: одновременно упали (1) reverse-туннель Kraken→TrueNAS (kraken-user) и (2) cloudflared SSH-туннель ssh-kraken.qentra.top. Обе поломки — одна причина, не две.

Таймлайн последнего boot (Kraken)

Событие Время
Boot Sep 15 17:29:17
Ядро видит sda1 (USB HDD) +130 с → 17:31:27
dockerd стартовал (PID 1324) 17:31:01 ← на 26 с раньше диска
Диск смонтирован 17:31:27

Механизм: /etc/docker/daemon.json → data-root = /srv/dev-disk-by-uuid-49e8f586-.../docker-data (симлинк на 6194539b-...). docker.service не имеет RequiresMountsFor= → не ждёт монтирования. dockerd на 17:31:01 открыл путь до появления диска → увидел пусто → загрузил 0 контейнеров; через 26 с диск смонтировался поверх точки, но daemon уже держал пустое состояние в памяти. Перечитывания нет.

Что НЕ потеряно (проверено живьём)

  • docker-data/containers/ = 4.7G, 35 контейнеров целы (cloudflared, xray-reverse-bridge, jellyfin, sonarr, radarr, prowlarr, transmission, homeassistant, hermes-kraken, portainer, rclone, watchtower, flaresolverr, timemachine).
  • Образы (21), 32 volume — на месте. Диск sda1 1.8T смонтирован, 242G свободно.
  • docker info при этом рапортует Containers=0 — не верь ему, metadata на диске цела.

Побочные дефекты, найденные при разборе

  1. /etc/fstab содержит ДУБЛЬ строки для 6194539b: OMV-блок + ручная строка UUID=6194539b-... → systemd: Duplicate entry in '/etc/fstab'?.
  2. docker.service: RequiresMountsFor= пусто — корень гонки. Drop-in нужен, чтобы dockerd ждал диск.
  3. RestartPolicy=null → нужен ручной docker start ❌ ЭТО БЫЛО ОШИБОЧНОЕ ДОПУЩЕНИЕ. Я прочитал RestartPolicy.Name из hostconfig.json (это reflection исходного docker run, там null), но в daemon state policy есть. Факт: после systemctl restart docker все 12 контейнеров с unless-stopped поднялись сами, ручной docker start не потребовался. Проверять политику надо docker inspect <name> --format '{{.HostConfig.RestartPolicy.Name}}' (живой daemon), а не hostconfig.json на диске.

Команды диагностики (воспроизводимые)

ssh kraken 'docker ps -a --format "{{.Names}}\t{{.Status}}"'          # пусто → daemon state пуст
ssh kraken 'ps -o pid,lstart,cmd -p $(pgrep -x dockerd)'               # реальное время старта dockerd
ssh kraken 'systemctl show docker -p RequiresMountsFor'                # пусто = нет зависимости от mount
ssh kraken 'uptime -s; findmnt /srv/dev-disk-by-uuid-6194539b-...'     # когда boot / когда диск
ssh kraken 'sudo ls /srv/dev-disk-by-uuid-6194539b-.../docker-data/containers | wc -l'  # 35 = целы

Питфолл: systemctl show docker -p ExecMainStartTimestamp дал stale 15:18:36; истинное время старта — ps -o lstart = 17:31:01.

План восстановления (согласован 2026-09-20)

  1. Backup: /etc/fstab, /etc/docker/daemon.json, /home/kraken/xray-reverse/ → /home/kraken/backups/docker-recovery-<date>/.
  2. sudo systemctl restart docker — диск уже смонтирован → daemon прочитает все 35 контейнеров.
  3. docker start по списку — ⚠️ НЕ ПОТРЕБОВАЛСЯ: оказалось, RestartPolicy в daemon state есть (unless-stopped), все 12 контейнеров поднялись автоматически после рестарта daemon. hostconfig.json на диске показывает null — это НЕ отражает реальную политику. Проверять через живой daemon: docker inspect --format '{{.HostConfig.RestartPolicy.Name}}'.
  4. Правка боевого: убрать дубль fstab + drop-in RequiresMountsFor=/srv/dev-disk-by-uuid-6194539b-... — только с апрувом Alex. Порядок: коммит ДО → правка → заливка → проверка Alex → коммит ПОСЛЕ.
  5. Проверка: docker ps все Up; reverse-канал udp:reverse:0; cloudflared tunnel.
  6. Версии Xray на бридже: оставить 26.4.25 + network_mode: host (проверенный фикс 2026-09-02) — открытый вопрос к Alex.

Статус (обновлено 2026-09-20): ✅ ФИКС ПРИМЕНЁН, ПРОВЕРЕН, REBOOT-БЕЗОПАСЕН.

Что сделано:

  1. ✅ Backup: /home/kraken/backups/docker-recovery-20260920-105228/ (fstab, daemon.json, xray-reverse).
  2. ✅ sudo systemctl restart docker → все 25 контейнеров загрузились, 12 поднялись автоматом (cloudflared, xray-reverse-bridge в т.ч.).
  3. ✅ Drop-in /etc/systemd/system/docker.service.d/mounts.conf:
    [Unit]
    RequiresMountsFor=/srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker-data
    After=srv-dev\x2ddisk\x2dby\x2duuid\x2d6194539b\x2d03e0\x2d4f33\x2d986b\x2d4da09834e82f.mount
    
    Проверено: systemctl show docker -p Requires -p After → маунт-юнит в Requires И After. dockerd теперь физически не стартует раньше диска → гонка закрыта.
  4. ✅ /etc/fstab: убран дубль строки для 6194539b + дубль bind-mount /var/log/journal. Осталось 1 вхождение (OMV-блок). Проверено грепом.
  5. ✅ Sanity systemctl restart docker после правок → containers=25, 11-12 Up. Критичные поднялись сами.

⚠️ hermes-kraken — Restarting (1) (crash-loop, не связан с этой задачей, был до правок).

Питфолл (опровергнут): RestartPolicy в hostconfig.json = null, но в daemon state policy есть → при рестарте daemon контейнеры поднимаются сами. Не пугаться null, не нужен ручной docker start.

Урок на будущее: USB-диск на Kraken поднимается ~130 с. Любой сервис, зависящий от docker-data на этом диске, ОБЯЗАН иметь RequiresMountsFor. Теперь это обеспечено для docker.service.

🔴 2026-09-15 — KRAKEN НЕДОСТУПЕН ПО ВСЕМ ПУТЯМ (проверено с Mac)

⚠️ ВНИМАНИЕ (обновлено 2026-09-20): вывод этой секции был ЧАСТИЧНО НЕВЕРЕН. «Kraken недоступен» относилось к внешним путям (cloudflared ssh-kraken.qentra.top, WG 10.99.1.2) — оба были down не из-за выключенной машины Kraken, а из-за гонки docker↔mount (см. секцию выше): cloudflared-контейнер просто не загрузился daemon'ом. По LAN Kraken был жив всю дорогу (192.168.1.15). Урок: «недоступен снаружи» ≠ «машина мертва» — проверять LAN и состояние docker daemon, прежде чем звонить провайдеру.

Симптом: перестал работать клиент kraken-user в 3x-ui на TrueNAS. При разборе выяснилось — причина не в БД и не в конфиге, а в том, что сам хост Kraken недоступен.

Путь Команда Результат
Cloudflare SSH ssh ssh-kraken.qentra.top ❌ Connection timed out during banner exchange
WireGuard Direct ssh kraken@10.99.1.2:22 ❌ Operation timed out
DNS host kraken ❌ NXDOMAIN (в /etc/hosts записи нет)

Состояние TrueNAS-стороны (жива): xray-reverse-portal Up 13 дней, порты 12345 (SOCKS) и 12346 (interconn) в LISTEN, конфиг /mnt/RED_2TB/docker/reverse-portal/config.json цел.

Диагностика, доказывающая «бридж молчит»:

docker exec xray-reverse-portal netstat -an | grep 12346   # пусто = от Kraken никто не звонит
curl -s --max-time 20 --socks5-hostname 127.0.0.1:12345 https://api.ipify.org   # пусто (ждём 92.62.70.41)

Логи портала при этом содержат app/dispatcher: non existing outTag: reverse-out — это не битый конфиг, а ожидаемое следствие: reverse-out создаётся Xray'ем автоматически только пока бридж подключён (объявлен в inbounds[interconn].clients[0].reverse.tag, не в .outbounds).

Вывод: нужно проверять Kraken со стороны панели хостинга/консоли провайдера — машина выключена либо сетевая недоступность. Решение Alex: «подождём, может оживет».

⚠️ Урок: перед тем как искать причину в конфиге TrueNAS, проверять доступность самого Kraken. Полдня ушло на разбор 3x-ui, который к этой поломке отношения не имел.

Обновлено: 2026-09-04

Updated: 2026-09-01 23:00 — диск/докер кракена восстановились после перезагрузки.

Как зайти

Везде ssh kraken. Резолвится через ~/.ssh/config на Eagle:

  • Дома — напрямую по LAN (192.168.1.15)
  • Снаружи — ⚠️ через WireGuard (10.99.1.2) БОЛЬШЕ НЕ РАБОТАЕТ: VPS-узло (10.99.0.1/10.99.1.1) qentra.top удалили 2026-09-01. Альтернатива внешнего доступа обсуждается через Xray reverse (см. tech/xray-reverse-tunnel-kraken-truenas).

⚠️ Kraken-диск был нестабилен 2026-09-01: USB-диск TOSHIBA в цикле enumeration (device descriptor read/64 error -110, device not accepting address error -62, [sda] Read Capacity(10) failed → 0 B), Kraken перезагружался (System is booting up / pam_nologin). После повторной перезагрузки диск зарегистрировался: sda 1.8T, sda1 смонтирован в /srv/dev-disk-by-uuid-6194539b-.... Docker стал active.

⚠️ Kraken Docker на 2026-09-01: Server 29.4.3, Docker Root Dir /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f/docker-data. 30 образов сохранены, но 0 контейнеров (all прежние контейнеры — jellyfin/transmission/radarr/hermes-kraken и т.д. — потеряны и НЕ пересозданы после сбоя; data-root на HDD был в цикле enumeration). При необходимости — пересоздать из образов.

Portainer (локально)

http://kraken:9000

API:

BASE=http://localhost:9000
KEY="ptr_AJY+Ba9A7f6pcAHZfDD5koU4stkKgJCdbTEXLDLxn0g="
EP=3  # endpoint ID на Кракене = 3, не 1!

Hermes API

http://kraken:8642/v1/chat/completions — OpenAI-compatible endpoint.

Reverse Xray bridge (развёрнут 2026-09-01)

  • Контейнер xray-reverse-bridge в /home/kraken/xray-reverse/ (compose + config.json), образ teddysun/xray:26.4.25 + network_mode: host (проверенный фикс 2026-09-02).
  • Outbound VLESS+REALITY TCP → mallexxx.duckdns.org:12346 (TrueNAS через OpenWrt DNAT), reverse tag reverse-in, egress freedom с finalRules:[{action:allow}].
  • ✅ End-to-end payload работает (верифицировано 2026-09-02: SOCKS 12345 → egress IP Kraken 92.62.70.41). Полная история диагностики (регрессии #6612/#6242, docker bridge/NAT) — в tech/xray-reverse-tunnel-kraken-truenas.
  • ⚠️ 2026-09-15…20 контейнер был не запущен (гонка docker↔mount, см. шапку) — это единственная причина «туннель down». После рестарта daemon — снова Up.

Docker контейнеры (обновлено 2026-09-20, после фикса)

✅ daemon видит все контейнеры. containers=25, 12 Up (после восстановления гонки docker↔mount, см. шапку). Все 35 metadata-записей в docker-data/containers/ целы.

Имя Статус 2026-09-20 Заметки
xray-reverse-bridge ✅ Up образ teddysun/xray:26.4.25, network_mode: host (фикс 2026-09-02)
cloudflared ✅ Up cloudflare/cloudflared:latest, network_mode: host, remote-managed по TUNNEL_TOKEN
jellyfin / sonarr / radarr / prowlarr ✅ Up
portainer / transmission / rclone / watchtower / flaresolverr ✅ Up
hermes-kraken ✅ Up crash-loop вылечен 2026-09-20 (см. ниже)
homeassistant ⏹ Exited (128) 2 месяца назад не поднимался, отдельная задача
timemachine + alpine-* (6 шт.) ⏹ Exited (0) одноразовые/диагностические, норма

Питфолл про RestartPolicy (проверено): hostconfig.json на диске показывает RestartPolicy.Name = null, но в daemon state политика unless-stopped есть → контейнеры поднимаются сами. Не пугаться null, не нужен ручной docker start. Проверять живой daemon: docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' <name>.

✅ hermes-kraken — crash-loop вылечен 2026-09-20 (права каталога)

Симптом: hermes-kraken в вечном Restarting (1). Логи циклично: mkdir: cannot create directory '/opt/data': Permission denied.

НЕ связано с гонкой docker↔mount (контейнер был запущен, но падал сам).

Что Значение
Контейнер работает под UID 1000:1000 (kraken, задан в образе, не в compose)
/opt/data примонтирован из …/docker/hermes/config
Владелец на хосте (было) 10000:10000, drwx------ (700), mtime Sep 15 15:37
Итог 1000 ≠ 10000 + mode 700 → Permission denied на mkdir /opt/data

Корень: каталог docker/hermes/config после перерегистрации диска (15 сен) получил чужой UID 10000 — след старого OMV-маппинга. 10000 больше нигде в …/docker/ не встречается: все прочие каталоги либо root:root, либо 1000:1000. Данные (.env, auth.json, sessions/, cron/, response_store.db) были целы — только владелец не тот.

Фикс:

# top-level — мгновенно
sudo chown 1000:1000 /srv/dev-disk-by-uuid-6194539b-.../docker/hermes/config
# рекурсивно — долго (медленный USB-HDD), запускать в фоне, НЕ блокируясь на SSH:
sudo systemd-run --unit=hermes-chown --collect --property=Type=oneshot \
  chown -R 1000:1000 /srv/dev-disk-by-uuid-6194539b-.../docker/hermes/config

Проверка: sudo find …/docker/hermes -uid 10000 → пусто; контейнер Up; API http://localhost:8642/ отвечает (404 на / — норма, эндпоинт /v1/chat/completions).

Питфоллы:

  • chown -R по большому дереву на USB-HDD идёт минуты → обычный ssh-вызов рвётся по таймауту и правка НЕ применяется. Запускать через systemd-run … --collect в фоне, потом проверять systemctl is-active hermes-chown и ls -ldn каталога.
  • Логи после старта содержат «хвост» прежних mkdir ошибок из буфера — не пугаться, если дальше идёт Hermes Gateway Starting... и скиллы синхронизированы.

Cloudflared туннель — публичные маршруты (состояние на 2026-09-04)

Туннель kraken в Zero Trust, remote-managed по TUNNEL_TOKEN, network_mode: host, образ cloudflare/cloudflared:latest. Актуальный ingress конфиг (виден в логах cloudflared на Kraken, INF Updated to new configuration):

{"ingress":[
  {"hostname":"kraken.qentra.top",     "originRequest":{"httpHostHeader":"kraken.qentra.top"},"service":"http://localhost:8642"},  ← Hermes API
  {"hostname":"ssh-kraken.qentra.top",  "service":"ssh://localhost:22"},                                                          ← SSH (published application route)
  {"service":"http_status:404"}                                                                                                    ← default catch-all
]}

⚠️ Важно (путаница была!): kraken.qentra.top — это HTTP-маршрут на localhost:8642 (Hermes API), НЕ SSH. Поэтому SSH к kraken.qentra.top:22 и не шёл. Под SSH создан отдельный hostname ssh-kraken.qentra.top.

✅ SSH-доступ работает через ssh-kraken.qentra.top (РАБОЧИЙ, 2026-09-04)

Вход (проверено, работает):

ssh kraken@ssh-kraken.qentra.top

~/.ssh/config блок:

Host ssh-kraken.qentra.top
  HostName ssh-kraken.qentra.top
  User kraken
  ProxyCommand cloudflared access ssh --hostname %h

Первый раз — авторизация cloudflared в Access-приложение:

cloudflared access login ssh-kraken.qentra.top

Маршрут на Kraken (UP, контейнер) подхвачен ingress ssh-kraken.qentra.top → ssh://localhost:22; sshd на Kraken — 0.0.0.0:22. DNS проксировано CF (104.21.x / 172.67.x).

⚠️ Питфол: почему ssh.kraken.qentra.top (двухуровневый) НЕ сработал

Изначально под SSH добавлялся hostname ssh.kraken.qentra.top (ssh.kraken + qentra.top) → ssh://localhost:22, + Access Application (type SSH) + Service Token. Вход НЕ заработал. Решающий факт — на edge Cloudflare у этого hostname НЕТ SSL/TLS-терминации, в отличие от одиночных subdomain:

openssl s_client -connect ssh.kraken.qentra.top:443 → SSL alert 40 (handshake failure), no peer certificate
curl https://ssh.kraken.qentra.top → ssl=1 handshake failure

Любой cloudflared access login/ssh и Service Token к чистому двухуровневому SSH-hostname не помогают — клиент не доходит даже до авторизации из-за отсутствия edge-TLS.

Решение, которое сработало: использовать одиночный subdomain через дефис — ssh-kraken.qentra.top (покрывается Universal SSL *.qentra.top). На нём размещены тот же published application route SSH → ssh://localhost:22 + Access Application. Вошло сразу.

Почему так: Universal SSL зоны покрывает *.qentra.top (1 уровень) и qentra.top, но НЕ *.kraken.qentra.top (2 уровня). Для 2-уровневого нужен Advanced Certificate — проще взять одиночный subdomain.

Диагноз IPv4/IPv6 «жив, но шумит» (актуально для обоих hostname)

  • В логах cloudflared — часть Registered tunnel connection ... protocol=quic, но постоянные ERR ... write udp [::]->198.41.x.x:7844: sendmsg: network is unreachable.
  • Причина: на Kraken НЕТ глобального IPv6 (только ::1 и link-local fe80::; роутер 192.168.1.1 IPv6 не выдаёт → ping6 2606:4700::1111 = Network is unreachable). cloudflared пробует QUIC и по IPv6 → каналы падают; туннель выживает по IPv4-QUIC.
  • Возможный фикс: заставить cloudflared QUIC только по IPv4, чтобы убрать IPv6-шум.

SSH через VPS reverse (независимо от cloudflared)

Остаётся рабочим внешним путём: reverse SSH туннель через VPS 91.207.28.205:2223 (см. ниже), НЕ cloudflared.

Связанные заметки