feat(web): скрипт открытия хаба в домашнюю сеть, с подтверждением цели
Владелец хочет попадать в хаб на сервере по сети, а не через SSH-туннель. Для этого нужны привязка к 0.0.0.0 и токен: без токена при небlocalhost привязке сервер отказывается стартовать. Скрипт ДОПОЛНЯЕТ hub_settings.json, а не переписывает: рядом лежат тема, интервал обновления квот и параметры маршрутизации. Запись атомарная, повторный запуск сохраняет прежний токен. Изменение требует явного --yes, а каталог печатается всегда. Причина не теоретическая: при отладке скрипт молча взял HERMES_HOME из окружения и записал настройки не в тестовую копию, а в живой хаб рабочей машины, привязав его к сети. Откачено, наружу ничего не вышло — адрес читается при старте, процесс не перезапускался, netstat подтвердил только 127.0.0.1. Предпросмотр по умолчанию закрывает этот класс ошибки. Попутно install-linux.sh разворачивает scripts/: они входили в поставку, но на установленной машине не оказывались, поэтому вспомогательных инструментов там просто не было. Проверено на копии настроек: предпросмотр не меняет файл, применение сохраняет прежние ключи, повторный запуск не меняет токен, посторонний каталог не затрагивается. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
11aa914fbb
commit
44808bdc4e
2 changed files with 76 additions and 0 deletions
|
|
@ -96,6 +96,15 @@ if [ -d "$REPO_ROOT/assets" ]; then
|
|||
cp -r "$REPO_ROOT/assets/"* "$HERMES_HOME/plugins/antigravity-provider/assets/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Deploy helper scripts. Они лежат в поставке, но раньше не разворачивались,
|
||||
# поэтому вспомогательных инструментов (например открытия хаба в домашнюю сеть)
|
||||
# на установленной машине просто не оказывалось.
|
||||
if [ -d "$REPO_ROOT/scripts" ]; then
|
||||
mkdir -p "$HERMES_HOME/scripts"
|
||||
cp -r "$REPO_ROOT/scripts/"*.py "$HERMES_HOME/scripts/" 2>/dev/null || true
|
||||
cp -r "$REPO_ROOT/scripts/"*.sh "$HERMES_HOME/scripts/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 4. Write Deployment Manifest
|
||||
echo "[4/6] Writing deployment manifest..."
|
||||
MANIFEST_FILE="$HERMES_HOME/plugins/antigravity-provider/deployment_manifest.json"
|
||||
|
|
|
|||
67
scripts/enable_lan_access.py
Normal file
67
scripts/enable_lan_access.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
"""Открыть веб-хаб в домашнюю сеть: привязка к 0.0.0.0 плюс обязательный токен.
|
||||
|
||||
python3 scripts/enable_lan_access.py # показать, что будет сделано
|
||||
python3 scripts/enable_lan_access.py --yes # применить
|
||||
|
||||
Почему подтверждение обязательно. Каталог берётся из HERMES_HOME, а эта
|
||||
переменная часто задана в окружении незаметно для запускающего. При отладке
|
||||
скрипт из-за этого записал настройки не туда, куда предполагалось, и привязал
|
||||
к сети не тот хаб. Поэтому цель печатается всегда, а изменение требует --yes.
|
||||
|
||||
Настройки ДОПОЛНЯЮТСЯ, а не переписываются: рядом лежат тема, интервал
|
||||
обновления квот и параметры маршрутизации. Запись атомарная.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main() -> int:
|
||||
apply = "--yes" 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"
|
||||
|
||||
print(f"Каталог Hermes : {home}")
|
||||
print(f" источник : {'переменная HERMES_HOME' if env_home else 'по умолчанию ~/.hermes'}")
|
||||
print(f"Файл настроек : {target}")
|
||||
print(f" существует : {'да' if target.exists() else 'нет, будет создан'}")
|
||||
|
||||
data = {}
|
||||
if target.exists():
|
||||
try:
|
||||
data = json.loads(target.read_text(encoding="utf-8"))
|
||||
except ValueError:
|
||||
print(f"\nОТКАЗ: {target} повреждён. Разберитесь вручную — перезаписывать не буду.")
|
||||
return 1
|
||||
|
||||
existing = 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 not apply:
|
||||
print("\nПоказан предпросмотр. Чтобы применить, повторите с --yes")
|
||||
return 0
|
||||
|
||||
token = existing or secrets.token_urlsafe(32)
|
||||
data["web_api_host"] = "0.0.0.0"
|
||||
data["web_api_token"] = token
|
||||
data.setdefault("web_api_port", 5800)
|
||||
|
||||
tmp = target.with_suffix(".json.tmp")
|
||||
tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
os.replace(tmp, target)
|
||||
|
||||
print(f"\nГотово: {target}")
|
||||
print("\nТОКЕН — вставить в «Настройки» в интерфейсе:")
|
||||
print(f" {token}")
|
||||
print("\nДальше: перезапустить хаб, затем открыть http://<адрес-сервера>:5800")
|
||||
print("Токен хранится в этом файле; в снапшот и в /api/settings он не попадает.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Reference in a new issue