Expand README with PostgreSQL documentation and updated setup guide
This commit is contained in:
@@ -2,7 +2,18 @@
|
||||
|
||||
**Версия:** [0.20.0](CHANGELOG.md)
|
||||
|
||||
Telegram-бот на Go (базовое приветствие; далее — VPN-функции).
|
||||
Telegram-бот на Go для управления VPN через панель [Remnawave](https://docs.rw/): проверка панели, создание пользователей, назначение сквадов. Данные хранятся в **PostgreSQL**.
|
||||
|
||||
## Содержание
|
||||
|
||||
- [Требования](#требования)
|
||||
- [Быстрый старт](#быстрый-старт-docker-compose)
|
||||
- [PostgreSQL](#postgresql)
|
||||
- [Развёртывание на VPS](#развёртывание-на-vps-linux)
|
||||
- [Обновление бота](#обновление-бота)
|
||||
- [Переменные окружения](#переменные-окружения)
|
||||
- [Админ-меню](#админ-меню-в-боте)
|
||||
- [Устранение неполадок](#устранение-неполадок)
|
||||
|
||||
## Требования
|
||||
|
||||
@@ -43,12 +54,16 @@ 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`). Бот стартует только после готовности БД.
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
@@ -56,23 +71,164 @@ docker compose up -d --build
|
||||
### 4. Проверка
|
||||
|
||||
```bash
|
||||
# логи (должно быть: «бот @имя_бота запущен»)
|
||||
docker compose logs -f bot
|
||||
|
||||
# статус контейнера
|
||||
# статус (db — healthy, bot — running)
|
||||
docker compose ps
|
||||
|
||||
# логи бота (должно быть: «postgres ok», «бот @имя запущен»)
|
||||
docker compose logs --tail=30 bot
|
||||
|
||||
# логи PostgreSQL
|
||||
docker compose logs --tail=20 db
|
||||
```
|
||||
|
||||
В Telegram откройте бота и отправьте `/start`.
|
||||
В Telegram: `/start`, от админа — `/admin squads`, `/admin user`.
|
||||
|
||||
### 5. Остановка
|
||||
|
||||
```bash
|
||||
# остановить контейнеры (данные БД сохраняются в 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
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db: # PostgreSQL 16, volume pgdata
|
||||
bot: # ждёт healthy у db, затем стартует
|
||||
```
|
||||
|
||||
Параметры по умолчанию (см. `docker-compose.yml`):
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Хост (внутри compose) | `db` |
|
||||
| Порт | `5432` |
|
||||
| База | `tgvpn` |
|
||||
| Пользователь | `tgvpn` |
|
||||
| Пароль | `tgvpn` |
|
||||
|
||||
Строка подключения для бота:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable
|
||||
```
|
||||
|
||||
Формат URL (общий вид):
|
||||
|
||||
```
|
||||
postgres://USER:PASSWORD@HOST:PORT/DATABASE?sslmode=disable
|
||||
```
|
||||
|
||||
### Подключение к БД вручную
|
||||
|
||||
Из каталога проекта:
|
||||
|
||||
```bash
|
||||
# интерактивная консоль psql внутри контейнера
|
||||
docker compose exec db psql -U tgvpn -d tgvpn
|
||||
```
|
||||
|
||||
Полезные запросы:
|
||||
|
||||
```sql
|
||||
-- все 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`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change_me_strong}
|
||||
```
|
||||
|
||||
2. Обновите `DATABASE_URL` в `.env` бота с тем же паролем.
|
||||
|
||||
3. Пересоздайте стек:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgres://user:password@postgres.example.com:5432/tgvpn?sslmode=require
|
||||
```
|
||||
|
||||
3. В `docker-compose.yml` закомментируйте или удалите сервис `db` и `depends_on` у `bot`.
|
||||
4. Убедитесь, что с хоста бота есть сетевой доступ к порту `5432`.
|
||||
|
||||
### Резервное копирование
|
||||
|
||||
```bash
|
||||
# дамп в файл (дата в имени)
|
||||
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 для ежедневных дампов.
|
||||
|
||||
### Проверка после деплоя
|
||||
|
||||
```bash
|
||||
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.
|
||||
@@ -126,7 +282,9 @@ cp .env.example .env
|
||||
nano .env # или vim / vi
|
||||
```
|
||||
|
||||
Укажите реальный `BOT_TOKEN`. Для продакшена оставьте `BOT_DEBUG=false`.
|
||||
Укажите реальный `BOT_TOKEN`, `DATABASE_URL` (в compose для VPS обычно оставляют `postgres://tgvpn:...@db:5432/...`), Remnawave и при необходимости UUID сквадов (`DEFAULT_*`).
|
||||
|
||||
Для продакшена смените пароль PostgreSQL — см. [PostgreSQL → Продакшен](#продакшен-смена-пароля-бд).
|
||||
|
||||
Права на секреты:
|
||||
|
||||
@@ -145,6 +303,7 @@ docker compose up -d --build
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs --tail=50 bot
|
||||
docker compose logs --tail=20 db
|
||||
```
|
||||
|
||||
### Шаг 6. Автозапуск после перезагрузки сервера
|
||||
@@ -285,9 +444,31 @@ docker compose logs -f bot
|
||||
|
||||
## Локальная разработка (без Docker)
|
||||
|
||||
Нужен запущенный PostgreSQL 16+ (локально или только контейнер БД):
|
||||
|
||||
```bash
|
||||
# вариант: только БД в Docker, бот на хосте
|
||||
docker compose up -d db
|
||||
```
|
||||
|
||||
В `.env` для локального бота укажите:
|
||||
|
||||
```env
|
||||
DATABASE_URL=postgres://tgvpn:tgvpn@localhost:5432/tgvpn?sslmode=disable
|
||||
```
|
||||
|
||||
Проброс порта в `docker-compose.yml` (если ещё нет):
|
||||
|
||||
```yaml
|
||||
db:
|
||||
ports:
|
||||
- "5432:5432"
|
||||
```
|
||||
|
||||
Запуск:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# укажите BOT_TOKEN в .env
|
||||
go run .
|
||||
```
|
||||
|
||||
@@ -369,10 +550,16 @@ 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
|
||||
|
||||
# удалить контейнер и неиспользуемые образы проекта
|
||||
@@ -385,8 +572,9 @@ docker compose down --rmi local
|
||||
|
||||
- Бот использует **long polling**: входящие запросы на ваш сервер **не нужны**, порты открывать не требуется.
|
||||
- Нужен только **исходящий** доступ к `https://api.telegram.org`.
|
||||
- Не коммитьте `.env` в git. Не публикуйте `BOT_TOKEN`.
|
||||
- Контейнер запускается от непривилегированного пользователя `bot` (UID 10001).
|
||||
- Не коммитьте `.env` в git. Не публикуйте `BOT_TOKEN` и пароль БД.
|
||||
- PostgreSQL доступен **только внутри docker-сети** (порт наружу не проброшен по умолчанию).
|
||||
- Контейнер бота запускается от непривилегированного пользователя `bot` (UID 10001).
|
||||
|
||||
Если позже добавите **webhook**, понадобится reverse proxy (nginx/Caddy), TLS и открытый порт 443 — это описывается отдельно при появлении функции.
|
||||
|
||||
@@ -432,6 +620,10 @@ docker compose logs --tail=200 bot
|
||||
|
||||
Чаще всего — пустой `BOT_TOKEN` или ошибка при старте.
|
||||
|
||||
### `DATABASE_URL не задан` / ошибки PostgreSQL
|
||||
|
||||
См. раздел [PostgreSQL → Ошибки](#ошибки-postgresql).
|
||||
|
||||
### Нет доступа к `docker` без sudo
|
||||
|
||||
```bash
|
||||
@@ -449,10 +641,11 @@ tgvpn/
|
||||
├── internal/
|
||||
│ ├── bot/ # Telegram, админ-меню, создание пользователей
|
||||
│ ├── config/ # переменные окружения
|
||||
│ ├── db/ # PostgreSQL, миграции, мастер админа
|
||||
│ ├── db/ # PostgreSQL: подключение, миграции, репозитории
|
||||
│ │ └── migrations/ # SQL-миграции (001_init.sql)
|
||||
│ └── remnawave/ # API панели (users, squads)
|
||||
├── Dockerfile # multi-stage сборка
|
||||
├── docker-compose.yml # оркестрация
|
||||
├── docker-compose.yml # bot + PostgreSQL (volume pgdata)
|
||||
├── .env.example # шаблон переменных
|
||||
├── .dockerignore
|
||||
├── go.mod / go.sum
|
||||
|
||||
Reference in New Issue
Block a user