# 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, до реального деплоя.