fix: reset admin password on reinstall

This commit is contained in:
Андрей Бобырев
2026-06-05 20:17:34 +03:00
committed by andrey271192
parent 0a3f9de717
commit 0143eafde7
3 changed files with 39 additions and 8 deletions

View File

@@ -134,6 +134,22 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web/main/scrip
Принудительная пересборка образа: **`NO_CACHE=1`**. Принудительная пересборка образа: **`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`**. Если на хосте уже что-то слушает **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 не отвечает ### Раздел 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. Чаще всего браузер бьётся не в **Node**‑процесс панели, а в **прокси** (nginx и т.п.) с неполным маппингом: **`/api/mtproto/*`**, **`/api/clients`** и остальное должны уходить на тот же upstream, что и **`/`** панели. Должен проксироваться **любой** путь под **`/api/`**, а не только отдельные location. На самой VPS **`curl -fsS http://127.0.0.1:ПОРТАНЕЛИ/health`** должен вернуть JSON с **`version`**. Если с localhost работает, а через домен — **404**, смотрите конфигурацию обратного прокси и TLS.

View File

@@ -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)" PREV_CONTAINER_ENV="$(docker inspect "${CONTAINER_NAME}" --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null || true)"
fi fi
for __reuse_var in UI_HIDE_SECTIONS UI_HIDE_USERS UI_HIDE_WARP UI_HIDE_CASCADE WARP_SSH_INSTALL_DIR \ 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 if [[ -z "${!__reuse_var:-}" ]] && [[ -n "${PREV_CONTAINER_ENV}" ]]; then
PREV_VAL="" PREV_VAL=""
while IFS= read -r __line; do 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 done
for __panel_env_var in UI_HIDE_SECTIONS UI_HIDE_USERS UI_HIDE_WARP UI_HIDE_CASCADE UI_HIDE_MTPROTO \ 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 if [[ -n "${!__panel_env_var:-}" ]]; then
RUN_ENV+=( -e "${__panel_env_var}=${!__panel_env_var}" ) RUN_ENV+=( -e "${__panel_env_var}=${!__panel_env_var}" )
fi fi
@@ -302,7 +302,7 @@ fi
# Выводим пароль в stdout по запросу пользователя. # Выводим пароль в stdout по запросу пользователя.
# 1) Первый запуск: пароль генерится/приходит через ADMIN_PASSWORD. # 1) Первый запуск: пароль генерится/приходит через ADMIN_PASSWORD.
# 2) Переустановка/апгрейд: если есть только password.hash — пароль восстановить нельзя. # 2) Переустановка/апгрейд: ADMIN_PASSWORD явно сбрасывает старый hash.
if [[ -f "${PASS_FILE}" ]]; then if [[ -f "${PASS_FILE}" ]]; then
__pw="$(tr -d '\r\n' <"${PASS_FILE}" || true)" __pw="$(tr -d '\r\n' <"${PASS_FILE}" || true)"
if [[ -n "${__pw}" ]]; then if [[ -n "${__pw}" ]]; then
@@ -312,7 +312,7 @@ elif [[ -n "${BOOT_PW}" ]]; then
echo "Первый пароль: ${BOOT_PW}" echo "Первый пароль: ${BOOT_PW}"
elif [[ -f "${DATA_DIR}/password.hash" ]]; then elif [[ -f "${DATA_DIR}/password.hash" ]]; then
echo "Пароль уже задан ранее (обнаружен ${DATA_DIR}/password.hash) — текущий пароль восстановить нельзя." echo "Пароль уже задан ранее (обнаружен ${DATA_DIR}/password.hash) — текущий пароль восстановить нельзя."
echo "Чтобы задать новый пароль: остановите контейнер, удалите ${DATA_DIR}/password.hash и запустите установку с переменной окружения ADMIN_PASSWORD=…" echo "Чтобы задать новый пароль: снова запустите установку с переменной окружения ADMIN_PASSWORD=…"
fi fi
if [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then if [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then
echo "Пароль по умолчанию (смените в панели): AmneziaAdmin!ChangeMe" echo "Пароль по умолчанию (смените в панели): AmneziaAdmin!ChangeMe"

View File

@@ -29,6 +29,11 @@ function envTruthy(v) {
return s === "1" || s === "true" || s === "yes"; 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` и т.д. */ /** Какие блоки веб-интерфейса скрыты: `UI_HIDE_SECTIONS=users,warp,cascade` или `UI_HIDE_USERS` и т.д. */
function resolveUiHidden() { function resolveUiHidden() {
const raw = process.env.UI_HIDE_SECTIONS?.trim(); const raw = process.env.UI_HIDE_SECTIONS?.trim();
@@ -101,19 +106,21 @@ function panelPromoFooterPayload() {
} }
function editionPayload() { function editionPayload() {
const pro = proToolsEnabled();
return { return {
readOnlyClients: false, readOnlyClients: false,
allowDeleteClients: true, allowDeleteClients: true,
showDebugWg: false, showDebugWg: pro,
proHostTools: false, proHostTools: pro,
}; };
} }
function effectiveUiHidden() { function effectiveUiHidden() {
const pro = proToolsEnabled();
return { return {
users: UI_HIDDEN.users, users: UI_HIDDEN.users,
warp: true, warp: UI_HIDDEN.warp || !pro,
cascade: true, cascade: UI_HIDDEN.cascade || !pro,
mtproto: UI_HIDDEN.mtproto, mtproto: UI_HIDDEN.mtproto,
}; };
} }
@@ -424,6 +431,10 @@ function rejectUnavailableFeature(res) {
} }
function requireProTier(_req, res, next) { function requireProTier(_req, res, next) {
if (proToolsEnabled()) {
next();
return;
}
rejectUnavailableFeature(res); rejectUnavailableFeature(res);
} }