From 05e6d007e217154167eb7da48aed3504a2330afe 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: Sat, 6 Jun 2026 14:16:56 +0300 Subject: [PATCH] docs: make pro repo public install source --- README.md | 56 +++++++++++++--------------------------------- package.json | 2 +- public/app.js | 4 ++-- scripts/install.sh | 43 +++++++++++++---------------------- server.js | 24 +++++--------------- 5 files changed, 40 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index b5c6772..a136d1f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # amnezia_web-PRO -### Редакции: открытая база и PRO +## Public PRO panel -- **[amnezia_web](https://github.com/andrey271192/amnezia_web)** — открытый репозиторий **базовой** панели: **только просмотр** клиентов AmneziaWG и статусов. Нет включения/выключения peer в туннеле, правки дат отключения, переименования, удаления, экспорта `.conf`, блока «Новый клиент под каскад», Cloudflare WARP, Telegram MTProto‑прокси и синхронизации времени хоста по SSH. Редакция задаётся файлом **`.amnezia-panel-edition`** со значением `community` (его подставляет установщик этого форка) или переменной **`AMNEZIA_EDITION=community`**. Текст и кнопка «Разблокировать PRO» используют **`COMMUNITY_UPGRADE_URL`** и **`COMMUNITY_UPGRADE_PITCH`** (по умолчанию URL ведёт на страницу подписки уровня PRO на Boosty). Типичная установка PRO для подписчиков — через публичный **[amnezia-web-pro-deploy](https://github.com/andrey271192/amnezia-web-pro-deploy)** (Compose + образ GHCR); исходники **amnezia_web-PRO** — приватный репозиторий для сборки из кода при необходимости. +**amnezia_web-PRO** — public full Amnezia Web panel. One repository, one installer, no private download flow and no separate deploy repository. -- **Этот репозиторий (`amnezia_web-PRO`)** — **полная** панель (редакция **pro** по умолчанию): все функции из README ниже активны, если не задана **`AMNEZIA_EDITION=community`**. +Base project **[amnezia_web](https://github.com/andrey271192/amnezia_web)** remains a lighter open panel. This repository contains the full PRO feature set by default. ## Что открывается по какому порту @@ -23,30 +23,20 @@ Панель: заголовок, подсказки по расписанию и нескольким инстансам, форма смены пароля

