mirror of
https://github.com/andrey271192/amnezia-web-pro-deploy.git
synced 2026-09-20 13:50:06 +00:00
fix: avoid GHCR 403 in default installer
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
# Скопируйте в .env и заполните значения из закрытого поста Boosty (только для подписчиков).
|
# Legacy GHCR mode only.
|
||||||
|
# Обычная установка больше не требует .env и GHCR PAT:
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash
|
||||||
|
#
|
||||||
|
# Этот файл нужен только если вы сознательно запускаете USE_GHCR=1.
|
||||||
|
|
||||||
# Образ из GHCR (пример; ваш продавец подставит точное значение)
|
# Образ из GHCR. Если package закрыт или PAT без read:packages, Docker вернёт 403 Forbidden.
|
||||||
GHCR_IMAGE=ghcr.io/andrey271192/amnezia-admin-pro
|
GHCR_IMAGE=ghcr.io/andrey271192/amnezia-admin-pro
|
||||||
IMAGE_TAG=v1.0.0
|
IMAGE_TAG=v1.0.0
|
||||||
|
|
||||||
|
|||||||
169
README.md
169
README.md
@@ -1,136 +1,113 @@
|
|||||||
# Amnezia Admin Pro — установка (Docker / GHCR)
|
# Amnezia Web PRO — установка
|
||||||
|
|
||||||
Скрипты, которые снимают FREE-панель [amnezia_web](https://github.com/andrey271192/amnezia_web) и поднимают PRO-образ с GitHub Container Registry. VPN-контейнеры (**`amnezia-awg`**, **`amnezia-awg2`**) не трогаем.
|
Публичный установщик для **Amnezia Web PRO**. По умолчанию ставит панель из открытого GitHub repo:
|
||||||
|
|
||||||
## Что понадобится на VPS
|
- source: [`andrey271192/amnezia_web-PRO_test`](https://github.com/andrey271192/amnezia_web-PRO_test)
|
||||||
|
- текущий релиз: `v1.5.2`
|
||||||
|
- old GHCR image больше не используется по умолчанию, чтобы у пользователей не было `403 Forbidden`.
|
||||||
|
|
||||||
- **Docker** и работающий демон.
|
## Быстрая установка
|
||||||
- **`docker compose`** v2 (не старый `docker-compose` 1.x — будет `ContainerConfig` / KeyError).
|
|
||||||
- **curl**, при первой установке — **git**.
|
|
||||||
- **Ключ** с Boosty: GitHub PAT с `read:packages` (не светите в чатах и на скринах).
|
|
||||||
|
|
||||||
`quick-install.sh` сам подтянет Compose v2, если в apt его нет (`scripts/lib-compose-v2.sh`).
|
На VPS от root:
|
||||||
|
|
||||||
## Как выглядит PRO
|
|
||||||
|
|
||||||
После установки — та же панель, что в **amnezia_web-PRO**:
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="docs/screenshots/panel-users-table.png" alt="Панель: пользователи AmneziaWG, инстансы, время, статусы" width="780"/>
|
|
||||||
<br/><br/>
|
|
||||||
<img src="docs/screenshots/panel-overview-password.png" alt="Панель: заголовок, форма смены пароля" width="780"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Одна команда — FREE → PRO (спросит только ключ)
|
|
||||||
|
|
||||||
На VPS **от root**:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
Скрипт **перед установкой PRO**:
|
То же самое с явным первым паролем admin:
|
||||||
|
|
||||||
1. **Убирает FREE-панель** из типового `install.sh` (**amnezia_web**): контейнеры `amnezia-admin`, `amnezia-web-landing`, локальные образы `amnezia-admin:latest` / `amnezia-web-landing:latest`, каталог сборки **`/opt/amnezia-admin`**.
|
|
||||||
2. **Не трогает** контейнеры VPN (**AmneziaWG / AWG**): **`amnezia-awg`**, **`amnezia-awg2`** и т.п.
|
|
||||||
3. Подставляет **`AWG_CONTAINER`** автоматически, если на сервере уже есть `amnezia-awg` или `amnezia-awg2`.
|
|
||||||
4. Клонирует/обновляет **`/opt/amnezia-web-pro-deploy`**, тянет тег из [`PRO_IMAGE_TAG`](PRO_IMAGE_TAG), запрашивает **ключ PAT** (ввод с **`/dev/tty`**).
|
|
||||||
|
|
||||||
Перед всем этим, если **`docker compose`** отсутствует, установщик **подтягивает** модуль Compose v2 (см. выше).
|
|
||||||
|
|
||||||
Отключить снос FREE (редко нужно): `SKIP_REMOVE_FREE=1 curl … | sudo -E bash`.
|
|
||||||
|
|
||||||
Если **нет интерактива** на stdin:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh -o /tmp/amnezia-quick-install.sh
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh \
|
||||||
sudo bash /tmp/amnezia-quick-install.sh
|
| sudo ADMIN_PASSWORD='СЛОЖНЫЙ_ПАРОЛЬ' bash
|
||||||
```
|
```
|
||||||
|
|
||||||
**Порт:** если после удаления FREE **8080** всё ещё занят — скрипт предложит другой или задайте `HOST_PORT=8081 curl … | sudo -E bash`.
|
`quick-install.sh` скачает и запустит рабочий установщик:
|
||||||
|
|
||||||
## Частые проблемы после установки
|
|
||||||
|
|
||||||
### `Bind for 0.0.0.0:8080 failed: port is already allocated`
|
|
||||||
|
|
||||||
На **8080** уже слушает другой процесс или контейнер (не только снятая FREE-панель). Посмотреть занятость: `ss -tlnp | grep ':8080'`. Обход: переустановка с **`HOST_PORT=8081`** (или свободный порт):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
HOST_PORT=8081 curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo -E bash
|
https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO_test/main/install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### `KeyError: 'ContainerConfig'` и в трассировке указан **`docker-compose` 1.29.x** (`/usr/lib/python3/...`)
|
## Почему больше не GHCR
|
||||||
|
|
||||||
Старый **Docker Compose v1** из пакета `docker-compose` **непонимает** образы из GHCR с современным OCI-манифестом без поля **`ContainerConfig`**. Нужна **Compose v2** — **`docker compose`**.
|
Старый сценарий тянул private image:
|
||||||
|
|
||||||
На актуальной ветке **`main`** установщики **не дергают legacy `docker-compose` 1.x**, а поднимают Compose v2 через APT (**если пакет виден**) либо **официальный CLI‑плагин с GitHub**.
|
```text
|
||||||
|
ghcr.io/andrey271192/amnezia-admin-pro:v1.0.0
|
||||||
```bash
|
|
||||||
sudo git -C /opt/amnezia-web-pro-deploy fetch origin main
|
|
||||||
sudo git -C /opt/amnezia-web-pro-deploy reset --hard origin/main
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Вручную: **`docker-compose-plugin`** из [репозитория Docker CE](https://docs.docker.com/engine/install/ubuntu/) или шаг из справки в **`scripts/lib-compose-v2.sh`**.
|
Если у GitHub PAT нет доступа к package или package закрыт, Docker показывает:
|
||||||
|
|
||||||
Если после неудачного `up` образовался полубитый контейнер:
|
```text
|
||||||
|
unexpected status ... 403 Forbidden
|
||||||
```bash
|
|
||||||
sudo docker rm -f amnezia-admin-pro 2>/dev/null || true
|
|
||||||
sudo bash /opt/amnezia-web-pro-deploy/scripts/install.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Если файл **`.env` удалён или пуст**, снова запустите **`quick-install.sh`** — он заново попросит PAT.
|
Это не ошибка VPS и не ошибка Docker. Это отказ GitHub Container Registry. Чтобы не ловить эту ошибку у подписчиков, обычная установка теперь идёт из GitHub source.
|
||||||
|
|
||||||
### `Unable to locate package docker-compose-plugin` (Ubuntu без репозитория Docker)
|
Предупреждение Docker:
|
||||||
|
|
||||||
Пакет поставляет официальный репозиторий Docker CE на Ubuntu/Debian. Если его подключать не хотите или `apt-get` всё равно пишет, что пакета нет:
|
```text
|
||||||
|
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'
|
||||||
1. Просто снова запустите обновлённый **`quick-install.sh`** после `git pull` репозитория установки — он попытается **скачать плагин Compose v2 напрямую** с GitHub (нужны `curl` и исходящий HTTPS до `github.com`).
|
|
||||||
|
|
||||||
Либо отдельно:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/scripts/lib-compose-v2.sh -o /tmp/lib-compose-v2.sh
|
|
||||||
sudo bash -c 'source /tmp/lib-compose-v2.sh && ensure_compose_v2'
|
|
||||||
sudo rm -f /tmp/lib-compose-v2.sh
|
|
||||||
docker compose version
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ручной способ (git + .env)
|
не является причиной ошибки. Это только предупреждение Docker.
|
||||||
|
|
||||||
|
## Legacy GHCR mode
|
||||||
|
|
||||||
|
Оставлен только для ручного использования, если у вас реально есть доступ к package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/andrey271192/amnezia-web-pro-deploy.git
|
USE_GHCR=1 curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo -E bash
|
||||||
cd amnezia-web-pro-deploy
|
```
|
||||||
cp .env.example .env
|
|
||||||
# заполните GHCR_* из закрытого поста Boosty
|
или:
|
||||||
sudo bash scripts/install.sh
|
|
||||||
|
```bash
|
||||||
|
USE_GHCR=1 sudo -E bash scripts/install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Нужны:
|
||||||
|
|
||||||
|
- GitHub PAT с `read:packages`;
|
||||||
|
- доступ к package `ghcr.io/andrey271192/amnezia-admin-pro`;
|
||||||
|
- существующий tag из `PRO_IMAGE_TAG`.
|
||||||
|
|
||||||
|
## Удаление
|
||||||
|
|
||||||
|
Обычная остановка панели:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO_test/main/uninstall.sh | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Полная очистка с данными:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO_test/main/uninstall.sh \
|
||||||
|
| sudo REMOVE_DATA=1 REMOVE_DIR=1 bash
|
||||||
```
|
```
|
||||||
|
|
||||||
## Обновление
|
## Обновление
|
||||||
|
|
||||||
После объявления нового тега образа обновите `IMAGE_TAG` в `.env` и выполните:
|
В панели: **Настройки → О программе и обновления → Проверить обновления**.
|
||||||
|
|
||||||
|
Доступно:
|
||||||
|
|
||||||
|
- release channel;
|
||||||
|
- beta channel;
|
||||||
|
- выбор версии;
|
||||||
|
- rollback на старый tag.
|
||||||
|
|
||||||
|
Ручное обновление source-установки:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo bash scripts/update.sh
|
cd /opt/amnezia-web-pro
|
||||||
|
git pull
|
||||||
|
docker compose build
|
||||||
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
## Шаблон поста для Boosty
|
|
||||||
|
|
||||||
См. [docs/BOOSTY_SUBSCRIBERS_POST.md](docs/BOOSTY_SUBSCRIBERS_POST.md).
|
|
||||||
|
|
||||||
## Безопасность
|
|
||||||
|
|
||||||
- Файл `.env` с токеном не должен попадать в issue, чаты и скриншоты.
|
|
||||||
- При утечке токена автор перевыпускает его в GitHub; подписчикам выдаётся новый токен в обновлённом посте.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Поддержка проекта
|
## Поддержка проекта
|
||||||
|
|
||||||
---
|
- GitHub: [andrey271192/amnezia_web-PRO_test](https://github.com/andrey271192/amnezia_web-PRO_test)
|
||||||
|
- Boosty: [boosty.to/andrey27/donate](https://boosty.to/andrey27/donate)
|
||||||
- ⭐ **GitHub:** [andrey271192/amnezia-web-pro-deploy](https://github.com/andrey271192/amnezia-web-pro-deploy)
|
- Telegram: [@lot_andrey](https://t.me/lot_andrey)
|
||||||
- 💖 **Boosty:** [boosty.to/andrey27/donate](https://boosty.to/andrey27/donate)
|
|
||||||
- 💳 **Ozon Bank (СБП):** [ссылка](https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798)
|
|
||||||
- ✉️ **Telegram:** [@lot_andrey](https://t.me/lot_andrey)
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Одна команда: curl … | sudo bash — спросит только ключ (PAT для ghcr.io).
|
# One-command installer kept for old links. Default path now installs from the
|
||||||
|
# open source repo, not the private GHCR image, so subscribers do not hit 403.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
DEPLOY_REPO="${DEPLOY_REPO:-https://github.com/andrey271192/amnezia-web-pro-deploy.git}"
|
|
||||||
RAW_BASE="${RAW_BASE:-https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main}"
|
RAW_BASE="${RAW_BASE:-https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main}"
|
||||||
INSTALL_ROOT="${INSTALL_ROOT:-/opt/amnezia-web-pro-deploy}"
|
SOURCE_INSTALL_URL="${SOURCE_INSTALL_URL:-https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO_test/main/install.sh}"
|
||||||
|
|
||||||
DEFAULT_GHCR_IMAGE="${DEFAULT_GHCR_IMAGE:-ghcr.io/andrey271192/amnezia-admin-pro}"
|
|
||||||
DEFAULT_GHCR_USERNAME="${DEFAULT_GHCR_USERNAME:-andrey271192}"
|
|
||||||
|
|
||||||
need_root() {
|
need_root() {
|
||||||
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
||||||
@@ -18,11 +15,38 @@ need_root() {
|
|||||||
|
|
||||||
need_cmd() {
|
need_cmd() {
|
||||||
command -v "$1" >/dev/null 2>&1 || {
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
echo "Нужна утилита: $1 (например: apt-get install -y $1)"
|
echo "Нужна утилита: $1"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_root
|
||||||
|
need_cmd curl
|
||||||
|
|
||||||
|
if [[ "${USE_GHCR:-0}" != "1" ]]; then
|
||||||
|
echo "→ GHCR-установка отключена: старый private image часто даёт 403 Forbidden."
|
||||||
|
echo "→ Ставлю Amnezia Web PRO из GitHub: ${SOURCE_INSTALL_URL}"
|
||||||
|
echo "→ Для старого GHCR-сценария запустите: USE_GHCR=1 curl ... | sudo -E bash"
|
||||||
|
echo ""
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
trap 'rm -f "$tmp"' EXIT
|
||||||
|
curl -fsSL "${SOURCE_INSTALL_URL}" -o "$tmp"
|
||||||
|
exec bash "$tmp"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEPLOY_REPO="${DEPLOY_REPO:-https://github.com/andrey271192/amnezia-web-pro-deploy.git}"
|
||||||
|
INSTALL_ROOT="${INSTALL_ROOT:-/opt/amnezia-web-pro-deploy}"
|
||||||
|
|
||||||
|
DEFAULT_GHCR_IMAGE="${DEFAULT_GHCR_IMAGE:-ghcr.io/andrey271192/amnezia-admin-pro}"
|
||||||
|
DEFAULT_GHCR_USERNAME="${DEFAULT_GHCR_USERNAME:-andrey271192}"
|
||||||
|
|
||||||
|
need_cmd docker
|
||||||
|
|
||||||
|
if ! docker info >/dev/null 2>&1; then
|
||||||
|
echo "Docker daemon недоступен. Запустите Docker и повторите."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
trim() {
|
trim() {
|
||||||
local v="$1"
|
local v="$1"
|
||||||
v="${v//$'\r'/}"
|
v="${v//$'\r'/}"
|
||||||
@@ -31,15 +55,6 @@ trim() {
|
|||||||
printf '%s' "$v"
|
printf '%s' "$v"
|
||||||
}
|
}
|
||||||
|
|
||||||
need_root
|
|
||||||
need_cmd curl
|
|
||||||
need_cmd docker
|
|
||||||
|
|
||||||
if ! docker info >/dev/null 2>&1; then
|
|
||||||
echo "Docker daemon недоступен. Запустите Docker и повторите."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! docker compose version >/dev/null 2>&1; then
|
if ! docker compose version >/dev/null 2>&1; then
|
||||||
_lib="$(mktemp)"
|
_lib="$(mktemp)"
|
||||||
if ! curl -fsSL "${RAW_BASE}/scripts/lib-compose-v2.sh" -o "${_lib}"; then
|
if ! curl -fsSL "${RAW_BASE}/scripts/lib-compose-v2.sh" -o "${_lib}"; then
|
||||||
@@ -53,8 +68,6 @@ if ! docker compose version >/dev/null 2>&1; then
|
|||||||
ensure_compose_v2 || exit 1
|
ensure_compose_v2 || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Снимаем FREE-панель (amnezia_web / install.sh): контейнеры + локальный образ + каталог сборки.
|
|
||||||
# VPN/AWG контейнеры (amnezia-awg, amnezia-awg2 и т.д.) не останавливаем.
|
|
||||||
remove_free_amnezia_web_panel() {
|
remove_free_amnezia_web_panel() {
|
||||||
if [[ "${SKIP_REMOVE_FREE:-}" == "1" ]]; then
|
if [[ "${SKIP_REMOVE_FREE:-}" == "1" ]]; then
|
||||||
echo "→ SKIP_REMOVE_FREE=1 — FREE-панель не удаляю."
|
echo "→ SKIP_REMOVE_FREE=1 — FREE-панель не удаляю."
|
||||||
@@ -93,17 +106,12 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
# При «curl … | sudo bash» stdin — это поток скрипта, а не клавиатура.
|
echo "Введите ключ доступа к образу (GitHub PAT с правом read:packages)."
|
||||||
# Читаем ключ с настоящего терминала; иначе read получает EOF и ломает .env.
|
echo "Ввод скрыт — символы не отображаются."
|
||||||
if [[ -r /dev/tty ]]; then
|
if [[ -r /dev/tty ]]; then
|
||||||
echo "Введите ключ доступа к образу (GitHub PAT с правом read:packages)."
|
|
||||||
echo "Ввод скрыт — символы не отображаются."
|
|
||||||
IFS= read -rs GHCR_KEY < /dev/tty || true
|
IFS= read -rs GHCR_KEY < /dev/tty || true
|
||||||
else
|
else
|
||||||
echo "Нет доступа к /dev/tty (интерактивный ввод недоступен)."
|
echo "Нет доступа к /dev/tty. Скачайте скрипт и запустите файлом."
|
||||||
echo "Скачайте скрипт и запустите файлом:"
|
|
||||||
echo " curl -fsSL ${RAW_BASE}/quick-install.sh -o /tmp/amnezia-quick-install.sh"
|
|
||||||
echo " sudo bash /tmp/amnezia-quick-install.sh"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
@@ -114,7 +122,6 @@ if [[ -z "${GHCR_KEY}" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Порт панели на хосте (8080 часто занят старой установкой amnezia-admin и т.п.)
|
|
||||||
tcp_port_in_use() {
|
tcp_port_in_use() {
|
||||||
local port="$1"
|
local port="$1"
|
||||||
command -v ss >/dev/null 2>&1 || return 1
|
command -v ss >/dev/null 2>&1 || return 1
|
||||||
@@ -122,7 +129,6 @@ tcp_port_in_use() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pick_host_port() {
|
pick_host_port() {
|
||||||
# Явный HOST_PORT=… (часто с sudo -E) — не переопределяем.
|
|
||||||
if [[ -n "${HOST_PORT:-}" ]]; then
|
if [[ -n "${HOST_PORT:-}" ]]; then
|
||||||
printf '%s' "${HOST_PORT}"
|
printf '%s' "${HOST_PORT}"
|
||||||
return
|
return
|
||||||
@@ -132,31 +138,18 @@ pick_host_port() {
|
|||||||
printf '%s' "${want}"
|
printf '%s' "${want}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "⚠ Порт ${want} уже занят на этом сервере (часто это старая панель или другой контейнер)." >&2
|
|
||||||
local alt="8081"
|
local alt="8081"
|
||||||
if [[ -r /dev/tty ]]; then
|
echo "⚠ Порт ${want} занят. Введите свободный порт [${alt}]:" >&2
|
||||||
echo "Введите свободный порт для веб-панели [${alt}]:" >&2
|
IFS= read -r line < /dev/tty || true
|
||||||
|
line="$(trim "${line}")"
|
||||||
|
[[ -z "${line}" ]] && line="${alt}"
|
||||||
|
while tcp_port_in_use "${line}"; do
|
||||||
|
echo "⚠ Порт ${line} тоже занят. Укажите другой:" >&2
|
||||||
IFS= read -r line < /dev/tty || true
|
IFS= read -r line < /dev/tty || true
|
||||||
line="$(trim "${line}")"
|
line="$(trim "${line}")"
|
||||||
[[ -z "${line}" ]] && line="${alt}"
|
[[ -z "${line}" ]] && exit 1
|
||||||
while tcp_port_in_use "${line}"; do
|
done
|
||||||
echo "⚠ Порт ${line} тоже занят. Укажите другой:" >&2
|
printf '%s' "${line}"
|
||||||
IFS= read -r line < /dev/tty || true
|
|
||||||
line="$(trim "${line}")"
|
|
||||||
[[ -z "${line}" ]] && {
|
|
||||||
echo "Порт не указан — выход." >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
done
|
|
||||||
printf '%s' "${line}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
echo "Нет /dev/tty — пробую ${alt}. При необходимости задайте HOST_PORT=… и повторите запуск." >&2
|
|
||||||
if tcp_port_in_use "${alt}"; then
|
|
||||||
echo "И ${alt} занят. Задайте явно: HOST_PORT=9080 curl … | sudo -E bash" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
printf '%s' "${alt}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pick_awg_container_name() {
|
pick_awg_container_name() {
|
||||||
@@ -179,7 +172,6 @@ SELECTED_HOST_PORT="$(pick_host_port)"
|
|||||||
SELECTED_AWG="$(pick_awg_container_name)"
|
SELECTED_AWG="$(pick_awg_container_name)"
|
||||||
|
|
||||||
umask 077
|
umask 077
|
||||||
# %q экранирует $ и прочее — безопасно для «source .env» в install.sh
|
|
||||||
{
|
{
|
||||||
printf 'GHCR_IMAGE=%q\n' "${DEFAULT_GHCR_IMAGE}"
|
printf 'GHCR_IMAGE=%q\n' "${DEFAULT_GHCR_IMAGE}"
|
||||||
printf 'IMAGE_TAG=%q\n' "${IMAGE_TAG}"
|
printf 'IMAGE_TAG=%q\n' "${IMAGE_TAG}"
|
||||||
@@ -188,6 +180,9 @@ umask 077
|
|||||||
printf 'HOST_PORT=%q\n' "${SELECTED_HOST_PORT}"
|
printf 'HOST_PORT=%q\n' "${SELECTED_HOST_PORT}"
|
||||||
printf 'CONTAINER_NAME=%q\n' "${CONTAINER_NAME:-amnezia-admin-pro}"
|
printf 'CONTAINER_NAME=%q\n' "${CONTAINER_NAME:-amnezia-admin-pro}"
|
||||||
printf 'AWG_CONTAINER=%q\n' "${SELECTED_AWG}"
|
printf 'AWG_CONTAINER=%q\n' "${SELECTED_AWG}"
|
||||||
|
if [[ -n "${ADMIN_PASSWORD:-}" ]]; then
|
||||||
|
printf 'ADMIN_PASSWORD=%q\n' "${ADMIN_PASSWORD}"
|
||||||
|
fi
|
||||||
} >"${INSTALL_ROOT}/.env"
|
} >"${INSTALL_ROOT}/.env"
|
||||||
|
|
||||||
echo "→ Запуск установки из ${INSTALL_ROOT}"
|
echo "→ Запуск установки из ${INSTALL_ROOT}"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Установка Pro с приватного GHCR (без исходников). Публичный репозиторий — только этот скрипт и compose.
|
# Legacy GHCR installer. Default public install now goes through quick-install.sh
|
||||||
|
# -> amnezia_web-PRO_test/install.sh to avoid GHCR 403 for users without package access.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
@@ -31,6 +32,16 @@ need_docker
|
|||||||
ensure_compose_v2 || exit 1
|
ensure_compose_v2 || exit 1
|
||||||
COMPOSE=(docker compose)
|
COMPOSE=(docker compose)
|
||||||
|
|
||||||
|
if [[ "${USE_GHCR:-0}" != "1" ]]; then
|
||||||
|
echo "Этот сценарий использует private GHCR image и может дать 403 Forbidden."
|
||||||
|
echo "Для обычной установки используйте:"
|
||||||
|
echo " curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia-web-pro-deploy/main/quick-install.sh | sudo bash"
|
||||||
|
echo ""
|
||||||
|
echo "Если точно нужен старый GHCR-режим, запустите:"
|
||||||
|
echo " USE_GHCR=1 sudo -E bash scripts/install.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -f "${ENV_FILE}" ]]; then
|
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||||
echo "Создайте файл .env из .env.example и вставьте GHCR_* из закрытого поста Boosty:"
|
echo "Создайте файл .env из .env.example и вставьте GHCR_* из закрытого поста Boosty:"
|
||||||
echo " cp .env.example .env && nano .env"
|
echo " cp .env.example .env && nano .env"
|
||||||
@@ -54,6 +65,7 @@ GHCR_IMAGE="$(trim_crlf "${GHCR_IMAGE:-}")"
|
|||||||
IMAGE_TAG="$(trim_crlf "${IMAGE_TAG:-}")"
|
IMAGE_TAG="$(trim_crlf "${IMAGE_TAG:-}")"
|
||||||
GHCR_USERNAME="$(trim_crlf "${GHCR_USERNAME:-}")"
|
GHCR_USERNAME="$(trim_crlf "${GHCR_USERNAME:-}")"
|
||||||
GHCR_TOKEN="$(trim_crlf "${GHCR_TOKEN:-}")"
|
GHCR_TOKEN="$(trim_crlf "${GHCR_TOKEN:-}")"
|
||||||
|
ADMIN_PASSWORD="$(trim_crlf "${ADMIN_PASSWORD:-}")"
|
||||||
|
|
||||||
: "${GHCR_IMAGE:?Укажите GHCR_IMAGE в .env}"
|
: "${GHCR_IMAGE:?Укажите GHCR_IMAGE в .env}"
|
||||||
: "${IMAGE_TAG:?Укажите IMAGE_TAG в .env}"
|
: "${IMAGE_TAG:?Укажите IMAGE_TAG в .env}"
|
||||||
@@ -66,8 +78,26 @@ printf '%s\n' "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --pas
|
|||||||
echo "→ pull ${GHCR_IMAGE}:${IMAGE_TAG}"
|
echo "→ pull ${GHCR_IMAGE}:${IMAGE_TAG}"
|
||||||
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" pull
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" pull
|
||||||
|
|
||||||
|
RESET_PANEL_PASSWORD=0
|
||||||
|
if [[ -n "${ADMIN_PASSWORD}" ]]; then
|
||||||
|
echo "→ ADMIN_PASSWORD задан — сбрасываю старый пароль панели в volume."
|
||||||
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" run --rm --no-deps --entrypoint sh panel -lc '
|
||||||
|
set -eu
|
||||||
|
if [ -f /data/password.hash ]; then
|
||||||
|
cp -p /data/password.hash "/data/password.hash.bak.$(date -u +%Y%m%dT%H%M%SZ)" 2>/dev/null || true
|
||||||
|
rm -f /data/password.hash
|
||||||
|
rm -f /data/session.secret
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
RESET_PANEL_PASSWORD=1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "→ up -d"
|
echo "→ up -d"
|
||||||
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" up -d
|
UP_ARGS=(up -d)
|
||||||
|
if [[ "${RESET_PANEL_PASSWORD}" == "1" ]]; then
|
||||||
|
UP_ARGS+=(--force-recreate)
|
||||||
|
fi
|
||||||
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" "${UP_ARGS[@]}"
|
||||||
|
|
||||||
IP="$(hostname -I 2>/dev/null | awk '{print $1}' || true)"
|
IP="$(hostname -I 2>/dev/null | awk '{print $1}' || true)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -14,6 +14,19 @@ fi
|
|||||||
ensure_compose_v2 || exit 1
|
ensure_compose_v2 || exit 1
|
||||||
COMPOSE=(docker compose)
|
COMPOSE=(docker compose)
|
||||||
|
|
||||||
|
if [[ "${USE_GHCR:-0}" != "1" ]]; then
|
||||||
|
echo "Этот update.sh относится к legacy GHCR-режиму и может дать 403 Forbidden."
|
||||||
|
echo "Для source-установки обновляйтесь из панели или вручную:"
|
||||||
|
echo " cd /opt/amnezia-web-pro"
|
||||||
|
echo " git pull"
|
||||||
|
echo " docker compose build"
|
||||||
|
echo " docker compose up -d"
|
||||||
|
echo ""
|
||||||
|
echo "Если точно нужен старый GHCR-режим, запустите:"
|
||||||
|
echo " USE_GHCR=1 sudo -E bash scripts/update.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
set -a
|
set -a
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "${ENV_FILE}"
|
source "${ENV_FILE}"
|
||||||
@@ -28,9 +41,29 @@ trim_crlf() {
|
|||||||
}
|
}
|
||||||
GHCR_USERNAME="$(trim_crlf "${GHCR_USERNAME:-}")"
|
GHCR_USERNAME="$(trim_crlf "${GHCR_USERNAME:-}")"
|
||||||
GHCR_TOKEN="$(trim_crlf "${GHCR_TOKEN:-}")"
|
GHCR_TOKEN="$(trim_crlf "${GHCR_TOKEN:-}")"
|
||||||
|
ADMIN_PASSWORD="$(trim_crlf "${ADMIN_PASSWORD:-}")"
|
||||||
|
|
||||||
printf '%s\n' "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
|
printf '%s\n' "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
|
||||||
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" pull
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" pull
|
||||||
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" up -d
|
|
||||||
|
RESET_PANEL_PASSWORD=0
|
||||||
|
if [[ -n "${ADMIN_PASSWORD}" ]]; then
|
||||||
|
echo "→ ADMIN_PASSWORD задан — сбрасываю старый пароль панели в volume."
|
||||||
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" run --rm --no-deps --entrypoint sh panel -lc '
|
||||||
|
set -eu
|
||||||
|
if [ -f /data/password.hash ]; then
|
||||||
|
cp -p /data/password.hash "/data/password.hash.bak.$(date -u +%Y%m%dT%H%M%SZ)" 2>/dev/null || true
|
||||||
|
rm -f /data/password.hash
|
||||||
|
rm -f /data/session.secret
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
RESET_PANEL_PASSWORD=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
UP_ARGS=(up -d)
|
||||||
|
if [[ "${RESET_PANEL_PASSWORD}" == "1" ]]; then
|
||||||
|
UP_ARGS+=(--force-recreate)
|
||||||
|
fi
|
||||||
|
"${COMPOSE[@]}" -f "${COMPOSE_FILE}" --env-file "${ENV_FILE}" "${UP_ARGS[@]}"
|
||||||
|
|
||||||
echo "Обновлено."
|
echo "Обновлено."
|
||||||
|
|||||||
Reference in New Issue
Block a user