From e90f6331a2044f7e165457dbb90c6a293469c22c Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Tue, 25 Aug 2026 10:47:29 +0700 Subject: [PATCH] =?UTF-8?q?fix(launcher):=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B8=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=83=D1=81=D0=BA=D0=B5=20=D0=BD=D0=B5=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=D0=BE=20=D1=81=20=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=D0=BC=D0=B8;?= =?UTF-8?q?=20=D1=81=D0=BC=D0=B5=D0=BD=D0=B0=20=D1=82=D0=BE=D0=BA=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Владелец привязал хаб на сервере к сети, а лаунчер всё равно напечатал «Headless Mode», показал http://127.0.0.1:5800 и посоветовал пробросить порт через ssh -L. Текст был зашит и настроек не читал: инструкция вела поднимать туннель к серверу, который уже был виден напрямую. Инструкция, не совпадающая с реальностью, хуже отсутствующей — тот же класс дефекта, что и снятая заглушка про «вход через веб невозможен». Теперь сообщение читает web_api_host из hub_settings.json: при 127.0.0.1 показывает проброс порта и подсказывает про enable_lan_access.py, при сетевой привязке — реальный адрес из hostname -I и напоминание про токен. Добавлен --rotate: смена токена понадобилась немедленно, потому что выданный токен был вставлен в переписку и скомпрометирован. Без флага поведение прежнее — повторный запуск токен не трогает. Проверено: без --rotate токен сохраняется, с --rotate меняется; bash -n на лаунчере проходит; переводы строк LF. Co-Authored-By: Claude Opus 5 --- launcher/hermes-hub-web.sh | 46 ++++++++++++++++++++++++++++++------ scripts/enable_lan_access.py | 16 +++++++++---- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/launcher/hermes-hub-web.sh b/launcher/hermes-hub-web.sh index 9c6cbcf..4b424d8 100644 --- a/launcher/hermes-hub-web.sh +++ b/launcher/hermes-hub-web.sh @@ -95,16 +95,48 @@ if ! check_health; then fi # 4. Headless Server Check (SSH / No Graphical Display) +# +# Текст здесь раньше был зашит: он всегда советовал пробрасывать порт и +# показывал 127.0.0.1, даже когда хаб уже привязан к сети и доступен напрямую. +# Инструкция, не совпадающая с настройками, хуже отсутствующей — владелец +# поднимал туннель к серверу, который и так был виден. if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then + SETTINGS_FILE="$HERMES_HOME/hub_settings.json" + BIND_HOST="127.0.0.1" + if [ -f "$SETTINGS_FILE" ]; then + BIND_HOST="$("$PYTHON_BIN" - "$SETTINGS_FILE" <<'PYEOF' 2>/dev/null || echo "127.0.0.1" +import json, sys +try: + print(json.load(open(sys.argv[1], encoding="utf-8")).get("web_api_host", "127.0.0.1")) +except Exception: + print("127.0.0.1") +PYEOF +)" + fi + echo "======================================================================" - echo " Hermes Hub Web Server is running (Headless Mode)" - echo " Web Interface URL: $TARGET_URL" + echo " Hermes Hub Web Server is running (no graphical display)" echo "" - echo " To access the interface from your local computer, forward the port:" - echo " ssh -L $PORT:127.0.0.1:$PORT user@server" - echo "" - echo " Then open in your browser:" - echo " $TARGET_URL" + if [ "$BIND_HOST" = "127.0.0.1" ] || [ -z "$BIND_HOST" ]; then + echo " Listening on 127.0.0.1:$PORT — reachable from this machine only." + echo "" + echo " To open it from another computer, forward the port:" + echo " ssh -L $PORT:127.0.0.1:$PORT @" + echo " then open http://127.0.0.1:$PORT/ there." + echo "" + echo " To expose it on the local network instead:" + echo " python3 $HERMES_HOME/scripts/enable_lan_access.py" + else + LAN_IP="$(hostname -I 2>/dev/null | awk '{print $1}')" + [ -n "$LAN_IP" ] || LAN_IP="
" + echo " Listening on $BIND_HOST:$PORT — reachable over the network." + echo "" + echo " Open from another computer:" + echo " http://$LAN_IP:$PORT/" + echo "" + echo " A token is required: paste it in Settings on first open." + echo " No port forwarding needed." + fi echo "======================================================================" exit 0 fi diff --git a/scripts/enable_lan_access.py b/scripts/enable_lan_access.py index de46b07..ed2ea7e 100644 --- a/scripts/enable_lan_access.py +++ b/scripts/enable_lan_access.py @@ -1,7 +1,8 @@ """Открыть веб-хаб в домашнюю сеть: привязка к 0.0.0.0 плюс обязательный токен. - python3 scripts/enable_lan_access.py # показать, что будет сделано - python3 scripts/enable_lan_access.py --yes # применить + python3 scripts/enable_lan_access.py # показать, что будет сделано + python3 scripts/enable_lan_access.py --yes # применить + python3 scripts/enable_lan_access.py --yes --rotate # сменить токен Почему подтверждение обязательно. Каталог берётся из HERMES_HOME, а эта переменная часто задана в окружении незаметно для запускающего. При отладке @@ -20,6 +21,7 @@ from pathlib import Path def main() -> int: apply = "--yes" in sys.argv + rotate = "--rotate" in sys.argv env_home = os.environ.get("HERMES_HOME") home = Path(env_home) if env_home else (Path.home() / ".hermes") target = home / "hub_settings.json" @@ -37,10 +39,16 @@ def main() -> int: print(f"\nОТКАЗ: {target} повреждён. Разберитесь вручную — перезаписывать не буду.") return 1 - existing = data.get("web_api_token") + existing = None if rotate else data.get("web_api_token") keep = sorted(k for k in data if not k.startswith("web_api")) print(f"Будут сохранены: {', '.join(keep) if keep else '(файл пуст)'}") - print(f"Токен : {'уже задан, оставляю прежний' if existing else 'будет создан новый'}") + if rotate: + note = "БУДЕТ ЗАМЕНЁН — прежний перестанет действовать" + elif existing: + note = "уже задан, оставляю прежний" + else: + note = "будет создан новый" + print(f"Токен : {note}") if not apply: print("\nПоказан предпросмотр. Чтобы применить, повторите с --yes")