fix(launcher): сообщение при запуске не совпадало с настройками; смена токена
Владелец привязал хаб на сервере к сети, а лаунчер всё равно напечатал «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 <noreply@anthropic.com>
This commit is contained in:
parent
2ca42a39c4
commit
e90f6331a2
2 changed files with 51 additions and 11 deletions
|
|
@ -95,16 +95,48 @@ if ! check_health; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. Headless Server Check (SSH / No Graphical Display)
|
# 4. Headless Server Check (SSH / No Graphical Display)
|
||||||
|
#
|
||||||
|
# Текст здесь раньше был зашит: он всегда советовал пробрасывать порт и
|
||||||
|
# показывал 127.0.0.1, даже когда хаб уже привязан к сети и доступен напрямую.
|
||||||
|
# Инструкция, не совпадающая с настройками, хуже отсутствующей — владелец
|
||||||
|
# поднимал туннель к серверу, который и так был виден.
|
||||||
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
|
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 "======================================================================"
|
||||||
echo " Hermes Hub Web Server is running (Headless Mode)"
|
echo " Hermes Hub Web Server is running (no graphical display)"
|
||||||
echo " Web Interface URL: $TARGET_URL"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " To access the interface from your local computer, forward the port:"
|
if [ "$BIND_HOST" = "127.0.0.1" ] || [ -z "$BIND_HOST" ]; then
|
||||||
echo " ssh -L $PORT:127.0.0.1:$PORT user@server"
|
echo " Listening on 127.0.0.1:$PORT — reachable from this machine only."
|
||||||
echo ""
|
echo ""
|
||||||
echo " Then open in your browser:"
|
echo " To open it from another computer, forward the port:"
|
||||||
echo " $TARGET_URL"
|
echo " ssh -L $PORT:127.0.0.1:$PORT <user>@<this-host>"
|
||||||
|
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="<address of this host>"
|
||||||
|
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 "======================================================================"
|
echo "======================================================================"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
python3 scripts/enable_lan_access.py # показать, что будет сделано
|
python3 scripts/enable_lan_access.py # показать, что будет сделано
|
||||||
python3 scripts/enable_lan_access.py --yes # применить
|
python3 scripts/enable_lan_access.py --yes # применить
|
||||||
|
python3 scripts/enable_lan_access.py --yes --rotate # сменить токен
|
||||||
|
|
||||||
Почему подтверждение обязательно. Каталог берётся из HERMES_HOME, а эта
|
Почему подтверждение обязательно. Каталог берётся из HERMES_HOME, а эта
|
||||||
переменная часто задана в окружении незаметно для запускающего. При отладке
|
переменная часто задана в окружении незаметно для запускающего. При отладке
|
||||||
|
|
@ -20,6 +21,7 @@ from pathlib import Path
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
apply = "--yes" in sys.argv
|
apply = "--yes" in sys.argv
|
||||||
|
rotate = "--rotate" in sys.argv
|
||||||
env_home = os.environ.get("HERMES_HOME")
|
env_home = os.environ.get("HERMES_HOME")
|
||||||
home = Path(env_home) if env_home else (Path.home() / ".hermes")
|
home = Path(env_home) if env_home else (Path.home() / ".hermes")
|
||||||
target = home / "hub_settings.json"
|
target = home / "hub_settings.json"
|
||||||
|
|
@ -37,10 +39,16 @@ def main() -> int:
|
||||||
print(f"\nОТКАЗ: {target} повреждён. Разберитесь вручную — перезаписывать не буду.")
|
print(f"\nОТКАЗ: {target} повреждён. Разберитесь вручную — перезаписывать не буду.")
|
||||||
return 1
|
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"))
|
keep = sorted(k for k in data if not k.startswith("web_api"))
|
||||||
print(f"Будут сохранены: {', '.join(keep) if keep else '(файл пуст)'}")
|
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:
|
if not apply:
|
||||||
print("\nПоказан предпросмотр. Чтобы применить, повторите с --yes")
|
print("\nПоказан предпросмотр. Чтобы применить, повторите с --yes")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue