tgvpn

Версия: 0.20.0

Telegram-бот на Go для управления VPN через панель Remnawave: проверка панели, создание пользователей, назначение сквадов. Данные хранятся в PostgreSQL.

Содержание

Требования

Компонент Минимум
Docker 24+
Docker Compose v2 (docker compose)
PostgreSQL 16+ (в compose включён)
Токен бота @BotFather
Сеть Исходящий HTTPS к api.telegram.org (порт 443)

Для запуска без Docker: Go 1.22+.


Установщик на сервере

Интерактивный скрипт запросит все параметры, создаст .env и запустит Docker.

Требования на сервере

  • Linux (Ubuntu 22.04/24.04, Debian 12)
  • curl, git (для клонирования)
  • Права sudo (для установки Docker при необходимости)

Установка одной командой

Если репозиторий уже на сервере:

cd tgvpn
chmod +x install.sh
./install.sh

Или скачайте скрипт и укажите каталог /opt/tgvpn:

sudo mkdir -p /opt/tgvpn
cd /opt/tgvpn
git clone <URL-вашего-репозитория> .
chmod +x install.sh
./install.sh

Что спрашивает установщик

Блок Параметры
Telegram BOT_TOKEN, TELEGRAM_ADMIN_ID, BOT_DEBUG
Remnawave URL панели, API token, Caddy token, subscription URL
PostgreSQL пользователь, база, пароль (можно сгенерировать случайный)
VPN срок по умолчанию, UUID сквадов (опционально)
Система каталог установки, URL git (если не из текущей папки)

После завершения: docker compose up -d --build, проверка docker compose ps.

Переменные окружения для PostgreSQL в compose

В .env должны совпадать POSTGRES_PASSWORD и пароль в DATABASE_URL:

POSTGRES_USER=tgvpn
POSTGRES_PASSWORD=ваш_сильный_пароль
POSTGRES_DB=tgvpn
DATABASE_URL=postgres://tgvpn:ваш_сильный_пароль@db:5432/tgvpn?sslmode=disable

Установщик заполняет это автоматически.


Быстрый старт (Docker Compose)

1. Клонирование

git clone <URL-вашего-репозитория>
cd tgvpn

2. Переменные окружения

cp .env.example .env

Отредактируйте .env:

BOT_TOKEN=ваш_токен_от_BotFather
BOT_DEBUG=false
TELEGRAM_ADMIN_ID=123456789
REMNAWAVE_PANEL_NAME=Панель 1
REMNAWAVE_PANEL_URL=https://panel.example.com
REMNAWAVE_API_TOKEN=токен_из_панели
REMNAWAVE_SUBSCRIPTION_URL=https://sub.example.com
DATABASE_URL=postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable
DEFAULT_USER_DAYS=30

Важно: файл .env не попадает в git и не копируется в образ. Compose передаёт переменные в контейнер при старте.

3. Сборка и запуск

Поднимаются два сервиса: PostgreSQL (db) и бот (bot). Бот стартует только после готовности БД.

docker compose up -d --build

4. Проверка

# статус (db — healthy, bot — running)
docker compose ps

# логи бота (должно быть: «postgres ok», «бот @имя запущен»)
docker compose logs --tail=30 bot

# логи PostgreSQL
docker compose logs --tail=20 db

В Telegram: /start → кнопка «Получить конфиг» или /config (trial на TRIAL_USER_DAYS, по умолчанию 1 день). От админа — /admin squads, /admin user.

5. Остановка

# остановить контейнеры (данные БД сохраняются в volume pgdata)
docker compose down

# удалить и данные БД (осторожно!)
docker compose down -v

PostgreSQL

Бот не работает без PostgreSQL: при старте проверяется DATABASE_URL, применяется миграция, далее идёт работа с БД.

Роль базы данных

Таблица Назначение
telegram_users Пользователи Telegram, зашедшие в бота (/start)
vpn_users Созданные в Remnawave аккаунты: UUID, логин, сквады, срок
admin_wizard Состояние мастера админа (создание пользователя, назначение сквадов)

Миграции лежат в internal/db/migrations/ и применяются автоматически при каждом запуске бота (CREATE TABLE IF NOT EXISTS).

Схема в Docker Compose

services:
  db:    # PostgreSQL 16, volume pgdata
  bot:   # ждёт healthy у db, затем стартует

Параметры по умолчанию (см. docker-compose.yml):

Параметр Значение
Хост (внутри compose) db
Порт 5432
База tgvpn
Пользователь tgvpn
Пароль tgvpn

Строка подключения для бота:

DATABASE_URL=postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable

Формат URL (общий вид):

postgres://USER:PASSWORD@HOST:PORT/DATABASE?sslmode=disable

Подключение к БД вручную

Из каталога проекта:

# интерактивная консоль psql внутри контейнера
docker compose exec db psql -U tgvpn -d tgvpn

Полезные запросы:

-- все VPN-пользователи, созданные через бота
SELECT remnawave_username, remnawave_uuid, expire_at, created_at FROM vpn_users;

-- активные мастера админа
SELECT admin_telegram_id, step, updated_at FROM admin_wizard;

\q

Продакшен: смена пароля БД

  1. Задайте сильный пароль в docker-compose.yml (секция db.environment) или вынесите в .env:
environment:
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change_me_strong}
  1. Обновите DATABASE_URL в .env бота с тем же паролем.

  2. Пересоздайте стек:

docker compose down
docker compose up -d --build

Если меняете пароль у уже существующего volume pgdata, может понадобиться сброс volume или ALTER USER внутри старой БД.

Внешний PostgreSQL (без контейнера db)

Если БД на отдельном сервере или managed Postgres:

  1. Создайте базу и пользователя с правами CREATE, SELECT, INSERT, UPDATE, DELETE.
  2. В .env укажите реальный URL:
DATABASE_URL=postgres://user:password@postgres.example.com:5432/tgvpn?sslmode=require
  1. В docker-compose.yml закомментируйте или удалите сервис db и depends_on у bot.
  2. Убедитесь, что с хоста бота есть сетевой доступ к порту 5432.

Резервное копирование

# дамп в файл (дата в имени)
docker compose exec -T db pg_dump -U tgvpn tgvpn > backup_$(date +%Y%m%d).sql

# восстановление (на пустую или новую БД)
cat backup_20260101.sql | docker compose exec -T db psql -U tgvpn -d tgvpn

Рекомендуется настроить cron на VPS для ежедневных дампов.

Проверка после деплоя

docker compose ps
# tgvpn-db   running (healthy)
# tgvpn-bot  running

docker compose logs bot | grep -i postgres
# ожидается успешный старт без «ping postgres» / «apply migration» ошибок

Ошибки PostgreSQL

Симптом Решение
DATABASE_URL не задан Добавьте переменную в .env
connect postgres / ping postgres Проверьте, что db в состоянии healthy: docker compose ps
Бот стартует раньше БД В compose уже есть depends_on: condition: service_healthy — обновите compose
password authentication failed Совпадение пароля в POSTGRES_PASSWORD и в DATABASE_URL
Пустые таблицы после создания user Смотрите логи бота и ответ Remnawave API; запись в vpn_users идёт после успешного POST /api/users

Развёртывание на VPS (Linux)

Ниже — пошаговая установка на чистый сервер (Ubuntu 22.04/24.04, Debian 12). Аналогично на других дистрибутивах с Docker.

Шаг 1. Подключение к серверу

ssh user@your-server-ip

Шаг 2. Установка Docker

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER

Выйдите из SSH и зайдите снова, чтобы группа docker применилась:

exit
ssh user@your-server-ip
docker --version
docker compose version

Шаг 3. Клонирование проекта

sudo mkdir -p /opt/tgvpn
sudo chown $USER:$USER /opt/tgvpn
cd /opt/tgvpn
git clone <URL-вашего-репозитория> .

Шаг 4. Настройка .env

cp .env.example .env
nano .env   # или vim / vi

Укажите реальный BOT_TOKEN, DATABASE_URL (в compose для VPS обычно оставляют postgres://tgvpn:...@db:5432/...), Remnawave и при необходимости UUID сквадов (DEFAULT_*).

Для продакшена смените пароль PostgreSQL — см. PostgreSQL → Продакшен.

Права на секреты:

chmod 600 .env

Шаг 5. Запуск в фоне

docker compose up -d --build

Проверка:

docker compose ps
docker compose logs --tail=50 bot
docker compose logs --tail=20 db

Шаг 6. Автозапуск после перезагрузки сервера

В docker-compose.yml уже указано restart: unless-stopped. После перезагрузки VPS контейнер поднимется сам, если Docker запущен:

sudo systemctl enable docker
sudo systemctl start docker

Шаг 7. Обновление

См. раздел Обновление бота ниже.


Обновление бота

Инструкция для уже работающей установки: подтянуть код из git, пересобрать контейнер и убедиться, что бот запустился.

Перед обновлением

  1. Убедитесь, что .env сохранён на сервере (он не в git).
  2. Посмотрите, не появились ли новые переменные в .env.example:
cd /opt/tgvpn   # или каталог, куда клонировали проект
git fetch origin
git diff HEAD origin/main -- .env.example

Если в .env.example есть новые строки — добавьте их в свой .env вручную.

Обновление на VPS (Docker)

cd /opt/tgvpn

# 1. Скачать изменения
git pull origin main

# 2. Пересобрать и перезапустить (простой даунтайм ~10–30 сек)
docker compose up -d --build

# 3. Проверить логи
docker compose ps
docker compose logs --tail=50 bot

В логах должны быть строки вида: бот @имя_бота запущен и администратор ID ….

Проверка в Telegram (от аккаунта админа):

  • /start — бот отвечает
  • /admin check — проверка панели Remnawave

Обновление на Windows (Docker Desktop)

cd tgvpn
git pull origin main
docker compose up -d --build
docker compose logs --tail=50 bot

Обновление без Docker (локально)

cd tgvpn
git pull origin main
go build -o bot .
# остановите старый процесс бота, затем:
./bot

Если изменили только .env

Пересборка не нужна — достаточно пересоздать контейнер:

docker compose up -d --force-recreate

Откат на предыдущую версию

cd /opt/tgvpn
git log --oneline -5          # найти нужный коммит
git checkout <хеш_коммита>    # например: git checkout f360d53
docker compose up -d --build

Вернуться на актуальную ветку:

git checkout main
git pull origin main
docker compose up -d --build

Очистка старых образов Docker (опционально)

После нескольких обновлений на диске копятся неиспользуемые слои:

docker image prune -f

Частые проблемы при обновлении

Симптом Решение
git pull конфликтует с локальными правками git stashgit pullgit stash pop или сбросить локальные изменения: git checkout -- .
Бот не стартует после pull docker compose logs bot — часто не хватает новой переменной в .env
Старый код в контейнере Обязательно --build: docker compose up -d --build
Нет доступа к git Проверьте SSH/HTTPS-доступ к вашему git-серверу

Развёртывание на Windows

Docker Desktop

  1. Установите Docker Desktop.
  2. В PowerShell:
git clone <URL-вашего-репозитория>
cd tgvpn
Copy-Item .env.example .env
# отредактируйте .env — вставьте BOT_TOKEN
docker compose up -d --build
docker compose logs -f bot

Локальная разработка (без Docker)

Нужен запущенный PostgreSQL 16+ (локально или только контейнер БД):

# вариант: только БД в Docker, бот на хосте
docker compose up -d db

В .env для локального бота укажите:

DATABASE_URL=postgres://tgvpn:tgvpn@localhost:5432/tgvpn?sslmode=disable

Проброс порта в docker-compose.yml (если ещё нет):

db:
  ports:
    - "5432:5432"

Запуск:

cp .env.example .env
go run .

или

go build -o bot .
./bot

Переменные окружения

Переменная Обязательно Описание
BOT_TOKEN да Токен от @BotFather
TELEGRAM_ADMIN_ID да Числовой Telegram user ID администратора (например, @userinfobot)
REMNAWAVE_PANEL_NAME нет Название панели в админ-меню (по умолчанию «Панель 1»)
REMNAWAVE_PANEL_URL да URL панели — сюда же идут запросы API (/api/...). Пример: https://panel.example.com (док)
REMNAWAVE_API_TOKEN да Токен из Remnawave Settings → API Tokens, заголовок Authorization: Bearer
CADDY_AUTH_API_TOKEN нет X-Api-Key, если включён Caddy with security (как в оф. .env subscription-page)
REMNAWAVE_SUBSCRIPTION_URL нет Опционально: домен Subscription Page (sub.*), отдельная проверка
DATABASE_URL да PostgreSQL, в compose: postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable
TRIAL_USER_DAYS нет Срок trial-конфига для /config (по умолчанию 1)
DEFAULT_USER_DAYS нет Срок при создании админом /admin user (по умолчанию 1)
DEFAULT_EXTERNAL_SQUAD_UUID нет External squad по умолчанию при быстром создании
DEFAULT_INTERNAL_SQUAD_UUIDS нет Internal squads через запятую
BOT_DEBUG нет true — подробные логи Telegram API (только для отладки)

Команды для пользователей

  • /start — приветствие и кнопка получения конфига
  • /config — создать пользователя в Remnawave на TRIAL_USER_DAYS (если активная подписка уже есть — вернёт существующую ссылку)

Нужны DEFAULT_EXTERNAL_SQUAD_UUID и DEFAULT_INTERNAL_SQUAD_UUIDS — те же сквады, что для быстрого /admin user.

Админ-меню в боте

Только пользователь с TELEGRAM_ADMIN_ID:

  • /admin — админ-меню (панель 1, Remnawave)
  • /admin check — полная проверка: веб панели, API (статистика, users, nodes), подписка (settings + API), страница подписки
  • /admin config — конфиг панели в боте
  • /admin user — мастер создания пользователя в Remnawave + назначение сквадов
  • /admin user <логин> [дней] — быстрое создание (сквады из DEFAULT_* в .env)
  • /admin squads — список internal/external squads
  • /admin assign <логин> — назначить сквады существующему пользователю
  • Кнопки: «Создать пользователя», «Сквады», «Проверить панель», «Конфиг»

Remnawave API (по официальной документации)

Как в Bundled Subscription Page:

REMNAWAVE_PANEL_URL=https://panel.example.com
REMNAWAVE_API_TOKEN=API_TOKEN_FROM_REMNAWAVE
CADDY_AUTH_API_TOKEN=
  • Отдельного REMNAWAVE_API_URL нет — API всегда на том же хосте, что и панель: {REMNAWAVE_PANEL_URL}/api/...
  • Авторизация: Authorization: Bearer {REMNAWAVE_API_TOKEN}
  • Внутри Docker-сети Remnawave: REMNAWAVE_PANEL_URL=http://remnawave:3000
  • Домен sub.* — это Subscription Page, не панель; для API используйте panel.*

Пример проверки с сервера:

curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $REMNAWAVE_API_TOKEN" \
  "$REMNAWAVE_PANEL_URL/api/system/stats/recap"

Полезные команды Docker

# пересобрать образ и перезапустить
docker compose up -d --build

# логи в реальном времени
docker compose logs -f bot

# последние 100 строк логов
docker compose logs --tail=100 bot

# зайти в контейнер бота
docker compose exec bot sh

# консоль PostgreSQL
docker compose exec db psql -U tgvpn -d tgvpn

# дамп базы
docker compose exec -T db pg_dump -U tgvpn tgvpn > backup.sql

# удалить контейнеры (данные БД в volume сохранятся)
docker compose down

# удалить контейнер и неиспользуемые образы проекта
docker compose down --rmi local

Сеть и безопасность

  • Бот использует long polling: входящие запросы на ваш сервер не нужны, порты открывать не требуется.
  • Нужен только исходящий доступ к https://api.telegram.org.
  • Не коммитьте .env в git. Не публикуйте BOT_TOKEN и пароль БД.
  • PostgreSQL доступен только внутри docker-сети (порт наружу не проброшен по умолчанию).
  • Контейнер бота запускается от непривилегированного пользователя bot (UID 10001).

Если позже добавите webhook, понадобится reverse proxy (nginx/Caddy), TLS и открытый порт 443 — это описывается отдельно при появлении функции.


Устранение неполадок

BOT_TOKEN не задан / TELEGRAM_ADMIN_ID не задан

  • Проверьте, что файл .env лежит рядом с docker-compose.yml.
  • В .env нет пробелов вокруг =: BOT_TOKEN=123:ABC, не BOT_TOKEN = ....
  • TELEGRAM_ADMIN_ID — только цифры, без @username.
  • После правки: docker compose up -d --force-recreate.

Authentication failed / 401 Unauthorized

  • Неверный или отозванный токен. Создайте новый в @BotFather → /token → обновите .envdocker compose up -d --force-recreate.

Бот не отвечает в Telegram

docker compose ps          # State должен быть running
docker compose logs bot    # ошибки сети, токена
  • Убедитесь, что на сервере нет блокировки Telegram (firewall, провайдер).
  • Проверьте: curl -I https://api.telegram.org с хоста.

API возвращает 502, веб-панель — 200

Частая причина: в REMNAWAVE_PANEL_URL указан домен страницы подписки (sub.example.com), а не админ-панели (panel.example.com).

  1. Укажите URL панели (не sub): REMNAWAVE_PANEL_URL=https://panel.example.com
  2. Токен API: REMNAWAVE_API_TOKEN=... (Settings → API Tokens)
  3. Страницу подписки — опционально: REMNAWAVE_SUBSCRIPTION_URL=https://sub.example.com
  4. Проверьте на сервере: docker compose ps (Remnawave Panel запущен), логи reverse proxy

Контейнер постоянно перезапускается

docker compose logs --tail=200 bot

Чаще всего — пустой BOT_TOKEN или ошибка при старте.

DATABASE_URL не задан / ошибки PostgreSQL

См. раздел PostgreSQL → Ошибки.

Нет доступа к docker без sudo

sudo usermod -aG docker $USER
# перелогиньтесь

Структура проекта

tgvpn/
├── main.go
├── internal/
│   ├── bot/             # Telegram, админ-меню, создание пользователей
│   ├── config/          # переменные окружения
│   ├── db/              # PostgreSQL: подключение, миграции, репозитории
│   │   └── migrations/  # SQL-миграции (001_init.sql)
│   └── remnawave/       # API панели (users, squads)
├── Dockerfile           # multi-stage сборка
├── install.sh           # интерактивный установщик на сервер
├── docker-compose.yml   # bot + PostgreSQL (volume pgdata)
├── .env.example         # шаблон переменных
├── .dockerignore
├── go.mod / go.sum
├── CHANGELOG.md
└── README.md

Репозиторий

Укажите URL вашего приватного git-репозитория при клонировании.

S
Description
No description provided
Readme 189 KiB
v0.20.0 Latest
2026-05-20 22:02:12 +00:00
Languages
Go 84.8%
Shell 14.6%
Dockerfile 0.6%