-Те же иллюстрации подходят и для связки установки через **[amnezia-web-pro-deploy](https://github.com/andrey271192/amnezia-web-pro-deploy)** (контент панели тот же). Файлы: `docs/screenshots/panel-users-table.png`, `docs/screenshots/panel-overview-password.png` — замените на свои живые PNG при необходимости. +Файлы: `docs/screenshots/panel-users-table.png`, `docs/screenshots/panel-overview-password.png` — замените на свои живые PNG при необходимости. --- ## Установка -### Подписчики PRO: публичный репозиторий с Docker Compose - -Рабочую установку **в проде** автор ведёт не через сборку этого приватного репозитория с GitHub tarball, а через **открытый** бандл **[amnezia-web-pro-deploy](https://github.com/andrey271192/amnezia-web-pro-deploy)**: там `docker compose`, образ из **GHCR** и один скрипт `quick-install.sh`. Подробности, пат для **`docker pull`** (`read:packages`) и переход FREE → PRO — **в README того репозитория**: - -```bash -curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash -``` - -Панель после установки по-прежнему открывается в браузере по **`http://IP:HOST_PORT`** (порт задаётся в процессе установки / в `.env` деплоя). - -### Сборка из исходников (`amnezia_web-PRO`) - -Подходит для разработки и самособорки локально или при полном доступе к коду на GitHub: +### Public install from GitHub ```bash curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash ``` +Панель после установки открывается по **`http://IP:HOST_PORT`** (по умолчанию `:8080`). Первый вход: **логин `admin`, пароль `admin`**. Смените пароль сразу после входа. + ### Переменные окружения и `sudo` Частая ошибка: задали **`AWG_PROFILES`**, **`ADMIN_PASSWORD`** или другую переменную из таблицы «в одной строке» перед `curl`, а затем выполнили **`curl … | sudo bash`**. По умолчанию **`sudo` не передаёт** это окружение в `bash`, который читает установочный скрипт с stdin: установщик **не увидит** переменные, переключатель **«Инстанс»** не появится. @@ -106,7 +96,6 @@ cd /opt/amnezia-admin && chmod +x scripts/install.sh && sudo SKIP_DOWNLOAD=1 bas | `EXPORT_CONFIG_SECRET` | _(нет)_ | Секрет для прямой ссылки без входа в панель: `GET /api/clients/export-config?token=СЕКРЕТ&clientId=…&profileId=…` (при нескольких инстансах `profileId` обязателен). Не светите URL посторонним | | `ADMIN_PASSWORD` | _(генерируется)_ | Первый пароль вместо файла | | `SKIP_DOWNLOAD` | `0` | `1` — не качать GitHub, собрать из `INSTALL_DIR` | -| `ALLOW_DEFAULT_PASSWORD` | `0` | `1` — см. раздел «Пароль» ниже | | `SKIP_LANDING` | `0` | `1` — не поднимать nginx-лендинг на `LANDING_PORT` | | `LANDING_PORT` | `80` | Порт nginx-лендинга (если `80` занят — например `8081`) | | `LANDING_CONTAINER` | `amnezia-web-landing` | Имя контейнера лендинга | @@ -247,9 +236,7 @@ UI_HIDE_SECTIONS=warp,cascade curl -fsSL https://raw.githubusercontent.com/andre ### Обновление до новой версии -Если панель стоит через **[amnezia-web-pro-deploy](https://github.com/andrey271192/amnezia-web-pro-deploy)** (Compose + образ из GHCR), обновление по инструкции **того** репозитория — см. блок **«Обновление»** в его README (**`IMAGE_TAG`** / **`scripts/update.sh`**). - -Если же вы собирали из этого репозитория через **`scripts/install.sh`**, коммиты на GitHub **сами не попадают** в уже запущенный контейнер: нужно заново **скачать код и пересобрать образ** (`amnezia-admin` и, если не отключали лендинг, **`amnezia-web-landing`**). +Коммиты на GitHub **сами не попадают** в уже запущенный контейнер: нужно заново **скачать код и пересобрать образ** (`amnezia-admin` и, если не отключали лендинг, **`amnezia-web-landing`**). Проще всего для пути из исходников — та же команда, что при установке (данные в `DATA_DIR`, пароль и `AWG_PROFILES` сохранятся — профили подтягиваются из файла на VPS или из старого контейнера). Скрипт **подставит прежний внешний порт** контейнера `amnezia-admin`, если вы не передавали `HOST_PORT` и в коде по умолчанию стоит `8080`: @@ -299,15 +286,14 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/s ## Первый вход и пароль -### Режим по умолчанию (рекомендуется) +### Режим по умолчанию -Скрипт установки **генерирует** пароль и записывает его в файл на сервере: +На пустой установке создаётся первый вход: -```bash -sudo cat /root/amnezia-admin.initial-password -``` +- логин: **`admin`** +- пароль: **`admin`** -Войдите в панель этим паролем и сразу смените его в блоке **«Сменить пароль»**. +Смените пароль сразу после входа в блоке **«Сменить пароль»**. ### Свой пароль при установке @@ -317,23 +303,11 @@ ADMIN_PASSWORD='ВашНадёжныйПароль' curl -fsSL https://raw.githu После первого успешного старта переменную `ADMIN_PASSWORD` из команды `docker run` убирайте — пароль уже в томе `DATA_DIR`. -### Пароль по умолчанию из документации (только тест / лаборатория) - -Если задать при установке **`ALLOW_DEFAULT_PASSWORD=1`**, контейнер создаёт пароль из README: - -- **Логин в веб:** пароль по умолчанию **`AmneziaAdmin!ChangeMe`** - -Его можно переопределить переменной **`DEFAULT_ADMIN_PASSWORD`** в окружении контейнера до первого создания `password.hash`. - -На продакшене этот режим **не рекомендуется**. - ### Ручной Docker без скрипта -Нужны том `-v /путь/данных:/data` и **один из** вариантов: +Нужен том `-v /путь/данных:/data`. -1. `-e ADMIN_PASSWORD=...` при **первом** запуске (файла `password.hash` ещё нет); -2. `-e ALLOW_DEFAULT_PASSWORD=1` — см. пароль выше; -3. готовый файл `password.hash` в томе (продвинутый сценарий). +Если `password.hash` ещё нет, контейнер создаст `admin/admin`. Для своего первого пароля передайте `-e ADMIN_PASSWORD=...`. Для продвинутого сценария можно заранее положить готовый `password.hash` в том. --- diff --git a/package.json b/package.json index 7e48d02..eca3a41 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "amnezia-admin", "version": "1.2.28", - "private": true, + "private": false, "description": "amnezia_web-PRO — веб-панель AmneziaWG: несколько инстансов, WARP, каскад/Endpoint, экспорт .conf (Docker)", "license": "MIT", "repository": { diff --git a/public/app.js b/public/app.js index f2bf772..e1782b4 100644 --- a/public/app.js +++ b/public/app.js @@ -131,8 +131,8 @@ function applyEditionPayload(data) { cta.target = "_blank"; cta.href = editionState.upgradeUrl || - "https://boosty.to/andrey27/purchase/3906453?ssource=DIRECT&share=subscription_link"; - cta.textContent = "Разблокировать PRO (Boosty)"; + "https://github.com/andrey271192/amnezia_web-PRO"; + cta.textContent = "Открыть PRO на GitHub"; wrap.append(textCol, cta); editionBanner.appendChild(wrap); } else { diff --git a/scripts/install.sh b/scripts/install.sh index db2b923..d0caf23 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -55,25 +55,13 @@ if [[ "${SKIP_DOWNLOAD:-}" != "1" ]]; then --retry-connrefused ) if [[ "${INSTALL_SCRIPT_VERBOSE:-}" == "1" ]]; then CURL_OPTS+=(--progress-bar); fi - # Поддержка GITHUB_TOKEN / GH_TOKEN: для приватных репозиториев публичный - # URL /archive/refs/heads/.tar.gz отдаёт 404 без авторизации. - GH_AUTH_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}" - if [[ -n "${GH_AUTH_TOKEN}" ]]; then - CURL_OPTS+=(-H "Authorization: Bearer ${GH_AUTH_TOKEN}") - CURL_OPTS+=(-H "X-GitHub-Api-Version: 2022-11-28") - fi CURL_URL="${GITHUB_REPO_URL_OVERRIDE:-}" if [[ -z "${CURL_URL}" ]]; then - if [[ -n "${GH_AUTH_TOKEN}" ]]; then - # API-tarball работает и для приватных репо, и для публичных. - CURL_URL="https://api.github.com/repos/${GITHUB_REPO}/tarball/${BRANCH}" - else - CURL_URL="https://github.com/${GITHUB_REPO}/archive/refs/heads/${BRANCH}.tar.gz" - fi + CURL_URL="https://github.com/${GITHUB_REPO}/archive/refs/heads/${BRANCH}.tar.gz" fi if ! curl "${CURL_OPTS[@]}" "${CURL_URL}" | tar xz -C "${TMP}"; then echo "Ошибка: не удалось скачать или распаковать архив (${CURL_URL})." - echo "Подсказка: проверьте токен (для приватного репо нужен GITHUB_TOKEN/GH_TOKEN с правом Contents:Read), ping/curl до github.com, при необходимости export GITHUB_REPO_URL_OVERRIDE='…' или INSTALL_SCRIPT_VERBOSE=1." + echo "Подсказка: проверьте доступ к github.com, branch/repo, при необходимости export GITHUB_REPO_URL_OVERRIDE='…' или INSTALL_SCRIPT_VERBOSE=1." exit 1 fi echo "→ Перенос распакованного дерева в ${INSTALL_DIR}…" @@ -110,18 +98,24 @@ fi BOOT_PW="" PASS_FILE="/root/amnezia-admin.initial-password" -if [[ -f "${DATA_DIR}/password.hash" ]]; then - echo "→ В ${DATA_DIR} уже есть password.hash — контейнер поднимется с прежним паролем." -elif [[ -n "${ADMIN_PASSWORD:-}" ]]; then +if [[ -n "${ADMIN_PASSWORD:-}" ]]; then BOOT_PW="${ADMIN_PASSWORD}" - echo "→ Использую ADMIN_PASSWORD из окружения." -elif [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then - echo "→ ALLOW_DEFAULT_PASSWORD=1 — см. README, пароль по умолчанию для входа." + if [[ -f "${DATA_DIR}/password.hash" ]]; then + __pw_backup="${DATA_DIR}/password.hash.bak.$(date -u +%Y%m%dT%H%M%SZ)" + cp -p "${DATA_DIR}/password.hash" "${__pw_backup}" 2>/dev/null || true + rm -f "${DATA_DIR}/password.hash" + rm -f "${DATA_DIR}/session.secret" + echo "→ ADMIN_PASSWORD задан — сбрасываю старый пароль панели (backup: ${__pw_backup})." + else + echo "→ Использую ADMIN_PASSWORD из окружения." + fi +elif [[ -f "${DATA_DIR}/password.hash" ]]; then + echo "→ В ${DATA_DIR} уже есть password.hash — контейнер поднимется с прежним паролем." else - BOOT_PW="$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 22 || openssl rand -hex 16)" + BOOT_PW="admin" umask 077 printf '%s\n' "${BOOT_PW}" >"${PASS_FILE}" - echo "→ Первый пароль записан в ${PASS_FILE}" + echo "→ Первый вход: admin / admin. Смените пароль сразу после входа." fi # AWG_PROFILES: не терять при апдейте без переменной (пропадает список «Инстанс»). @@ -240,8 +234,6 @@ done if [[ -n "${BOOT_PW}" ]]; then RUN_ENV+=( -e "ADMIN_PASSWORD=${BOOT_PW}" ) -elif [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then - RUN_ENV+=( -e "ALLOW_DEFAULT_PASSWORD=1" ) fi if [[ -n "${AMNEZIA_EDITION:-}" ]]; then @@ -293,8 +285,5 @@ fi if [[ -f "${PASS_FILE}" ]]; then echo "Первый пароль: $(cat "${PASS_FILE}")" fi -if [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "1" ]] || [[ "${ALLOW_DEFAULT_PASSWORD:-}" == "true" ]]; then - echo "Пароль по умолчанию (смените в панели): AmneziaAdmin!ChangeMe" -fi echo "" echo "Удаление: curl -fsSL https://raw.githubusercontent.com/${GITHUB_REPO}/${BRANCH}/scripts/uninstall.sh | sudo bash" diff --git a/server.js b/server.js index 3dfa29c..eb32914 100644 --- a/server.js +++ b/server.js @@ -53,10 +53,10 @@ const AMNEZIA_EDITION = (process.env.AMNEZIA_EDITION || "pro").trim().toLowerCas const IS_COMMUNITY = AMNEZIA_EDITION === "community"; const COMMUNITY_UPGRADE_URL = process.env.COMMUNITY_UPGRADE_URL?.trim() || - "https://boosty.to/andrey27/purchase/3906453?ssource=DIRECT&share=subscription_link"; + "https://github.com/andrey271192/amnezia_web-PRO"; const COMMUNITY_UPGRADE_PITCH = process.env.COMMUNITY_UPGRADE_PITCH?.trim() || - "В PRO: вкл/выкл клиентов, даты и расписание отключений, переименование, удаление, экспорт .conf, каскад, Cloudflare WARP, синхронизация времени хоста. Полная сборка — приватный репозиторий amnezia_web-PRO; доступ по подписке Boosty."; + "В PRO: вкл/выкл клиентов, даты и расписание отключений, переименование, удаление, экспорт .conf, каскад, Cloudflare WARP, синхронизация времени хоста. Полная сборка открыта в публичном репозитории amnezia_web-PRO."; function editionPayload() { return { @@ -219,22 +219,10 @@ function bootstrapPassword() { ); return; } - const allowDefault = - process.env.ALLOW_DEFAULT_PASSWORD === "1" || - process.env.ALLOW_DEFAULT_PASSWORD === "true"; - const docPass = process.env.DEFAULT_ADMIN_PASSWORD || "AmneziaAdmin!ChangeMe"; - if (allowDefault) { - passwordHashStored = hashPassword(docPass); - fs.writeFileSync(PW_FILE, `${passwordHashStored}\n`, { mode: 0o600 }); - console.warn( - "Включён пароль по умолчанию из документации (README). Смените его в панели и отключите ALLOW_DEFAULT_PASSWORD." - ); - return; - } - console.error( - "Нет пароля: задайте ADMIN_PASSWORD при первом запуске, см. README, или ALLOW_DEFAULT_PASSWORD=1 только для теста." - ); - process.exit(1); + const defaultPassword = process.env.DEFAULT_ADMIN_PASSWORD || "admin"; + passwordHashStored = hashPassword(defaultPassword); + fs.writeFileSync(PW_FILE, `${passwordHashStored}\n`, { mode: 0o600 }); + console.warn("Первый вход: admin / admin. Смените пароль сразу после входа."); } function signSession(payload) {