mirror of
https://github.com/andrey271192/PCA_Phobos.git
synced 2026-09-20 11:55:32 +00:00
Versioning: VERSION file, phobos-update (update/rollback), panel version+update UI
This commit is contained in:
41
app.py
41
app.py
@@ -403,6 +403,23 @@ def generate_failover_conf_for_client(client_id):
|
|||||||
return "\n".join(lines) + "\n"
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def panel_version():
|
||||||
|
try:
|
||||||
|
return open(os.path.join(PANEL_DIR, ".version")).read().strip()
|
||||||
|
except Exception:
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def run_update(arg):
|
||||||
|
import subprocess
|
||||||
|
try:
|
||||||
|
r = subprocess.run(["/opt/Phobos/server/update.sh", arg],
|
||||||
|
capture_output=True, text=True, timeout=150)
|
||||||
|
return (r.stdout + r.stderr)[-1200:]
|
||||||
|
except Exception as e:
|
||||||
|
return "update error: " + str(e)
|
||||||
|
|
||||||
|
|
||||||
def build_phone_config(cid, mode="android"):
|
def build_phone_config(cid, mode="android"):
|
||||||
"""Assemble a phone client config from the client's files.
|
"""Assemble a phone client config from the client's files.
|
||||||
android = WireGuard + [instance] obfuscator -> phobos:// link (PhobosWG app).
|
android = WireGuard + [instance] obfuscator -> phobos:// link (PhobosWG app).
|
||||||
@@ -1088,6 +1105,16 @@ def labels_page():
|
|||||||
def settings_page():
|
def settings_page():
|
||||||
s = load_settings()
|
s = load_settings()
|
||||||
msg = ""
|
msg = ""
|
||||||
|
if request.method == "POST" and request.form.get("action") in ("update", "rollback"):
|
||||||
|
if request.form.get("action") == "update":
|
||||||
|
_out = run_update(request.form.get("target", "").strip() or "main")
|
||||||
|
else:
|
||||||
|
_out = run_update("--rollback")
|
||||||
|
s = load_settings()
|
||||||
|
return render(f'''<div class="container">{nav("settings")}<div class="card">
|
||||||
|
<h2>{tr("Результат", "Result")}</h2>
|
||||||
|
<pre style="white-space:pre-wrap;font-size:.8em;background:#0f172a;padding:12px;border-radius:8px">{_out}</pre>
|
||||||
|
<a href="/settings" class="btn btn-sm">{tr("← к настройкам", "← back to settings")}</a></div></div>''')
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
new_pass = request.form.get("admin_pass", "").strip()
|
new_pass = request.form.get("admin_pass", "").strip()
|
||||||
if new_pass:
|
if new_pass:
|
||||||
@@ -1116,6 +1143,20 @@ def settings_page():
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2>{tr("Версия и обновления","Version & updates")} {hlp("Скачивает свежие файлы PCA-слоя (панель + скрипты) с GitHub и перезапускает панель. Ключи WireGuard, server.env и клиенты НЕ трогаются. Пусто или main = последняя версия; можно указать тег (например v1.1.0). Откат восстанавливает предыдущую версию из автоматического бэкапа.", "Fetches the latest PCA files (panel + scripts) from GitHub and restarts the panel. WireGuard keys, server.env and clients are NOT touched. Empty or main = latest; you can pass a tag (e.g. v1.1.0). Rollback restores the previous version from an automatic backup.")}</h2>
|
||||||
|
<p>{tr("Установленная версия","Installed version")}: <b style="color:#a5b4fc">{panel_version()}</b></p>
|
||||||
|
<form method="post" class="form-row">
|
||||||
|
<input type="hidden" name="action" value="update">
|
||||||
|
<input type="text" name="target" placeholder="main / v1.1.0" style="width:150px">
|
||||||
|
<button class="btn btn-primary" type="submit" onclick="return confirm('{tr("Обновить панель и скрипты?","Update panel and scripts?")}')">{tr("Обновить","Update")}</button>
|
||||||
|
</form>
|
||||||
|
<form method="post" style="margin-top:8px">
|
||||||
|
<input type="hidden" name="action" value="rollback">
|
||||||
|
<button class="btn btn-danger btn-sm" type="submit" onclick="return confirm('{tr("Откатить на предыдущую версию?","Roll back to the previous version?")}')">{tr("Откатить на предыдущую","Rollback")}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>{tr("Информация о сервере","Server info")}</h2>
|
<h2>{tr("Информация о сервере","Server info")}</h2>
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -171,6 +171,8 @@ fetch overlay/phobos-pull.sh "$PHOBOS_DIR/repo/client/templat
|
|||||||
fetch server/phobos-health.sh "$PHOBOS_DIR/server/phobos-health.sh" && chmod +x "$PHOBOS_DIR/server/phobos-health.sh"
|
fetch server/phobos-health.sh "$PHOBOS_DIR/server/phobos-health.sh" && chmod +x "$PHOBOS_DIR/server/phobos-health.sh"
|
||||||
fetch server/phobos-pull.sh "$PHOBOS_DIR/server/phobos-pull.sh" && chmod +x "$PHOBOS_DIR/server/phobos-pull.sh"
|
fetch server/phobos-pull.sh "$PHOBOS_DIR/server/phobos-pull.sh" && chmod +x "$PHOBOS_DIR/server/phobos-pull.sh"
|
||||||
fetch server/phobos-router-watchdog.py "$PHOBOS_DIR/server/phobos-router-watchdog.py"
|
fetch server/phobos-router-watchdog.py "$PHOBOS_DIR/server/phobos-router-watchdog.py"
|
||||||
|
fetch update.sh "$PHOBOS_DIR/server/update.sh" && chmod +x "$PHOBOS_DIR/server/update.sh" && ln -sf "$PHOBOS_DIR/server/update.sh" /usr/local/bin/phobos-update
|
||||||
|
mkdir -p "$PANEL_DIR"; fetch VERSION "$PANEL_DIR/.version" 2>/dev/null || true
|
||||||
[ -f "$PHOBOS_DIR/tokens/tokens.json" ] || echo '[]' > "$PHOBOS_DIR/tokens/tokens.json"
|
[ -f "$PHOBOS_DIR/tokens/tokens.json" ] || echo '[]' > "$PHOBOS_DIR/tokens/tokens.json"
|
||||||
|
|
||||||
# ── 7. web panel ──
|
# ── 7. web panel ──
|
||||||
|
|||||||
94
update.sh
Executable file
94
update.sh
Executable file
@@ -0,0 +1,94 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
|
# PCA Phobos — updater / rollback
|
||||||
|
#
|
||||||
|
# phobos-update # обновить до последней версии (main)
|
||||||
|
# phobos-update v1.1.0 # обновить до конкретной версии (git tag)
|
||||||
|
# phobos-update --rollback # откатить на предыдущую версию (из бэкапа)
|
||||||
|
# phobos-update --version # показать установленную и последнюю версию
|
||||||
|
# phobos-update --list # список бэкапов для отката
|
||||||
|
#
|
||||||
|
# Обновляет ТОЛЬКО PCA-слой (панель + скрипты онбординга/служебные).
|
||||||
|
# НЕ трогает ключи WireGuard, server.env, клиентов — они сохраняются.
|
||||||
|
# Перед каждым обновлением делает бэкап; откат восстанавливает его.
|
||||||
|
# ============================================================
|
||||||
|
set -e
|
||||||
|
PHOBOS_DIR=/opt/Phobos
|
||||||
|
PANEL_DIR=/opt/phobos-panel
|
||||||
|
REPO=andrey271192/PCA_Phobos
|
||||||
|
RAW="https://raw.githubusercontent.com/$REPO"
|
||||||
|
BACKUPS="$PHOBOS_DIR/updates"
|
||||||
|
VERFILE="$PANEL_DIR/.version"
|
||||||
|
CUR=$(cat "$VERFILE" 2>/dev/null || echo "unknown")
|
||||||
|
|
||||||
|
managed_files() {
|
||||||
|
cat <<LIST
|
||||||
|
$PANEL_DIR/app.py|app.py
|
||||||
|
$PHOBOS_DIR/repo/server/scripts/phobos-client.sh|overlay/phobos-client.sh
|
||||||
|
$PHOBOS_DIR/repo/client/templates/install-router.sh.template|overlay/install-router.sh.template
|
||||||
|
$PHOBOS_DIR/repo/client/templates/router-configure-wireguard.sh|overlay/router-configure-wireguard.sh
|
||||||
|
$PHOBOS_DIR/repo/client/templates/phobos-pull.sh|overlay/phobos-pull.sh
|
||||||
|
$PHOBOS_DIR/server/phobos-health.sh|server/phobos-health.sh
|
||||||
|
$PHOBOS_DIR/server/phobos-pull.sh|server/phobos-pull.sh
|
||||||
|
$PHOBOS_DIR/server/phobos-router-watchdog.py|server/phobos-router-watchdog.py
|
||||||
|
$PHOBOS_DIR/server/update.sh|update.sh
|
||||||
|
LIST
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_version() { curl -fsSL -m10 "$RAW/main/VERSION" 2>/dev/null | tr -d ' \r\n'; }
|
||||||
|
|
||||||
|
do_backup() {
|
||||||
|
local dir="$BACKUPS/${CUR}-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
mkdir -p "$dir"
|
||||||
|
managed_files | while IFS='|' read -r lp rp; do
|
||||||
|
[ -f "$lp" ] && install -D "$lp" "$dir/$rp" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
echo "$CUR" > "$dir/.fromversion"
|
||||||
|
echo "$dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_ref() {
|
||||||
|
local ref="$1"
|
||||||
|
managed_files | while IFS='|' read -r lp rp; do
|
||||||
|
local tmp; tmp=$(mktemp)
|
||||||
|
if curl -fsSL -m25 "$RAW/$ref/$rp" -o "$tmp" && [ -s "$tmp" ]; then
|
||||||
|
mkdir -p "$(dirname "$lp")"; mv "$tmp" "$lp"
|
||||||
|
case "$lp" in *.sh|*.py) chmod +x "$lp" 2>/dev/null || true;; esac
|
||||||
|
else
|
||||||
|
rm -f "$tmp"; echo " WARN: не удалось скачать $rp (пропуск)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
--version|-v)
|
||||||
|
echo "Установлено: $CUR"
|
||||||
|
echo "Доступно: $(latest_version)"
|
||||||
|
;;
|
||||||
|
--list)
|
||||||
|
echo "Бэкапы (для отката):"
|
||||||
|
ls -dt "$BACKUPS"/*/ 2>/dev/null | sed 's#.*/updates/##' || echo " нет"
|
||||||
|
;;
|
||||||
|
--rollback)
|
||||||
|
last=$(ls -dt "$BACKUPS"/*/ 2>/dev/null | head -1)
|
||||||
|
[ -z "$last" ] && { echo "Нет бэкапа для отката."; exit 1; }
|
||||||
|
fromver=$(cat "$last/.fromversion" 2>/dev/null || echo "?")
|
||||||
|
echo "Откат на $fromver ($last)"
|
||||||
|
managed_files | while IFS='|' read -r lp rp; do
|
||||||
|
[ -f "$last/$rp" ] && { mkdir -p "$(dirname "$lp")"; cp "$last/$rp" "$lp"; chmod +x "$lp" 2>/dev/null || true; }
|
||||||
|
done
|
||||||
|
echo "$fromver" > "$VERFILE"
|
||||||
|
systemctl restart phobos-panel 2>/dev/null || true
|
||||||
|
echo "Откат выполнен -> $fromver"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ref="${1:-main}"; [ "$ref" = "latest" ] && ref="main"
|
||||||
|
target=$(curl -fsSL -m10 "$RAW/$ref/VERSION" 2>/dev/null | tr -d ' \r\n'); [ -z "$target" ] && target="$ref"
|
||||||
|
echo "Текущая: $CUR -> целевая: $target ($ref)"
|
||||||
|
b=$(do_backup); echo "Бэкап: $b"
|
||||||
|
apply_ref "$ref"
|
||||||
|
echo "$target" > "$VERFILE"
|
||||||
|
systemctl restart phobos-panel 2>/dev/null || true
|
||||||
|
echo "Обновлено до $target. Откат: phobos-update --rollback"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user