Releases only existed on GitHub, while install.sh now defaults to pulling the archive from the Gitea mirror. This builds the same archive on a v* tag and publishes it through the Gitea API, since the runner has no gh CLI: create the release, fall back to looking it up by tag when it already exists, then upload the tarball as an asset. Two details are easy to get wrong and are commented in place. The release id is the first "id" in Gitea's JSON, so the match must be non-greedy — a greedy one picks up the author or asset id instead. And the id helper needs `|| true`, because an empty grep under pipefail would abort the step on the path where the release already exists. The workflow cannot run yet: the Gitea repo is a pull mirror, which neither runs Actions nor accepts release creation. It starts working once the repo is un-mirrored, Actions are enabled and a runner with the ubuntu-latest label is registered; the header of the file lists those prerequisites.
132 lines
7.9 KiB
Markdown
132 lines
7.9 KiB
Markdown
# Forgetting
|
||
Панель управления и API для VPN на базе [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module)
|
||
> [!WARNING]
|
||
> Данный проект предназначен только для использования в законных целях.
|
||
## Архитектура
|
||
|
||
Три компонента, устанавливаются в `/opt/awg-control/`:
|
||
|
||
| Компонент | Роль |
|
||
|---|---|
|
||
| **awg-ctrl** | Привилегированный REST-бэкенд. Управляет пирами через `awg`/`awg-quick`, ведёт SQLite-базу, генерирует `vpn://` ключи. Слушает только loopback. |
|
||
| **awg-ui** | Express + React. Веб-панель, аутентификация (JWT), интеграция с API MA7, прокси к awg-ctrl. Единственный сервис, доступный по сети. |
|
||
| **cli** | Менеджер процессов: `start`/`stop`/`restart`/`status`, смена логина/пароля панели, интерактивное TUI-меню. |
|
||
|
||
Внутренняя связь awg-ui → awg-ctrl подписывается асимметрично (Ed25519): приватный ключ только у awg-ui, awg-ctrl проверяет подпись публичным.
|
||
|
||
## Требования
|
||
- **ОС**: Ubuntu 24.04+ (Тесты проходили на Ubuntu 24.04.4 LTS)
|
||
- **Права**: root.
|
||
- **Ядро**: kvm (не OpenVZ/LXC/Docker/WSL — нужен загружаемый kernel-модуль AmneziaWG).
|
||
- **Заголовки ядра** под текущее ядро (для сборки DKMS-модуля).
|
||
- **Node.js 20.x** (ставится установщиком автоматически).
|
||
|
||
Совместимость установщик проверяет сам перед любыми изменениями.
|
||
|
||
## Установка
|
||
|
||
На сервере, от root:
|
||
|
||
```bash
|
||
bash <(curl -Ls https://git.ma7neko.ru/maeneko/forgetting/raw/branch/main/install.sh)
|
||
```
|
||
|
||
Установщик по умолчанию ставит сервер на AmneziaWG 3.1. Если модуль в ядре
|
||
старше 3.x или ядро старше 5.5, установка остановится с диагностикой — поставить
|
||
на 2.0 можно так:
|
||
|
||
```bash
|
||
AWG_GEN=auto bash <(curl -Ls https://git.ma7neko.ru/maeneko/forgetting/raw/branch/main/install.sh)
|
||
```
|
||
|
||
Перевести такой сервер на 3.1 позже можно кнопкой «Перейти на AWG 3.1» в панели —
|
||
переустановка не нужна, пользователи сохраняются, ключи перевыпускаются
|
||
автоматически.
|
||
|
||
### Свой источник и своё имя
|
||
|
||
В коде не зашиты ни репозиторий, ни бренд — всё задаётся окружением до запуска:
|
||
|
||
| Переменная | По умолчанию | Зачем |
|
||
|---|---|---|
|
||
| `REPO_BASE` | `https://git.ma7neko.ru/maeneko/forgetting` | основной источник архива релиза |
|
||
| `REPO_FALLBACK` | `https://github.com/maeneko/forgetting` | запасной, если в основном релиза ещё нет |
|
||
| `ARCHIVE_URL` | — | полный URL архива, перекрывает оба варианта |
|
||
| `BRAND` | из `.env` | имя продукта в баннерах, systemd-юните и панели |
|
||
|
||
Путь релиза у Gitea и GitHub одинаковый (`<repo>/releases/download/v<версия>/awgcontrol-<версия>.tar.gz`),
|
||
так что подходит любой из них. Если архив не найден в основном источнике,
|
||
установщик предупреждает и берёт его из запасного.
|
||
|
||
Архив собирается по тегу `v*`: на GitHub — `.github/workflows/release.yml`, в
|
||
Gitea — `.gitea/workflows/release.yml` (сборка та же, публикация через API
|
||
Gitea). Для запуска в Gitea репозиторий не должен быть pull-зеркалом, Actions
|
||
включены, а runner зарегистрирован с меткой `ubuntu-latest`.
|
||
|
||
```bash
|
||
REPO_BASE=https://git.example.org/me/vpn BRAND="My VPN" \
|
||
bash <(curl -Ls https://git.example.org/me/vpn/raw/branch/main/install.sh)
|
||
```
|
||
|
||
Имя панели, канал и версия лежат в `.env` в корне проекта (едет в архиве
|
||
релиза, на сервере — `/opt/awg-control/.env`):
|
||
|
||
```env
|
||
BRAND=Forgetting
|
||
CHANNEL=Beta
|
||
VERSION=0.2.0
|
||
```
|
||
|
||
Оттуда их читают CLI (баннер меню) и панель (вордмарк, `GET /ui/brand`).
|
||
`BRAND=` при установке перекрывает значение из файла.
|
||
|
||
Сама панель и её API к домену не привязаны: работают по адресу того сервера,
|
||
куда установлены, внешних сервисов не требуют.
|
||
## Управление
|
||
|
||
```bash
|
||
awg-ctrl
|
||
```
|
||
|
||
Через systemd (автозапуск на загрузке):
|
||
|
||
```bash
|
||
systemctl start|stop|restart awg-control
|
||
```
|
||
|
||
## Интеграция с MA7
|
||
|
||
Этот сервер персональный — принадлежит одному абоненту MA7 (сервиса
|
||
VPN-подписки). Панель ничем не управляет в MA7 и не отдаёт наружу свой API:
|
||
вкладка «Профиль» только читает баланс своего владельца. Секрет MA7 живёт
|
||
только в `awg-ui` (`cli.env`) и в браузер не попадает — фронт ходит на свой
|
||
бэкенд, тот читает MA7.
|
||
|
||
Нужные переменные (задаются при установке или руками в `cli.env`):
|
||
|
||
| Переменная | Назначение |
|
||
|---|---|
|
||
| `MA7_API_BASE_URL` | адрес API MA7, например `https://amnesia.ma7neko.ru` |
|
||
| `MA7_JWT_SECRET` | секрет, которым панель сама подписывает `X-Bot-Token` (эндпоинта, выдающего токен, в MA7 нет) |
|
||
| `MA7_LOGIN` | логин владельца этого сервера в MA7 (`ma7_xxxxxx`) |
|
||
|
||
Вкладка «Профиль» просто показывает текущий баланс `MA7_LOGIN`. При установке
|
||
`MA7_LOGIN` заодно предлагается как логин панели (`UI_USER`) — сервер
|
||
персональный, и заказчик входит тем же именем, что знает по MA7; при желании
|
||
логин панели можно задать свой. Это разные переменные: `UI_USER` решает, кого
|
||
пускать в панель, `MA7_LOGIN` — чей баланс показывать.
|
||
|
||
`MA7_LOGIN` задаётся один раз при установке и **не редактируется из панели**: у панели
|
||
один общий пароль (`UI_USER`/`UI_PASS`) без отдельного клиентского входа, а
|
||
`MA7_JWT_SECRET` умеет искать в MA7 любого абонента — редактируемый в браузере
|
||
логин превратил бы личный баланс в инструмент подглядывания за чужими.
|
||
|
||
> [!WARNING]
|
||
> `MA7_JWT_SECRET` — мастер-ключ ко всему MA7: с ним можно читать данные любых
|
||
> пользователей MA7, не только этого сервера. Токены MA7 без срока действия,
|
||
> отзыва нет — «отобрать доступ» значит одновременно сменить `MA7_JWT_SECRET`
|
||
> во всех сервисах MA7 и здесь, в `cli.env`.
|
||
|
||
## Лицензия
|
||
[MIT](LICENSE) © 2026 Ivan Vasilev
|