From 0143eafde71ca01581eef5c369c9e8317f91c673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B2?= Date: Fri, 5 Jun 2026 20:17:34 +0300 Subject: [PATCH] fix: reset admin password on reinstall --- README.md | 20 ++++++++++++++++++++ scripts/install.sh | 8 ++++---- server.js | 19 +++++++++++++++---- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6b96ec9..aaa8efe 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,22 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scrip Принудительная пересборка образа: **`NO_CACHE=1`**. +Сброс пароля панели при переустановке: + +```bash +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scripts/install.sh \ + | sudo ADMIN_PASSWORD='НОВЫЙ_ПАРОЛЬ' bash +``` + +Если старый **`/opt/amnezia-admin-data/password.hash`** уже есть, установщик сделает backup hash, удалит старую сессию и поднимет контейнер с новым паролем. + +PRO-инструменты сервера (Cloudflare WARP, каскад, синхронизация времени хоста) включаются явно: + +```bash +curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scripts/install.sh \ + | sudo ENABLE_PRO_TOOLS=1 bash +``` + --- ## Удаление @@ -180,6 +196,10 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scrip Если на хосте уже что-то слушает **TCP 80**, установщик сообщит об этом и, при дефолтном **`LANDING_PORT=80`**, сам попробует другой свободный порт (обычно начиная с **8081**). Либо явно: **`LANDING_PORT=8083`**, либо **`SKIP_LANDING=1`**. +### После переустановки пишет «Неверный пароль» + +Переустановка сохраняет **`/opt/amnezia-admin-data/password.hash`**, чтобы случайный апгрейд не сбросил доступ. Чтобы намеренно задать новый пароль, передайте **`ADMIN_PASSWORD`** при установке. Старый hash будет сохранён рядом как **`password.hash.bak.*`**. + ### Раздел MTProto или вся панель: ошибка «Not found», API не отвечает Чаще всего браузер бьётся не в **Node**‑процесс панели, а в **прокси** (nginx и т.п.) с неполным маппингом: **`/api/mtproto/*`**, **`/api/clients`** и остальное должны уходить на тот же upstream, что и **`/`** панели. Должен проксироваться **любой** путь под **`/api/`**, а не только отдельные location. На самой VPS **`curl -fsS http://127.0.0.1:ПОРТ_ПАНЕЛИ/health`** должен вернуть JSON с **`version`**. Если с localhost работает, а через домен — **404**, смотрите конфигурацию обратного прокси и TLS. diff --git a/scripts/install.sh b/scripts/install.sh index de6e86f..fdbfbe9 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -168,7 +168,7 @@ if docker inspect "${CONTAINER_NAME}" >/dev/null 2>&1; then PREV_CONTAINER_ENV="$(docker inspect "${CONTAINER_NAME}" --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null || true)" fi for __reuse_var in UI_HIDE_SECTIONS UI_HIDE_USERS UI_HIDE_WARP UI_HIDE_CASCADE WARP_SSH_INSTALL_DIR \ - EXPORT_CONFIG_SECRET CLIENT_CONFIG_ENDPOINT CLIENT_EXPORT_DNS1 CLIENT_EXPORT_DNS2; do + EXPORT_CONFIG_SECRET CLIENT_CONFIG_ENDPOINT CLIENT_EXPORT_DNS1 CLIENT_EXPORT_DNS2 ENABLE_PRO_TOOLS PANEL_EDITION; do if [[ -z "${!__reuse_var:-}" ]] && [[ -n "${PREV_CONTAINER_ENV}" ]]; then PREV_VAL="" while IFS= read -r __line; do @@ -223,7 +223,7 @@ for __warp_var in WARP_DIR WARP_CONF_PATH WARP_CLIENTS_LIST AMNEZIA_START_SCRIPT done for __panel_env_var in UI_HIDE_SECTIONS UI_HIDE_USERS UI_HIDE_WARP UI_HIDE_CASCADE UI_HIDE_MTPROTO \ - EXPORT_CONFIG_SECRET CLIENT_CONFIG_ENDPOINT CLIENT_EXPORT_DNS1 CLIENT_EXPORT_DNS2; do + EXPORT_CONFIG_SECRET CLIENT_CONFIG_ENDPOINT CLIENT_EXPORT_DNS1 CLIENT_EXPORT_DNS2 ENABLE_PRO_TOOLS PANEL_EDITION; do if [[ -n "${!__panel_env_var:-}" ]]; then RUN_ENV+=( -e "${__panel_env_var}=${!__panel_env_var}" ) fi @@ -302,7 +302,7 @@ fi # Выводим пароль в stdout по запросу пользователя. # 1) Первый запуск: пароль генерится/приходит через ADMIN_PASSWORD. -# 2) Переустановка/апгрейд: если есть только password.hash — пароль восстановить нельзя. +# 2) Переустановка/апгрейд: ADMIN_PASSWORD явно сбрасывает старый hash. if [[ -f "${PASS_FILE}" ]]; then __pw="$(tr -d '\r\n' <"${PASS_FILE}" || true)" if [[ -n "${__pw}" ]]; then @@ -312,7 +312,7 @@ elif [[ -n "${BOOT_PW}" ]]; then echo "Первый пароль: ${BOOT_PW}" elif [[ -f "${DATA_DIR}/password.hash" ]]; then echo "Пароль уже задан ранее (обнаружен ${DATA_DIR}/password.hash) — текущий пароль восстановить нельзя." - echo "Чтобы задать новый пароль: остановите контейнер, удалите ${DATA_DIR}/password.hash и запустите установку с переменной окружения ADMIN_PASSWORD=…" + echo "Чтобы задать новый пароль: снова запустите установку с переменной окружения ADMIN_PASSWORD=…" fi if [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then echo "Пароль по умолчанию (смените в панели): AmneziaAdmin!ChangeMe" diff --git a/server.js b/server.js index a407e72..bf23fac 100644 --- a/server.js +++ b/server.js @@ -29,6 +29,11 @@ function envTruthy(v) { return s === "1" || s === "true" || s === "yes"; } +function proToolsEnabled() { + const edition = process.env.PANEL_EDITION?.trim().toLowerCase(); + return envTruthy(process.env.ENABLE_PRO_TOOLS) || edition === "pro"; +} + /** Какие блоки веб-интерфейса скрыты: `UI_HIDE_SECTIONS=users,warp,cascade` или `UI_HIDE_USERS` и т.д. */ function resolveUiHidden() { const raw = process.env.UI_HIDE_SECTIONS?.trim(); @@ -101,19 +106,21 @@ function panelPromoFooterPayload() { } function editionPayload() { + const pro = proToolsEnabled(); return { readOnlyClients: false, allowDeleteClients: true, - showDebugWg: false, - proHostTools: false, + showDebugWg: pro, + proHostTools: pro, }; } function effectiveUiHidden() { + const pro = proToolsEnabled(); return { users: UI_HIDDEN.users, - warp: true, - cascade: true, + warp: UI_HIDDEN.warp || !pro, + cascade: UI_HIDDEN.cascade || !pro, mtproto: UI_HIDDEN.mtproto, }; } @@ -424,6 +431,10 @@ function rejectUnavailableFeature(res) { } function requireProTier(_req, res, next) { + if (proToolsEnabled()) { + next(); + return; + } rejectUnavailableFeature(res); }