Document the panel API in the README
The public /api/v1 surface and its docs went away with the API keys, leaving nothing written down about what the panel exposes — even though every route it uses is reachable over HTTP with a login token. Replaces the install-source section with an API chapter: the JWT flow and its 401/429 cases, the unauthenticated /ui/brand, health and interface status, the user routes including why fetching a key is a POST, reissue, and the 2.0 to 3.1 upgrade with its 409 and 500 cases. What is left of the install-source notes is one line pointing at the comments in install.sh and .env. Shapes and status codes are taken from the handlers rather than from memory, and the auth behaviour was checked against a running server.
This commit is contained in:
@@ -43,45 +43,81 @@ AWG_GEN=auto bash <(curl -Ls https://git.ma7neko.ru/maeneko/forgetting/raw/branc
|
|||||||
переустановка не нужна, пользователи сохраняются, ключи перевыпускаются
|
переустановка не нужна, пользователи сохраняются, ключи перевыпускаются
|
||||||
автоматически.
|
автоматически.
|
||||||
|
|
||||||
### Свой источник и своё имя
|
Источник архива и имя панели не зашиты в код — задаются переменными
|
||||||
|
`REPO_BASE`, `REPO_FALLBACK`, `ARCHIVE_URL`, `BRAND` перед запуском установщика
|
||||||
|
(подробности — в комментариях `install.sh` и в `.env`).
|
||||||
|
|
||||||
В коде не зашиты ни репозиторий, ни бренд — всё задаётся окружением до запуска:
|
## API
|
||||||
|
|
||||||
| Переменная | По умолчанию | Зачем |
|
Отдельного публичного API с ключами нет: наружу смотрит только панель, и всё,
|
||||||
|---|---|---|
|
что она умеет, доступно по HTTP. Схема одна — логин отдаёт JWT на 24 часа,
|
||||||
| `REPO_BASE` | `https://git.ma7neko.ru/maeneko/forgetting` | основной источник архива релиза |
|
дальше с ним дёргаются те же роуты, что и из браузера. Базовый URL — адрес
|
||||||
| `REPO_FALLBACK` | `https://github.com/maeneko/forgetting` | запасной, если в основном релиза ещё нет |
|
сервера и порт, выбранный при установке.
|
||||||
| `ARCHIVE_URL` | — | полный URL архива, перекрывает оба варианта |
|
|
||||||
| `BRAND` | из `.env` | имя продукта в баннерах, systemd-юните и панели |
|
|
||||||
|
|
||||||
Путь релиза у Gitea и GitHub одинаковый (`<repo>/releases/download/v<версия>/awgcontrol-<версия>.tar.gz`),
|
> [!WARNING]
|
||||||
так что подходит любой из них. Если архив не найден в основном источнике,
|
> Панель отдаёт приватные поля пиров (`vpn_key`, `psk_key`) — это не публичный
|
||||||
установщик предупреждает и берёт его из запасного.
|
> контракт. Не выставляй её порт в интернет без TLS и ограничения по адресам.
|
||||||
|
|
||||||
Архив собирается по тегу `v*`: на GitHub — `.github/workflows/release.yml`, в
|
### Авторизация
|
||||||
Gitea — `.gitea/workflows/release.yml` (сборка та же, публикация через API
|
|
||||||
Gitea). Для запуска в Gitea репозиторий не должен быть pull-зеркалом, Actions
|
|
||||||
включены, а runner зарегистрирован с меткой `ubuntu-latest`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
REPO_BASE=https://git.example.org/me/vpn BRAND="My VPN" \
|
TOKEN=$(curl -s -X POST http://HOST:PORT/login \
|
||||||
bash <(curl -Ls https://git.example.org/me/vpn/raw/branch/main/install.sh)
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"user":"admin","pass":"***"}' | jq -r .token)
|
||||||
```
|
```
|
||||||
|
|
||||||
Имя панели, канал и версия лежат в `.env` в корне проекта (едет в архиве
|
| Метод | Ответ и ошибки |
|
||||||
релиза, на сервере — `/opt/awg-control/.env`):
|
|---|---|
|
||||||
|
| `POST /login` | `{ "token": "<JWT>" }`, срок 24 часа. `401` — неверная пара; `429` — больше 5 неудачных попыток с одного IP за 15 минут |
|
||||||
|
| `POST /logout` | `{ "ok": true }`, токен отзывается немедленно |
|
||||||
|
|
||||||
```env
|
Дальше в каждый запрос: `Authorization: Bearer $TOKEN`.
|
||||||
BRAND=Forgetting
|
|
||||||
CHANNEL=Beta
|
### Состояние
|
||||||
VERSION=0.2.0
|
|
||||||
|
| Метод | Ответ |
|
||||||
|
|---|---|
|
||||||
|
| `GET /ui/brand` | `{ "brand": "Forgetting", "channel": "Beta", "version": "0.2.0" }` — **без авторизации**, панель берёт отсюда вордмарк на экране логина |
|
||||||
|
| `GET /health` | `{ "status", "server", "ip", "gen", "awg": { "status", "peers", "module", "tools" } }`. `200`, если интерфейс поднят, иначе `503` и `status: "degraded"` |
|
||||||
|
| `GET /awg/status` | `{ "up": true, "peers": 3, "publicKey": "…" }` |
|
||||||
|
|
||||||
|
`gen` — поколение AmneziaWG, на параметрах которого сейчас работает интерфейс:
|
||||||
|
`"2"` или `"3.1"`. Оно выводится из `awg1.conf`, а не хранится отдельно.
|
||||||
|
|
||||||
|
### Пользователи
|
||||||
|
|
||||||
|
| Метод | Что делает |
|
||||||
|
|---|---|
|
||||||
|
| `POST /api/users` | Создаёт пира. Тело `{ "name": "alice" }`, имя — `a–z A–Z 0–9 _ -`, до 32 символов. `201` с `{ name, ip, pub_key, psk_key, vpn_key, key_gen, vpn_key_prev }`; `400` — имя не прошло валидацию, `409` — уже есть |
|
||||||
|
| `GET /api/users` | Список: `{ users: [{ name, ip, pub_key, vpn_key, key_gen, online, lastHandshake }] }` |
|
||||||
|
| `GET /api/users/stats` | То же без ключей, но со счётчиками: `{ users: [{ name, ip, key_gen, online, lastHandshake, rx, tx }] }` |
|
||||||
|
| `POST /api/users/:name` | Возвращает пользователя целиком, включая `vpn_key`. Метод именно `POST`, чтобы ключ не оседал в логах и истории как параметр `GET`. `404` — не найден |
|
||||||
|
| `DELETE /api/users/:name` | `{ "success": true, "name": "alice" }` |
|
||||||
|
| `POST /api/users/reissue` | Пересобирает `vpn://` всем на текущих параметрах: `{ total, reissued, regenerated: [], backup }`. IP и ключевая пара сохраняются, клиентам нужно заново импортировать ключ; `backup` — путь к снимку базы, снятому перед проходом |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s -X POST http://HOST:PORT/api/users \
|
||||||
|
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
||||||
|
-d '{"name":"alice"}' | jq -r .vpn_key
|
||||||
```
|
```
|
||||||
|
|
||||||
Оттуда их читают CLI (баннер меню) и панель (вордмарк, `GET /ui/brand`).
|
Имея `vpn_key`, конфиг `.conf` можно получить локально: убрать префикс `vpn://`,
|
||||||
`BRAND=` при установке перекрывает значение из файла.
|
base64url-декодировать, отбросить первые 4 байта (длина), распаковать
|
||||||
|
`zlib inflate` → JSON; текст конфига лежит в `last_config.config`.
|
||||||
|
|
||||||
|
### Интерфейс AWG
|
||||||
|
|
||||||
|
| Метод | Что делает |
|
||||||
|
|---|---|
|
||||||
|
| `POST /awg/start` | Поднимает интерфейс, если он лежит; возвращает его статус |
|
||||||
|
| `POST /awg/restart` | `awg-quick down/up` + ресинк пиров, `{ "success": true }`. Соединения клиентов кратковременно рвутся |
|
||||||
|
| `POST /awg/upgrade` | Переводит сервер с 2.0 на 3.1: правит `awg1.conf`, перезапускает интерфейс и перевыпускает все ключи. `{ gen, backup, bumpedS: [], reissue: { total, reissued, … } }` |
|
||||||
|
|
||||||
|
`POST /awg/upgrade` отвечает `409`, если сервер уже на 3.1, модуль в ядре не
|
||||||
|
3.x или ядро старше 5.5, и `500` с текстом причины, если ядро не приняло
|
||||||
|
3.1-конфиг — в этом случае прежний конфиг возвращается из копии, а интерфейс
|
||||||
|
поднимается обратно на 2.0.
|
||||||
|
|
||||||
Сама панель и её API к домену не привязаны: работают по адресу того сервера,
|
|
||||||
куда установлены, внешних сервисов не требуют.
|
|
||||||
## Управление
|
## Управление
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user