Add Go rewrite with Postgres 17 and Dokploy Docker Compose

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
orohi
2026-07-27 08:21:21 +03:00
co-authored by Cursor
parent bac78dd3fc
commit 99a27f00be
67 changed files with 17864 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
# Amnezia VPN Share Panel (Go)
Полный переезд панели совместного доступа к Amnezia VPN с PHP на Go
(модуль `amnezia-share`). Приложение — единый статически собранный бинарник:
HTTP-сервер, сессии, CSRF, шаблоны и вся бизнес-логика (гостевые
share-ссылки, личный кабинет, админка) внутри одного процесса + PostgreSQL.
## Состав репозитория
```
Go/
├── cmd/
│ ├── server/ — основной HTTP-сервер (слушает APP_PORT)
│ └── cleanup/ — разовая задача очистки просроченных share-ссылок
├── internal/
│ ├── config/ — чтение переменных окружения
│ ├── db/ — подключение к БД + миграции
│ ├── models/ — доменные структуры (ShareLink, Member, ServerInfo, ...)
│ ├── panel/ — клиент Amnezia Web Panel API
│ ├── settings/ — key-value настройки в БД (URL панели, токен, лейблы и т.д.)
│ ├── auth/ — вход администратора, Pocket ID (OIDC)
│ ├── member/ — личный кабинет (регистрация, подписка, конфиги)
│ ├── share/ — гостевые share-ссылки, коды продления, сборка бандлов
│ ├── i18n/ — переводы RU/EN
│ └── web/ — HTTP-слой: App, роуты, middleware, шаблоны
│ └── handlers/ — обработчики, сгруппированные по разделам
├── web/
│ ├── templates/ — HTML-шаблоны (layouts, share, cabinet, admin, auth)
│ └── static/ — CSS/иконки (Bootstrap 5 подключается через CDN)
├── migrations/ — SQL-схема (идемпотентные CREATE TABLE IF NOT EXISTS)
├── Dockerfile
├── docker-compose.yml
└── .env.example
```
## Запуск локально (без Docker)
Требуется Go 1.22+ и PostgreSQL 14+.
```bash
cd Go
cp .env.example .env # заполните пароли/секреты
go mod tidy
go build ./...
DATABASE_URL="postgres://vpn_admin:vpn_admin@127.0.0.1:5432/vpn_admin?sslmode=disable" \
APP_SESSION_SECRET="локальный-дев-секрет-минимум-32-символа" \
go run ./cmd/server
```
Сервер поднимется на `http://127.0.0.1:30000`. При первом запуске
(таблица администраторов пуста) корень `/` перенаправит на `/install`
форму создания единственного администратора. Дальше вход через `/login`.
Миграции (`migrations/001_schema.sql`) применяются автоматически при
старте `cmd/server` и `cmd/cleanup` — отдельно накатывать их не нужно.
## Запуск через Docker Compose / Dokploy
```bash
cd Go
cp .env.example .env
# отредактируйте .env: POSTGRES_PASSWORD, APP_SESSION_SECRET (32+ символов)
docker compose up -d --build
```
Сервисы:
- **app** — веб-приложение, слушает `30000:30000` (в Dokploy пробросьте
этот порт через ваш прокси/домен).
- **db** — PostgreSQL 17, доступен только внутри docker-сети `amnezia`
(порт 5432 наружу не публикуется; не открывайте его в проде).
- **cleanup** — тот же образ, в цикле раз в 5 минут запускает
`/app/cleanup`, который удаляет истёкшие share-ссылки и их конфиги
на панели Amnezia.
Проверка живости: `GET /health``{"ok":true,"db":true,"time":"..."}`.
Этот же путь используют healthcheck-и в docker-compose.
### Переменные окружения
| Переменная | Назначение | По умолчанию |
|---|---|---|
| `APP_PORT` | порт HTTP-сервера | `30000` |
| `APP_BASE_URL` | префикс пути, если приложение висит не на корне домена (например `vpn`) | пусто |
| `APP_SESSION_SECRET` | секрет сессий (используется как соль для CSRF/токенов); задайте случайную строку 32+ символов | — |
| `APP_HTTP_BUDGET_SEC` | таймаут на HTTP-запросы к панели Amnezia в рамках одного запроса | `52` |
| `DATABASE_URL` | строка подключения к PostgreSQL | `postgres://vpn_admin:vpn_admin@127.0.0.1:5432/vpn_admin?sslmode=disable` |
| `AMNEZIA_PANEL_URL`, `AMNEZIA_API_TOKEN` | адрес и токен панели Amnezia (можно также задать в `/admin/settings`) | пусто |
| `AMNEZIA_SERVER_LABELS_JSON` | JSON `{"1":"Германия"}` — переопределение названий серверов через окружение | пусто |
| `MIGRATIONS_DIR` | путь к папке с SQL-миграциями | `migrations` |
| `WEB_DIR` | путь к папке `templates/` и `static/` | `web` |
Настройки панели, Pocket ID, режим техработ, лейблы/флаги/скорости
серверов и лимиты личного кабинета по умолчанию удобнее менять прямо в
админке (`/admin/settings`, `/admin/servers`) — они хранятся в таблице
`site_settings` и переживают перезапуск контейнера.
## Основные маршруты
Гостевые:
- `GET /` — редирект на `/admin`, `/install` или `/login` в зависимости от состояния.
- `GET/POST /install` — создание единственного администратора (доступно, пока админов нет).
- `GET/POST /login`, `GET /login?oidc=1`, `GET /oidc/callback`, `GET /logout` — вход администратора (пароль или Pocket ID SSO).
- `GET/POST /share?k=ТОКЕН` — гостевая страница share-ссылки: выбор сервера/протокола, создание/перенос/продление конфига, скачивание. POST с заголовком `X-Share-Async: 1` отвечает JSON.
- `GET /share/servers?k=`, `GET /share/download?k=&cre=&part=conf|vpn|zip`.
- `GET /faq`, `GET /rules`, `GET /status` — статические страницы + пинг серверов.
- `GET/POST /cabinet`, `/cabinet/login`, `/cabinet/register`, `/cabinet/logout`, `/cabinet/servers`, `/cabinet/download` — личный кабинет.
Администрирование (требует входа):
- `GET /admin` — дашборд.
- `GET/POST /admin/links` — управление share-ссылками (создание, продление, список серверов, удаление конфигов).
- `GET/POST /admin/renewal` — коды продления (для гостевых ссылок и/или личного кабинета).
- `GET/POST /admin/configs` — обзор всех выданных конфигов с фильтрами и удалением.
- `GET/POST /admin/servers` — метки, протоколы, флаги, скорость и отключение серверов панели.
- `GET/POST /admin/settings` — URL/токен панели, Pocket ID, техработы, лимиты кабинета, проверка соединения.
Статика: `/static/*` раздаётся из `WEB_DIR/static`.
## Миграция с PHP-версии
- Схема БД совместима: `migrations/001_schema.sql` использует
`CREATE TABLE IF NOT EXISTS` — можно указать Go-приложению ту же базу,
на которой уже работала PHP-панель, без потери данных.
- Ключи в таблице настроек (`site_settings`) переиспользованы 1:1
(`amnezia_panel_url`, `amnezia_api_token`, `amnezia_server_labels_json`,
`share_maintenance_mode`, `pocket_id_*` и т.д.) — значения, заданные в
PHP-админке, подхватятся автоматически.
- Cookie для языка (`share_lang`) и сессии называются иначе
(`amnezia_session`), поэтому после переключения все пользователи один
раз залогинятся заново — это нормально.
- Разовый крон-скрипт очистки истёкших ссылок (`cleanup_share.php`)
заменён на бинарник `cmd/cleanup`, который в docker-compose запускается
в цикле каждые 5 минут отдельным контейнером.
- Файлы конфигов больше не пишутся на диск — тело ответа панели
сохраняется в БД (`share_creations.response_json`) и конфиги
собираются "на лету" при скачивании, как и в PHP-версии.
## Тесты
```bash
go build ./...
go test ./...
```
`internal/web` и `internal/web/handlers` содержат smoke-тесты, которые
парсят все HTML-шаблоны и рендерят каждую страницу с реалистичными
данными без подключения к базе — это ловит опечатки в шаблонах ещё на
этапе CI, до реального деплоя.