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
|
cp -r "$REPO_ROOT/assets/"* "$HERMES_HOME/plugins/antigravity-provider/assets/" 2>/dev/null || true
|
||||||
fi
|
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
|
# 4. Write Deployment Manifest
|
||||||
echo "[4/6] Writing deployment manifest..."
|
echo "[4/6] Writing deployment manifest..."
|
||||||
MANIFEST_FILE="$HERMES_HOME/plugins/antigravity-provider/deployment_manifest.json"
|
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