6 Commits

Author SHA1 Message Date
Бобырев Андрей
b64d1aba5b v1.4.2: move to git.bobyrev.com (GitHub account suspended), README photo + install command
Some checks failed
Publish Pro image to GHCR / build-push (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 04:39:35 +03:00
Бобырев Андрей
cb230fe50e docs: split old Notes into 09.3.N, fix 00 (news bot), move check scripts to scripts/checks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:44:20 +03:00
Бобырев Андрей
dbab96f7fd docs: 09.2 — install.sh checked on clean Ubuntu 24.04 LXC
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:36:48 +03:00
Бобырев Андрей
d34f25d544 docs: 09.2 v1.4.1, news, gitea
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:25:57 +03:00
Бобырев Андрей
1be56c1f60 v1.4.1: installer installs Docker, step-by-step quick start, drop confusing AWG_PROFILES hint
Some checks failed
Publish Pro image to GHCR / build-push (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:20:11 +03:00
Бобырев Андрей
a843f300a7 docs: 00, 09.2 v1.4.0, archive closed panel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:09:32 +03:00
31 changed files with 642 additions and 40 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ npm-debug.log*
*.swp
.env
.env.*
Новости/

View File

@@ -0,0 +1,10 @@
# 00. НАЧНИ ОТСЮДА — amnezia_web-PRO
**Промпт для нового чата:**
> Проект «Открытые проекты/amnezia_web-PRO» — полностью открытая веб-панель Amnezia (Node, `server.js` + `public/`). Закрытой версии нет (старая — в `Архив/amnezia_web-PRO_test`). Прочитай `PROJECT_INDEX.md` и `09. История и грабли`. Тесты — на school-friends (сервер) и school-it-kruzhok (клиент) через svault. Релиз: тег + GitHub API, затем Gitea, Notes, новость в группу PCA, тема «Новости» (chat_id -1003902709196, message_thread_id=131) ботом @PCAdmin27_bot (токен `TELEGRAM_MOD_BOT_TOKEN` в «Закрытые продукты/home_Friends_It/ДОСТУПЫ.md»); PCA_jarvis_bot не использовать. Gitea — pull-зеркало, обновлять mirror-sync.
## Оглавление
- `PROJECT_INDEX.md` — что где лежит, установка
- `09. История и грабли` — оглавление записей 09.N
- `scripts/checks/` — проверки парка AWG (запускать внутри контейнера панели, читают /app/data/data.json)
- `Новости/` — тексты новостей релизов (не в git)

View File

@@ -1,4 +1,6 @@
# 09. История и грабли
- [09.1 Версия 1.3.0 — протоколы с сайта, каскад, домен, тема](<09.1 Версия 1.3.0 — протоколы с сайта, каскад, домен, тема.md>) — 23.10.2026
- [09.2 Версия 1.4.0 — Xray VLESS, всё открыто](<09.2 Версия 1.4.0 — Xray VLESS, всё открыто.md>) — 23.10.2026
- [09.3 Старые исправления июня 2026](<09.3 Старые исправления июня 2026.md>) — 13 частей 09.3.N, перенесены из Notes 23.10.2026
- 04.10.2026 — проект переехал в папку-группу; код не менялся.

View File

@@ -0,0 +1,33 @@
# 09.2 Версия 1.4.0 — Xray VLESS-Reality, всё открыто (23.10.2026)
**Задача.** Перенести Xray/VLESS из закрытой панели, закрытую версию не развивать, убрать всё «платное».
**Сделано.**
- Убрана редакция community («только просмотр», баннер «купите PRO», `requireProTier`, `AMNEZIA_EDITION`, `COMMUNITY_UPGRADE_*`). Все функции открыты.
- Xray VLESS-Reality в `server.js` (блок «Xray VLESS-Reality») и раздел на странице: установка (TCP-порт, сайт-маскировка), клиенты создать/выкл/вкл/удалить, ссылка `vless://`.
Образ собирается на сервере (alpine + Xray v26.3.27), контейнер `amnezia-xray`, файлы `/opt/amnezia/xray` в формате приложения Amnezia (`xray_*.key`, `clientsTable`). Выключенный клиент — убран из `server.json`, помечен `disabled` в `clientsTable`.
- Закрытая панель `amnezia_web-PRO_test` перенесена в `Архив/` (SSD и Notes), там файл «АРХИВ — почему».
**Проверено** на school-friends (сервер) + school-it-kruzhok (клиент xray-core): соединение есть (HTTP 200 через socks), выключение клиента рвёт связь, включение возвращает. Тестовое удалено.
## Грабли
- **СИМПТОМ:** установка Xray «Не удалось получить ключи x25519». **ПРИЧИНА:** новый Xray пишет `Password (PublicKey): …` вместо `Public key:`. **ИСПРАВЛЕНИЕ:** регэксп `(?:Public\s*key|Password)[^:\n]*:`. **ПРОВЕРИТЬ:** `docker run --rm --entrypoint /usr/bin/xray amnezia-xray x25519`.
- **СИМПТОМ:** форма установки видна при установленном Xray. **ПРИЧИНА:** CSS `.instance-form` перебивает атрибут `hidden`. **ИСПРАВЛЕНИЕ:** `style.display`.
- Оба школьных сервера выходят в интернет через один NAT — проверка «по IP» не отличает туннель; проверять выключением клиента.
## 1.4.1 (23.10.2026)
- Установщик сам ставит Docker (`get.docker.com`) на чистом сервере. На машине без Docker не проверялось — школьные все с Docker.
- README: раздел «Быстрый старт» — 7 шагов от пустого VPS (порты, вход admin, протокол, клиент, Xray, домен, «если не работает»).
- Убрана подсказка «задайте AWG_PROFILES» — сбивала новичков.
- Проверено как у человека с GitHub: чистая установка `curl … | sudo bash` → вход admin → AWG 2.0 + клиент (рукопожатие, интернет) → Xray + клиент → обновление поверх (версия 1.4.1, клиенты на месте). Тестовое удалено.
## Проверка установщика на чистом сервере (23.10.2026)
- LXC 199 на Proxmox .5 (Ubuntu 24.04, unprivileged, nesting+keyctl), без Docker → `curl -fsSL …/scripts/install.sh | bash` → Docker поставился сам, контейнеры `amnezia-admin` и `amnezia-web-landing` поднялись, :8080 = 200, `/api/login` с паролем admin = ok. Ошибок нет, 1.4.2 не понадобилась. LXC удалён.
- Proxmox .5 и Gitea .153:3030 из сессии отвечают напрямую; в Gitea тег v1.4.1 есть.
## Публикация
- Новость 1.4.0 — @PCAdmin27_bot, тема «Новости» (131), сообщение 881. PCA_jarvis_bot из группы выгнан.
- Gitea — pull-зеркало: обновляется `mirror-sync` (push → 403). С мини .153 «недоступна» только из сессии Claude — ходить через `ssh andrey@127.0.0.1`.
## Осталось
- QR-кода для vless нет (ссылка копируется) — добавить, если попросят.

View File

@@ -0,0 +1,17 @@
# 09.3 Старые исправления июня 2026
Оглавление частей: заметки из Notes до регламента (июнь–июль 2026), по одной на исправление.
- [09.3.1 Canonical public amnezia_web-PRO 06.06](<09.3.1 Canonical public amnezia_web-PRO 06.06.md>)
- [09.3.2 Canonical amnezia_web-PRO status 21.06](<09.3.2 Canonical amnezia_web-PRO status 21.06.md>)
- [09.3.3 Fix AWG auto profiles 21.06](<09.3.3 Fix AWG auto profiles 21.06.md>)
- [09.3.4 Fix stale AWG profile snapshot 21.06](<09.3.4 Fix stale AWG profile snapshot 21.06.md>)
- [09.3.5 Client import from Amnezia backup 21.06](<09.3.5 Client import from Amnezia backup 21.06.md>)
- [09.3.6 Fix duplicate AWG instances 21.06](<09.3.6 Fix duplicate AWG instances 21.06.md>)
- [09.3.7 Fix AWG instance labels 21.06](<09.3.7 Fix AWG instance labels 21.06.md>)
- [09.3.8 Fix clients selected profile 21.06](<09.3.8 Fix clients selected profile 21.06.md>)
- [09.3.9 Fix peers missing clientsTable 21.06](<09.3.9 Fix peers missing clientsTable 21.06.md>)
- [09.3.10 Sync app-created Amnezia users 21.06](<09.3.10 Sync app-created Amnezia users 21.06.md>)
- [09.3.11 Fix legacy clientsTable formats 21.06](<09.3.11 Fix legacy clientsTable formats 21.06.md>)
- [09.3.12 Fix Amnezia source auto-discovery 22.06](<09.3.12 Fix Amnezia source auto-discovery 22.06.md>)
- [09.3.13 Fix awg binary not found 22.06](<09.3.13 Fix awg binary not found 22.06.md>)

View File

@@ -0,0 +1,17 @@
# 09.3.1 Canonical public amnezia_web-PRO 06.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
amnezia_web-PRO canonical public repo — 06.06
Keep one public project: https://github.com/andrey271192/amnezia_web-PRO
Install
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
Defaults
Fresh login: admin
Fresh password: admin
Change password after first login.
GitHub
Repo is public.
Private download flow removed.
Separate deploy bundle removed from active docs and notes.
Commit: 05e6d00 docs: make pro repo public install source.

View File

@@ -0,0 +1,23 @@
# 09.3.10 Sync app-created Amnezia users 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: dfeabe0 feat: sync app-created peers into clients table
Version: v1.2.36
Задача
Клиенты уже были созданы в приложении Amnezia. Их нужно подтянуть в веб-панель, а не создавать заново.
Решение
Добавлена кнопка Пользователи → Подтянуть из awg0.conf.
POST /api/clients/sync-peers берёт активные [Peer] текущего инстанса и создаёт недостающие строки clientsTable.
VPN-конфиг не пересоздаётся, контейнеры клиентов не трогаются.
Имена создаются как Клиент IP или Peer KEY, потом можно переименовать.
Экспорт .conf появится после импорта клиентского .conf, потому приватный ключ клиента есть только в приложении.
Команда
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Потом Ctrl+F5 → выбрать Инстанс → Пользователи → Подтянуть из awg0.conf.
Проверено
node --check server.js
node --check public/app.js
bash -n scripts/*.sh
npm audit --audit-level=moderate: 0 vulnerabilities
git diff --check

View File

@@ -0,0 +1,17 @@
# 09.3.11 Fix legacy clientsTable formats 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: 4e6ab2d fix: parse legacy clients table formats
Version: v1.2.37
Причина
Старые клиенты могли не подтягиваться, если clientsTable не был массивом [{clientId,userData}], а имел object/map/nested формат другой версии Amnezia.
Исправлено
parseClientsTable поддерживает array, object map, nested clients/users/rows/items/data/clientList/clientsTable.
clientRowId понимает clientId/id/publicKey/public_key/key/client_id и вложенные userData поля.
Добавлен GET /api/clients/source-report для диагностики источников без полных ключей.
Команда
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Потом Ctrl+F5 → выбрать Инстанс → Пользователи → Подтянуть из awg0.conf.
Если всё равно пусто
Открыть в браузере после логина: /api/clients/source-report?profileId=awg и /api/clients/source-report?profileId=awg2

View File

@@ -0,0 +1,20 @@
# 09.3.12 Fix Amnezia source auto-discovery 22.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: b360095 fix: auto-discover amnezia client sources
Version: v1.2.38
Root cause
Amnezia installs can keep old clients in /opt/amnezia/awg/wg0.conf, while profile pointed to /opt/amnezia/awg/awg0.conf. clientsTable can also live in /opt/amnezia/wireguard/clientsTable or have non-array format.
Fix
Runtime now scans config candidates: awg0.conf, wg0.conf, wireguard/wg0.conf.
Chooses config with max [Peer] count.
Runtime scans clientsTable candidates: awg/clientsTable and wireguard/clientsTable.
Chooses clientsTable with max parsed client count.
iface is inferred from selected config filename.
source-report shows resolved confPath/clientsPath/iface.
Command
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Then Ctrl+F5 → select Instance → Users → Pull from awg0.conf.
Source
Amnezia issue #1615 mentions manual flow with /opt/amnezia/awg/wg0.conf and clientsTable; issue #2238 confirms clientsTable field variance.

View File

@@ -0,0 +1,15 @@
# 09.3.13 Fix awg binary not found 22.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: 8e5d51a fix: auto-detect wg binary in containers
Version: v1.2.39
Symptom
При добавлении/подтягивании старых .conf ошибка: sh: awg: not found. В amneziawg контейнере awg binary отсутствует.
Fix
Runtime auto-detects binary inside container: preferred wgBinary, then wg for wg0.conf, then awg, then wg.
show/pubkey/genkey/syncconf use resolved binary, not hardcoded profile.wgBinary.
source-report and /api/clients expose resolved wgBinary.
Command
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Then Ctrl+F5 → Instance → Users → Pull from awg0.conf.

View File

@@ -0,0 +1,20 @@
# 09.3.2 Canonical amnezia_web-PRO status 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Важно: amnezia_web-PRO_test — отдельный продукт/тестовая ветка. Canonical public product сейчас: amnezia_web-PRO.
GitHub: https://github.com/andrey271192/amnezia_web-PRO
Local: /Users/andrejbobyrev/andrey271192-repos/amnezia_web-PRO
Last pushed commit: c202f0b — chore: add npm lockfile
Правило
amnezia_web-PRO — основной публичный продукт.
amnezia_web-PRO_test — отдельный тестовый продукт, не смешивать с public PRO.
amnezia-web-pro-deploy — legacy/старый deploy repo, не использовать как основной продукт.
Install
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
Defaults
Fresh login: admin
Fresh password: admin
Change password after first login.
AWG issue from client
Install-check видит два контейнера: amnezia-awg2 и amnezia-awg. Если веб показывает только awg2, причина в runtime-discovery/cache/UI-filter, не в Docker. Надо проверить конкретный VPS: docker ps, panel API/status, logs, затем исправить отображение обоих AWG profiles без ручного AWG_PROFILES.

View File

@@ -0,0 +1,22 @@
# 09.3.3 Fix AWG auto profiles 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Repo: https://github.com/andrey271192/amnezia_web-PRO
Commit: cbc20a1 — fix: auto-detect awg profiles on install
Что исправлено
Переустановка из GitHub работает для /opt/amnezia-admin без .git.
Установщик сохраняет текущий порт панели.
Установщик сохраняет текущий Docker volume /data.
Перед заменой /opt/amnezia-admin создаётся backup папки.
Если найден один контейнер amnezia-awg*, он становится AWG_CONTAINER.
Если найдено 2+ контейнера amnezia-awg*, AWG_PROFILES создаётся автоматически и сохраняется в /root/amnezia-admin.awg-profiles.json.
Dockerfile использует npm ci по package-lock.json.
Что сказать пользователю
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash
После установки: обновить страницу Ctrl+F5. AWG контейнеры не удаляются и не пересоздаются.
Проверено
bash -n scripts/install.sh
bash -n scripts/uninstall.sh
node --check server.js
npm audit --audit-level=moderate

View File

@@ -0,0 +1,9 @@
# 09.3.4 Fix stale AWG profile snapshot 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: 8ba2a26 — fix: refresh stale awg profile snapshots
Причина повтора бага: старый /root/amnezia-admin.awg-profiles.json мог содержать один профиль. Installer восстанавливал его и не пересобирал profiles по двум контейнерам.
Теперь если контейнеров amnezia-awg* два или больше, а восстановленный AWG_PROFILES содержит меньше двух container, installer автоматически пересобирает profiles и перезаписывает snapshot.
rm -f /root/amnezia-admin.awg-profiles.json
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s) | sudo env SKIP_LANDING=1 bash

View File

@@ -0,0 +1,24 @@
# 09.3.5 Client import from Amnezia backup 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Project: amnezia_web-PRO
Repo: https://github.com/andrey271192/amnezia_web-PRO
Commit: cff27e2 feat: import clients from amnezia configs
Что добавлено
В панели появился блок Импорт клиента.
Можно вставить готовый клиентский .conf или JSON backup Amnezia, если внутри есть текстовый .conf.
Если peer уже есть в awg0.conf, дубль не создаётся: восстанавливается/обновляется строка clientsTable.
Если peer отсутствует, он добавляется в текущий выбранный Инстанс.
Исходный .conf сохраняется в userData.last_config, чтобы дальше работали экспорт и управление из веба.
Добавлена защита: импортируемый .conf должен относиться к текущему серверу/инстансу по PublicKey сервера.
Команда переустановки для пользователя
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Проверено
node --check server.js
node --check public/app.js
bash -n для всех scripts/*.sh
npm audit --audit-level=moderate: 0 vulnerabilities
git diff --check
Что сказать пользователю
Обновите панель командой выше, зайдите в веб, выберите нужный Инстанс и откройте блок Импорт клиента. Вставьте экспортированный клиентский .conf из приложения Amnezia или backup, где внутри есть этот .conf. После импорта клиент появится в таблице, а старые peer-дубли создаваться не будут.

View File

@@ -0,0 +1,22 @@
# 09.3.6 Fix duplicate AWG instances 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Project: amnezia_web-PRO
Commit: 8c67d7d fix: dedupe duplicate awg instances
Version: v1.2.32
Причина
После переустановки один и тот же AWG контейнер мог попасть в список дважды: из AWG_PROFILES и из saved managed instances. Старый dedup был только по id, поэтому при разных id веб показывал две одинаковые карточки.
Исправлено
Dedup профилей по container + confPath + iface + clientsPath.
/api/instances дополнительно дедупит runtime target после auto-resolve контейнера.
load/save managed profiles чистит дубли из instances.json.
Docs обновлены: раздел Инстансы задублировались.
Команда для пользователя
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
После установки: Ctrl+F5 в браузере.
Проверено
node --check server.js
node --check public/app.js
npm audit --audit-level=moderate: 0 vulnerabilities
git diff --check

View File

@@ -0,0 +1,15 @@
# 09.3.7 Fix AWG instance labels 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: a9a67af fix: show distinct awg instance labels
Version: v1.2.33
Причина
У пользователя реально два контейнера: amnezia-awg2 и amnezia-awg. Порты и число клиентов разные, значит это не дубль. Но UI рисовал title по variant, поэтому обе карточки выглядели как AmneziaWG 2.0.
Исправлено
Карточка инстанса показывает profile label, а не только variant title.
Backend лучше определяет variant по profile/container/label до чтения конфига.
Docs уточнены: два разных контейнера с разными портами — нормальные два инстанса.
Команда
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Потом Ctrl+F5.

View File

@@ -0,0 +1,18 @@
# 09.3.8 Fix clients selected profile 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: cb5fca3 fix: load clients for selected profile
Version: v1.2.34
Симптом
Переключатель Инстанс показывает правильный контейнер, но таблица Пользователи показывает клиентов от другого/старого инстанса.
Причина
Создание/экспорт уже передавали profileId явно, но /api/clients и операции таблицы опирались на cookie выбранного профиля. Cookie мог не примениться/устареть, поэтому список клиентов приходил не от выбранного инстанса.
Исправлено
GET /api/clients принимает явный profileId.
disable/enable/rename/delete/disconnect-date используют runtimeFromExportRequest и body.profileId.
Frontend передаёт profileId во все запросы таблицы клиентов.
Docs обновлены.
Команда
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Потом Ctrl+F5.

View File

@@ -0,0 +1,18 @@
# 09.3.9 Fix peers missing clientsTable 21.06
_Старая заметка из Notes (июнь 2026), перенесена 23.10.2026. Оригинал: Архив/Старые заметки Notes 20261023._
Commit: fd66b0a fix: show peers missing clients table
Version: v1.2.35
Симптом
Инстанс выбран правильно, но старые клиенты не появляются в таблице Пользователи.
Причина
UI строил список только из clientsTable. У старых/созданных приложением клиентов peer может быть в awg0.conf, а запись clientsTable отсутствовать или иметь другой формат.
Исправлено
GET /api/clients теперь возвращает union clientsTable + Peer из awg0.conf.
Peer-only строки показываются как Peer xxxx… и помечаются missingClientTable.
Rename/date/disable/delete умеют работать с peer-only строками.
Для экспорта .conf всё равно нужен импорт клиентского .conf, потому приватный ключ клиента сервер не знает.
Команда
curl -fsSL "https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh?nocache=$(date +%s)" | sudo env SKIP_LANDING=1 bash
Потом Ctrl+F5.

View File

@@ -9,9 +9,9 @@
|---|---|
| Папка проекта | `/Volumes/ssd/Мои проекты/Открытые проекты/amnezia_web-PRO/` |
| Заметки | Apple Notes → `МОИ ПРОЕКТЫ` → папка `amnezia_web-PRO` |
| GitHub (публичный) | https://github.com/andrey271192/amnezia_web-PRO |
| GitHub (публичный) | https://git.bobyrev.com/PCA/amnezia_web-PRO |
| Ветка прода | `main` |
| Тестовая копия рядом | `/Volumes/ssd/Мои проекты/Закрытые продукты/amnezia_web-PRO_test/` |
| Старая закрытая панель (архив, не развивается) | `/Volumes/ssd/Мои проекты/Архив/amnezia_web-PRO_test/` |
Путь `/Volumes/andrey/Мои проекты/...` из старого промпта синхронизации **не существует** —
актуальная копия только на `/Volumes/ssd`.
@@ -39,7 +39,7 @@
## Установка
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
Первый вход: `admin` / `admin`, пароль сменить сразу.

View File

@@ -2,9 +2,26 @@
Полностью открытая веб-панель для сервера Amnezia: все функции бесплатны, без платных или закрытых редакций. Один репозиторий, один установщик.
<img src="docs/screenshots/panel-1.4.png" alt="Панель amnezia_web-PRO 1.4: пользователи AmneziaWG, Xray VLESS-Reality, протоколы и инстансы" width="780"/>
**Что умеет:** клиенты AmneziaWG (создать, выключить, дата отключения, .conf), установка протоколов из браузера (AmneziaWG 1.x/2.0/3.0/3.1, WireGuard), Xray VLESS‑Reality, Cloudflare WARP и каскад через другой сервер, Telegram MTProto‑прокси, домен сервера в конфигах, светлая/тёмная тема.
**Установка** (Ubuntu 22.04/24.04, Debian 12, под root; Docker поставится сам):
```bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
Панель: `http://IP:8080`, вход — пароль `admin` (смените сразу). Код — [git.bobyrev.com/PCA/amnezia_web-PRO](https://git.bobyrev.com/PCA/amnezia_web-PRO) (GitHub-аккаунт заблокирован, старые ссылки raw.githubusercontent.com больше не работают).
## Что нового в 1.4.2
- **Проект переехал на [git.bobyrev.com/PCA/amnezia_web-PRO](https://git.bobyrev.com/PCA/amnezia_web-PRO)** — GitHub-аккаунт заблокирован. Установщик и обновление качают код оттуда. Старая команда с `raw.githubusercontent.com` больше не работает — используйте новую (выше).
## Что нового в 1.4.0
- **Xray VLESS‑Reality** — раздел «Xray VLESS‑Reality»: установка с выбором TCP‑порта и сайта‑маскировки, клиенты (создать, выключить/включить, удалить), ссылка `vless://` для Amnezia VPN, v2rayNG, Hiddify, Streisand, Happ. Файлы в `/opt/amnezia/xray` в том же формате, что у приложения Amnezia.
- **Установщик сам ставит Docker** на чистом сервере.
- **Всё открыто:** убрана редакция «community / только просмотр» и переменные `AMNEZIA_EDITION`, `COMMUNITY_UPGRADE_*` — все функции доступны всем.
## Что нового в 1.3.0
@@ -25,6 +42,55 @@
- **Светлая / тёмная тема** — кнопка «◐ Тема» в шапке (по умолчанию как в системе).
- Старые установки не затрагиваются: контейнеры, поставленные приложением Amnezia, остаются как были.
## Быстрый старт: от пустого сервера до VPN за 10 минут
**Что нужно:** VPS с Ubuntu 22.04/24.04 или Debian 12 (1 ГБ ОЗУ хватает), доступ root по SSH. Docker ставить не нужно — установщик поставит его сам.
**1. Установите панель.** Зайдите на сервер по SSH и выполните:
```bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
В конце будет строка `Админ-панель: http://IP:8080`.
**2. Откройте порты** в фаерволе хостинга (панель управления VPS) и, если включён, в `ufw`:
| Порт | Зачем |
|---|---|
| `8080/tcp` | админ-панель |
| `80/tcp` | страница для пользователей (необязательно, `SKIP_LANDING=1` — без неё) |
| UDP-порт AmneziaWG, который выберете на шаге 4 (например `41010/udp`) | VPN AmneziaWG |
| TCP-порт Xray, если будете ставить (например `443/tcp`) | VPN Xray |
```bash
sudo ufw allow 8080/tcp && sudo ufw allow 41010/udp # пример, если ufw включён
```
**3. Войдите** на `http://IP:8080` — пароль **`admin`**. Сразу смените его в блоке «Сменить пароль».
**4. Разверните протокол.** Раздел «Протоколы / инстансы» → выберите вариант → порт (например `41010`) → «Развернуть инстанс». Какой выбрать:
- **AmneziaWG 2.0** — по умолчанию, для телефонов и ПК (приложение Amnezia VPN);
- **AmneziaWG 3.1 / 3.0** — самые новые, нужна свежая версия приложения;
- **AmneziaWG 1.x** — для роутеров Keenetic / OpenWrt;
- **WireGuard** — для любых WG-клиентов, без маскировки.
Если на сервере уже стоит VPN, поставленный приложением Amnezia, — шаг пропустите: панель найдёт его сама.
**5. Создайте клиента.** Блок «Новый клиент» → имя → «Создать и скачать .conf». Файл импортируйте в Amnezia VPN (на телефоне/ПК: «+» → «Файл с настройками»).
**6. (по желанию) Xray VLESS‑Reality** — если AmneziaWG у провайдера режут. Раздел «Xray VLESS‑Reality» → порт TCP (`443`, если свободен) и сайт‑маскировка → «Установить Xray» (~1 минута) → «Создать» клиента — ссылка `vless://` скопируется. Вставьте её в Amnezia VPN, v2rayNG, Hiddify, Streisand или Happ («+» → «Из буфера обмена»).
**7. Свой домен (по желанию).** В «Протоколы / инстансы» → «Домен или IP сервера в конфигах клиентов» → «Сохранить адрес». Без него в конфиги подставляется IP.
**Обновление** — та же команда из шага 1: клиенты, пароль и настройки сохраняются. **Удаление** — см. «Удаление одной командой».
**Если не работает:**
- «Рукопожатие есть, интернета нет» или нет рукопожатия — не открыт UDP-порт у хостинга (шаг 2).
- Панель не открывается — не открыт `8080/tcp`; проверка на сервере: `curl -s localhost:8080/health`.
- Xray: «TCP-порт занят» — выберите другой порт (например `8443`) и откройте его.
- Логи панели: `sudo docker logs --tail 50 amnezia-admin`.
## Что открывается по какому порту
| Адрес | Назначение |
@@ -51,7 +117,7 @@
### Public install from GitHub
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
Панель после установки открывается по **`http://IP:HOST_PORT`** (по умолчанию `:8080`). Первый вход: **логин `admin`, пароль `admin`**. Смените пароль сразу после входа.
@@ -61,13 +127,13 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/s
Если `/opt/amnezia-admin` не git-репозиторий, это нормально: установщик скачивает свежий архив с GitHub, делает backup старой папки, сохраняет текущий порт и текущий Docker volume `/data`, затем пересобирает только контейнер панели **`amnezia-admin`**. Контейнеры AmneziaWG (`amnezia-awg`, `amnezia-awg2` и т.д.) не удаляются и не пересоздаются.
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
Если не нужен лендинг на порту 80:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash
```
### Переменные окружения и `sudo`
@@ -79,7 +145,7 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/s
1. **`sudo -E bash`** вместо `sudo bash` (для большинства VPS достаточно):
```bash
AWG_PROFILES='[{"id":"awg",…}]' curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo -E bash
AWG_PROFILES='[{"id":"awg",…}]' curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo -E bash
```
2. **Файл на VPS** (способ без `-E`): записать JSON **одной строкой** в **`/root/amnezia-admin.awg-profiles.json`** (например `umask 077; printf '%s\n' '[{"id":"awg",…}]' > /root/amnezia-admin.awg-profiles.json`), затем обычный **`curl … | sudo bash`** — установщик подставит профили из файла (см. абзац про снимок ниже таблицы).
@@ -107,7 +173,7 @@ cd /opt/amnezia-admin && chmod +x scripts/install.sh && sudo SKIP_DOWNLOAD=1 bas
| Переменная | По умолчанию | Назначение |
|------------|--------------|------------|
| `GITHUB_REPO` | `andrey271192/amnezia_web-PRO` | Откуда качать архив |
| `GITHUB_REPO` | `PCA/amnezia_web-PRO` | Откуда качать архив |
| `BRANCH` | `main` | Ветка |
| `INSTALL_DIR` | `/opt/amnezia-admin` | Куда распаковать исходники |
| `DATA_DIR` | `/opt/amnezia-admin-data` | Том с `password.hash` и сессией |
@@ -155,14 +221,14 @@ cd /opt/amnezia-admin && chmod +x scripts/install.sh && sudo SKIP_DOWNLOAD=1 bas
```bash
AWG_PROFILES='[{"id":"awg","label":"AmneziaWG","container":"amnezia-awg","confPath":"/opt/amnezia/awg/awg0.conf","clientsPath":"/opt/amnezia/awg/clientsTable","iface":"awg0","wgBinary":"awg","pskPath":"/opt/amnezia/awg/wireguard_psk.key"},{"id":"legacy","label":"AmneziaWG Legacy","container":"amnezia-wg0","confPath":"/opt/amnezia/wireguard/wg0.conf","clientsPath":"/opt/amnezia/wireguard/clientsTable","iface":"wg0","wgBinary":"wg","pskPath":"/opt/amnezia/wireguard/wireguard_psk.key"}]' \
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo -E bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo -E bash
```
**Пример 2** — оба конфигурационных набора внутри контейнера **`amnezia-awg`** (файл `wg0.conf` рядом с `awg0.conf` в `/opt/amnezia/awg/`):
```bash
AWG_PROFILES='[{"id":"awg","label":"AmneziaWG","container":"amnezia-awg","confPath":"/opt/amnezia/awg/awg0.conf","clientsPath":"/opt/amnezia/awg/clientsTable","iface":"awg0","wgBinary":"awg","pskPath":"/opt/amnezia/awg/wireguard_psk.key"},{"id":"legacy","label":"AmneziaWG Legacy","container":"amnezia-awg","confPath":"/opt/amnezia/awg/wg0.conf","clientsPath":"/opt/amnezia/awg/clientsTable","iface":"wg0","wgBinary":"wg","pskPath":"/opt/amnezia/awg/wireguard_psk.key"}]' \
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo -E bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo -E bash
```
Для **Legacy** часто используется обычный `wg`, для новой AmneziaWG — **`awg`**; поле **`pskPath`** желательно указывать явно, если путь к `wireguard_psk.key` нестандартный.
@@ -249,7 +315,7 @@ cd /opt/amnezia-admin
Пример установки / обновления с частично пустой панелью:
```bash
UI_HIDE_SECTIONS=warp,cascade curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo -E bash
UI_HIDE_SECTIONS=warp,cascade curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo -E bash
```
Отдельные флаги **`UI_HIDE_USERS`**, **`UI_HIDE_WARP`**, **`UI_HIDE_CASCADE`**, **`UI_HIDE_MTPROTO`** (`1` или `true`) дублируют соответствующий токен.
@@ -288,13 +354,13 @@ UI_HIDE_SECTIONS=warp,cascade curl -fsSL https://raw.githubusercontent.com/andre
Проще всего для пути из исходников — та же команда, что при установке (данные в `DATA_DIR`, пароль и `AWG_PROFILES` сохранятся — профили подтягиваются из файла на VPS или из старого контейнера). Скрипт **подставит прежний внешний порт** контейнера `amnezia-admin`, если вы не передавали `HOST_PORT` и в коде по умолчанию стоит `8080`:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo bash
```
Если интерфейс после этого всё ещё старый — принудительно без кэша слоёв Docker:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo NO_CACHE=1 bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo NO_CACHE=1 bash
```
Если проект уже лежит в `/opt/amnezia-admin` через git и вы подтянули изменения (`git pull`), пересоберите без повторной загрузки архива:
@@ -320,13 +386,13 @@ sudo docker run --rm amnezia-admin:latest grep -Eo 'Новый клиент по
## Удаление одной командой
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/uninstall.sh | sudo bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/uninstall.sh | sudo bash
```
Полная очистка (контейнер, образ, данные панели и каталог `/opt/amnezia-admin`):
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/uninstall.sh | sudo REMOVE_IMAGE=1 REMOVE_DATA=1 REMOVE_SRC=1 bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/uninstall.sh | sudo REMOVE_IMAGE=1 REMOVE_DATA=1 REMOVE_SRC=1 bash
```
---
@@ -345,7 +411,7 @@ curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/s
### Свой пароль при установке
```bash
ADMIN_PASSWORD='ВашНадёжныйПароль' curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo -E bash
ADMIN_PASSWORD='ВашНадёжныйПароль' curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo -E bash
```
После первого успешного старта переменную `ADMIN_PASSWORD` из команды `docker run` убирайте — пароль уже в томе `DATA_DIR`.
@@ -377,7 +443,7 @@ ADMIN_PASSWORD=localtest node server.js
| Способ | Ссылка |
|--------|--------|
| GitHub | [amnezia_web-PRO](https://github.com/andrey271192/amnezia_web-PRO) |
| GitHub | [amnezia_web-PRO](https://git.bobyrev.com/PCA/amnezia_web-PRO) |
| Boosty | [boosty.to/andrey27/donate](https://boosty.to/andrey27/donate) |
| Ozon СБП | [Ozon СБП](https://finance.ozon.ru/apps/sbp/ozonbankpay/019dc200-2a5d-7931-a619-782d285f6798) |
| Telegram | [@lot_andrey](https://t.me/lot_andrey) |
@@ -400,7 +466,7 @@ MIT, см. [LICENSE](LICENSE).
---
- ⭐ **GitHub:** [andrey271192/amnezia_web-PRO](https://github.com/andrey271192/amnezia_web-PRO)
- ⭐ **GitHub:** [PCA/amnezia_web-PRO](https://git.bobyrev.com/PCA/amnezia_web-PRO)
- 💖 **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)

View File

@@ -22,7 +22,7 @@
```
2. Если строки нет, но `docker ps` показывает два контейнера вида `amnezia-awg*`, переустановите панель свежим установщиком из GitHub:
```bash
curl -fsSL https://raw.githubusercontent.com/andrey271192/amnezia_web-PRO/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash
curl -fsSL https://git.bobyrev.com/PCA/amnezia_web-PRO/raw/branch/main/scripts/install.sh | sudo env SKIP_LANDING=1 bash
```
Установщик сам создаст **`AWG_PROFILES`** и сохранит **`/root/amnezia-admin.awg-profiles.json`**.
3. Ручной JSON нужен только при нестандартных путях внутри AWG-контейнеров.

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

View File

@@ -1,6 +1,6 @@
{
"name": "amnezia-admin",
"version": "1.4.0",
"version": "1.4.2",
"private": false,
"description": "amnezia_web-PRO — веб-панель AmneziaWG: несколько инстансов, WARP, каскад/Endpoint, экспорт .conf (Docker)",
"license": "MIT",

View File

@@ -8,14 +8,14 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<script>try{var t=localStorage.getItem("theme")||(matchMedia("(prefers-color-scheme: light)").matches?"light":"dark");document.documentElement.dataset.theme=t}catch(e){}</script>
<link rel="stylesheet" href="/styles.css?v=1.4.0">
<link rel="stylesheet" href="/styles.css?v=1.4.2">
</head>
<body class="page">
<aside class="panel-promo-strip" role="complementary" aria-label="Поддержка и донат">
<div class="panel-promo-strip-inner">
<p class="panel-promo-subtitle muted">Поддержите проект через Boosty, Ozon СБП и Telegram — ниже те же ссылки в подвале.</p>
<div class="panel-promo-links">
<a class="panel-promo-a" href="https://github.com/andrey271192/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">⭐ GitHub</a>
<a class="panel-promo-a" href="https://git.bobyrev.com/PCA/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">⭐ Git</a>
<span class="panel-promo-sep" aria-hidden="true">·</span>
<a class="panel-promo-a" href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">💖 Boosty</a>
<span class="panel-promo-sep" aria-hidden="true">·</span>
@@ -39,7 +39,7 @@
</form>
<nav class="gate-donate muted" aria-label="Поддержка и донат">
Поддержка веб‑панелей (вне этого сервера):<br/>
<a href="https://github.com/andrey271192/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">GitHub</a>
<a href="https://git.bobyrev.com/PCA/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">GitHub</a>
<span class="gate-donate-dot" aria-hidden="true">·</span>
<a href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">Boosty</a>
<span class="gate-donate-dot" aria-hidden="true">·</span>
@@ -413,7 +413,7 @@
<div class="support-line">
<strong class="support-title">amnezia_web-PRO</strong>
<span class="support-sep" aria-hidden="true">·</span>
<a href="https://github.com/andrey271192/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">⭐ GitHub · amnezia_web-PRO</a>
<a href="https://git.bobyrev.com/PCA/amnezia_web-PRO" target="_blank" rel="noopener noreferrer">⭐ Git · amnezia_web-PRO</a>
<span class="support-sep" aria-hidden="true">·</span>
<a href="https://boosty.to/andrey27/donate" target="_blank" rel="noopener noreferrer">💖 Boosty</a>
<span class="support-sep" aria-hidden="true">·</span>
@@ -460,6 +460,6 @@
</div>
</dialog>
<script src="/app.js?v=1.4.0" type="module"></script>
<script src="/app.js?v=1.4.2" type="module"></script>
</body>
</html>

53
scripts/checks/audit2.py Normal file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""Сверяем ПОДНЯТЫЕ интерфейсы с их собственными конфигами.
Первый заход сравнивал wg0.conf с интерфейсом wg0, а в контейнере amnezia-awg
поднят awg0 — отсюда ложные «расхождения».
"""
import json, sys
sys.path.insert(0, "/app")
from managers.ssh_manager import SSHManager
PROBE = r"""
for c in $(docker ps --format '{{.Names}}' 2>/dev/null | grep '^amnezia-' | grep -vE 'nginx|frontend|backend|landing|xray|socks|ipsec|openvpn'); do
for bin in awg wg; do
docker exec $c sh -c "command -v $bin >/dev/null" 2>/dev/null || continue
for i in $(docker exec $c sh -c "$bin show interfaces 2>/dev/null"); do
live=$(docker exec $c sh -c "$bin show $i peers 2>/dev/null | grep -c ." | tr -d '\n')
conf=""
for f in /opt/amnezia/awg/$i.conf /opt/amnezia/awg/awg0.conf /opt/amnezia/awg/wg0.conf; do
docker exec $c test -f $f 2>/dev/null && { conf=$f; break; }
done
[ -n "$conf" ] || { echo "$c $i live=$live конфиг=НЕ НАЙДЕН"; continue; }
infile=$(docker exec $c grep -c '^\[Peer\]' $conf 2>/dev/null | tr -d '\n')
echo "$c $i live=$live файл=$infile ($conf)"
done
done
done
"""
d = json.load(open("/app/data/data.json"))
плохо = 0
for s in d["servers"]:
try:
with SSHManager(s["host"], s.get("ssh_port", 22), s["username"],
password=s.get("password") or None,
private_key=s.get("private_key") or None,
connect_timeout=8) as ssh:
out, err, _ = ssh.run_command(PROBE, timeout=60)
строки = [x.strip() for x in (out or "").splitlines() if x.strip()]
if not строки:
print(" ? %-26s нет поднятых интерфейсов" % s["name"][:26])
continue
for стр in строки:
беда = False
if "live=" in стр and "файл=" in стр:
l = int(стр.split("live=")[1].split()[0])
f = int(стр.split("файл=")[1].split()[0])
беда = (l != f)
плохо += 1 if беда else 0
print(" %s %-26s %s" % ("!!" if беда else "ok", s["name"][:26], стр))
except Exception as e:
плохо += 1
print(" !! %-26s НЕ ДОСТУЧАЛСЯ: %s" % (s["name"][:26], str(e)[:60]))
print("\nрасхождений:", плохо)

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env python3
"""Целостность конфигов awg по всему парку: склейки, финальный перевод строки,
проходит ли awg-quick strip и совпадает ли число пиров с живым интерфейсом."""
import json, sys
sys.path.insert(0, "/app")
from managers.ssh_manager import SSHManager
PROBE = r"""
for c in amnezia-awg2 amnezia-awg amnezia-awg31 amnezia-awg3 amnezia-awg-legacy; do
docker ps --format '{{.Names}}' 2>/dev/null | grep -qx $c || continue
for f in awg0.conf wg0.conf; do
p=/opt/amnezia/awg/$f
docker exec $c test -f $p 2>/dev/null || continue
glue=$(docker exec $c grep -c '/32\[Peer\]' $p 2>/dev/null | tr -d '\n')
end=$(docker exec $c sh -c "tail -c 1 $p | od -An -c | tr -d ' \n'")
peers=$(docker exec $c grep -c '^\[Peer\]' $p 2>/dev/null | tr -d '\n')
mode=$(docker exec $c stat -c %a $p 2>/dev/null | tr -d '\n')
bin=wg; iface=wg0
case $f in awg0.conf) bin=awg; iface=awg0;; esac
if docker exec $c sh -c "$bin-quick strip $p > /dev/null 2>&1"; then strip=ok; else strip=СБОЙ; fi
live=$(docker exec $c sh -c "$bin show $iface peers 2>/dev/null | grep -c ." | tr -d '\n')
echo "$c/$f peers=$peers live=$live glue=$glue end=$end mode=$mode strip=$strip"
done
done
"""
d = json.load(open("/app/data/data.json"))
беда = 0
for s in d["servers"]:
try:
with SSHManager(s["host"], s.get("ssh_port", 22), s["username"],
password=s.get("password") or None,
private_key=s.get("private_key") or None,
connect_timeout=8) as ssh:
out, err, _ = ssh.run_command(PROBE, timeout=60)
строки = [x.strip() for x in (out or "").splitlines() if x.strip()]
if not строки:
print(" ? %-26s нет контейнеров awg (%s)" % (s["name"][:26], (err or "")[:40]))
continue
for стр in строки:
плохо = ("glue=0" not in стр) or ("strip=ok" not in стр) or ("end=\\n" not in стр)
if "peers=" in стр and "live=" in стр:
try:
p = int(стр.split("peers=")[1].split()[0])
l = int(стр.split("live=")[1].split()[0])
if p != l:
плохо = True
стр += " ← файл и интерфейс расходятся"
except Exception:
pass
беда += 1 if плохо else 0
print(" %s %-26s %s" % ("!!" if плохо else "ok", s["name"][:26], стр))
except Exception as e:
беда += 1
print(" !! %-26s НЕ ДОСТУЧАЛСЯ: %s" % (s["name"][:26], str(e)[:60]))
print("\nпроблемных строк:", беда)

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Ищем склеенные строки в конфигах awg на всех серверах панели.
Имена переменных в пробе латиницей: sh внутри контейнеров кириллицу не берёт.
"""
import json, sys
sys.path.insert(0, "/app")
from managers.ssh_manager import SSHManager
ПРОБА = (
"for c in amnezia-awg2 amnezia-awg amnezia-awg31 amnezia-awg3 amnezia-awg-legacy; do "
" docker ps --format '{{.Names}}' 2>/dev/null | grep -qx $c || continue; "
" for f in awg0.conf wg0.conf; do "
" p=/opt/amnezia/awg/$f; "
" docker exec $c test -f $p 2>/dev/null || continue; "
" glue=$(docker exec $c grep -c '/32\\[Peer\\]' $p 2>/dev/null || echo 0); "
" endnl=$(docker exec $c sh -c \"tail -c 1 $p | od -An -c | tr -d ' '\" 2>/dev/null); "
" peers=$(docker exec $c grep -c '^\\[Peer\\]' $p 2>/dev/null || echo 0); "
" echo \"$c/$f peers=$peers glue=$glue end=$endnl\"; "
" done; done"
)
d = json.load(open("/app/data/data.json"))
for s in d["servers"]:
try:
with SSHManager(s["host"], s.get("ssh_port", 22), s["username"],
password=s.get("password") or None,
private_key=s.get("private_key") or None,
connect_timeout=8) as ssh:
out, err, _ = ssh.run_command(ПРОБА, timeout=40)
for строка in (out or err).splitlines():
строка = строка.strip()
if not строка:
continue
плохо = ("glue=0" not in строка) or ("end=\\n" not in строка)
print("%s %-26s %s" % (" !!" if плохо else " ", s["name"][:26], строка))
except Exception as e:
print(" %-26s СБОЙ: %s" % (s["name"][:26], str(e)[:50]))

View File

@@ -0,0 +1,30 @@
"""Не осталось ли от проверок тестовых клиентов в clientsTable и в data.json."""
import json, sys
sys.path.insert(0, "/app")
from managers.ssh_manager import SSHManager
МЕТКА = "__проверка_связи"
d = json.load(open("/app/data/data.json"))
в_панели = [c for c in json.dumps(d, ensure_ascii=False).split('"') if МЕТКА in c]
print("следов в data.json панели:", len(в_панели))
ПРОБА = (
"for c in $(docker ps --format '{{.Names}}' 2>/dev/null | grep -E 'amnezia-(awg|wireguard|xray)'); do "
" n=$(docker exec $c sh -c \"grep -o '%s[^\\\"]*' /opt/amnezia/awg/clientsTable /opt/amnezia/xray/clientsTable 2>/dev/null | wc -l\"); "
" [ \"$n\" != \"0\" ] && echo \"$c: $n\"; done; echo готово" % МЕТКА
)
всего = 0
for s in d["servers"]:
try:
with SSHManager(s["host"], s.get("ssh_port", 22), s["username"],
password=s.get("password") or None,
private_key=s.get("private_key") or None, connect_timeout=8) as ssh:
o, _, _ = ssh.run_command(ПРОБА, timeout=40)
строки = [x for x in (o or "").splitlines() if x.strip() and "готово" not in x]
if строки:
всего += len(строки)
print(" !!", s["name"], строки)
except Exception as e:
print(" ?", s["name"][:26], str(e)[:40])
print("серверов с остатками:", всего)

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Боевая проверка: на каждом сервере и каждом протоколе создаём тестового
клиента и тут же удаляем. Именно так работает кнопка «Добавить подключение».
Считаем пиров до и после: если после удаления число не вернулось — значит
за нами остался мусор, и это надо видеть.
"""
import json, sys, time
sys.path.insert(0, "/app")
from managers.ssh_manager import SSHManager
from managers.awg_manager import AWGManager
ИМЯ = "__проверка_связи_" + time.strftime("%d%m_%H%M")
ПРОТОКОЛЫ = ("awg", "awg2", "awg3", "awg31", "wireguard")
d = json.load(open("/app/data/data.json"))
итог = {"ok": 0, "сбой": 0, "мусор": 0}
for s in d["servers"]:
протоколы = [p for p in ПРОТОКОЛЫ
if (s.get("protocols", {}).get(p) or {}).get("installed")]
if not протоколы:
print(" – %-26s протоколов AWG не заведено" % s["name"][:26])
continue
for proto in протоколы:
метка = "%s / %s" % (s["name"][:22], proto)
try:
ssh = SSHManager(s["host"], s.get("ssh_port", 22), s["username"],
password=s.get("password") or None,
private_key=s.get("private_key") or None,
connect_timeout=10, connect_retries=1)
ssh.connect()
try:
m = AWGManager(ssh)
было = len(m._get_used_ips(proto))
порт = (s["protocols"][proto] or {}).get("port", "55424")
r = m.add_client(proto, ИМЯ, s["host"], порт)
cid = r.get("client_id") or r.get("clientId")
есть_конфиг = bool(r.get("config"))
стало = len(m._get_used_ips(proto))
m.remove_client(proto, cid)
после = len(m._get_used_ips(proto))
finally:
ssh.disconnect()
если_чисто = (после == было)
итог["ok" if (есть_конфиг and стало == было + 1) else "сбой"] += 1
if not если_чисто:
итог["мусор"] += 1
print(" %s %-30s пиров %d → %d → %d конфиг=%s" % (
"ok" if (есть_конфиг and стало == было + 1 and если_чисто) else "!!",
метка, было, стало, после, "есть" if есть_конфиг else "НЕТ"))
except Exception as e:
итог["сбой"] += 1
print(" !! %-30s %s" % (метка, str(e)[:70]))
print("\nсоздалось и убралось начисто: %d, сбоев: %d, осталось мусора: %d"
% (итог["ok"], итог["сбой"], итог["мусор"]))

View File

@@ -2,7 +2,8 @@
# Установка Amnezia Admin WebUI одной командой (см. README).
set -euo pipefail
GITHUB_REPO="${GITHUB_REPO:-andrey271192/amnezia_web-PRO}"
GITHUB_REPO="${GITHUB_REPO:-PCA/amnezia_web-PRO}"
GIT_BASE="${GIT_BASE:-https://git.bobyrev.com}"
BRANCH="${BRANCH:-main}"
INSTALL_DIR="${INSTALL_DIR:-/opt/amnezia-admin}"
DATA_DIR="${DATA_DIR:-/opt/amnezia-admin-data}"
@@ -21,8 +22,9 @@ need_root() {
need_docker() {
command -v docker >/dev/null 2>&1 || {
echo "Ошибка: нужен Docker."
exit 1
echo "→ Docker не найден — ставлю официальным скриптом get.docker.com..."
curl -fsSL https://get.docker.com | sh || { echo "Ошибка: не удалось поставить Docker."; exit 1; }
systemctl enable --now docker 2>/dev/null || true
}
docker info >/dev/null 2>&1 || {
echo "Ошибка: демон Docker не отвечает."
@@ -65,26 +67,24 @@ fi
if [[ "${SKIP_DOWNLOAD:-}" != "1" ]]; then
echo "→ Клонирование релиза ${GITHUB_REPO} (${BRANCH})..."
echo "→ Скачивание tar.gz с GitHub (вывода может не быть 1–10 мин.; при блокировках задайте зеркало GITHUB_REPO_URL_OVERRIDE или см. CURL_MAX_TIME ниже)."
echo "→ Скачивание tar.gz с ${GIT_BASE} (вывода может не быть 1–10 мин.; при блокировках задайте зеркало GITHUB_REPO_URL_OVERRIDE или см. CURL_MAX_TIME ниже)."
TMP=$(mktemp -d)
CURL_OPTS=(
-fsSL
-H 'Cache-Control: no-cache'
-H 'Pragma: no-cache'
--connect-timeout "${CURL_CONNECT_TIMEOUT:-30}"
--connect-timeout "${CURL_CONNECT_TIMEOUT:-15}"
--max-time "${CURL_MAX_TIME:-900}"
--retry "${CURL_RETRY:-2}"
--retry-delay "${CURL_RETRY_DELAY:-5}"
--retry-connrefused
)
if [[ "${INSTALL_SCRIPT_VERBOSE:-}" == "1" ]]; then CURL_OPTS+=(--progress-bar); fi
CURL_URL="${GITHUB_REPO_URL_OVERRIDE:-}"
if [[ -z "${CURL_URL}" ]]; then
CURL_URL="https://github.com/${GITHUB_REPO}/archive/refs/heads/${BRANCH}.tar.gz"
fi
# ponytail: GitHub-аккаунт заблокирован (10.2026), код живёт на git.bobyrev.com.
CURL_URL="${GITHUB_REPO_URL_OVERRIDE:-${GIT_BASE}/${GITHUB_REPO}/archive/${BRANCH}.tar.gz}"
if ! curl "${CURL_OPTS[@]}" "${CURL_URL}" | tar xz -C "${TMP}"; then
echo "Ошибка: не удалось скачать или распаковать архив (${CURL_URL})."
echo "Подсказка: проверьте доступ к github.com, branch/repo, при необходимости export GITHUB_REPO_URL_OVERRIDE='…' или INSTALL_SCRIPT_VERBOSE=1."
echo "Подсказка: проверьте доступ к git.bobyrev.com, при необходимости export GITHUB_REPO_URL_OVERRIDE='…' или INSTALL_SCRIPT_VERBOSE=1."
exit 1
fi
echo "→ Перенос распакованного дерева в ${INSTALL_DIR}…"
@@ -354,4 +354,4 @@ if [[ -f "${PASS_FILE}" ]]; then
echo "Первый пароль: $(cat "${PASS_FILE}")"
fi
echo ""
echo "Удаление: curl -fsSL https://raw.githubusercontent.com/${GITHUB_REPO}/${BRANCH}/scripts/uninstall.sh | sudo bash"
echo "Удаление: curl -fsSL ${GIT_BASE}/${GITHUB_REPO}/raw/branch/${BRANCH}/scripts/uninstall.sh | sudo bash"

View File

@@ -2626,10 +2626,7 @@ app.post("/api/settings", requireAuth, async (req, res) => {
app.get("/api/protocols", requireAuth, (req, res) => {
const rt = runtimeForRequest(req);
const hintSingle =
getProfiles().length < 2
? "Сейчас один инстанс: при установке не передали AWG_PROFILES или не восстановился снимок. Задайте JSON профилей и запустите install.sh — он сохранится в /root/amnezia-admin.awg-profiles.json."
: "";
const hintSingle = "";
res.json({
currentId: rt.profile.id,
currentLabel: rt.profile.label,