Telegram-бот для выдачи и управления ключами AmneziaWG
Заявки на доступ, выдача ключей в один тап, автономные ключи, статистика трафика и рассылки — всё из чата Telegram.
- 📝 Заявки на доступ — пользователь жмёт
/start, админ одобряет кнопкой - 🚀 Онбординг в один шаг —
/onboardодобряет и сразу выдаёт ключ - 🔑 Самообслуживание — выдача ключа, перечеканка, повторная отправка конфига и QR
- 🎁 Автономные ключи —
/keygenдля тех, кто не может зайти в бота - 📊 Статистика трафика — из
awg show, по каждому peer - 📢 Рассылки — всем одобренным или адресно, с вложениями
- 🔧 Обслуживание — починка PSK, удаление peer, отзыв доступа
- 🐳 Docker-native — управляет AWG через
docker exec, автодеплой через Watchtower
- Как это работает
- Скриншоты
- Требования
- Быстрый старт (Docker)
- Переменные окружения
- Продакшен: Docker Hub + Watchtower
- Запуск без Docker
- Команды бота
- Структура проекта
- Релизы и разработка
- Troubleshooting
- Пользователь пишет боту
/start— отправляется заявка на доступ - Администратор получает уведомление с кнопками «Одобрить» / «Отклонить»
- После одобрения пользователь может:
- Получить ключ — один раз, создаёт peer на сервере
- Перечеканить ключ — сгенерировать новую пару ключей (старый перестаёт работать)
- Показать конфиг — повторно отправить текущий конфиг и QR-код
Для тех, кто не может зайти в бота (заблокирован, нет Telegram и т.п.), администратор создаёт автономный ключ командой /keygen <метка>. Бот присылает конфиг и .vpn-файл прямо в чат админу — дальше его можно передать получателю любым способом. Такие ключи не привязаны к Telegram-аккаунту и хранятся только в конфиге сервера (peer manual_<метка>).
📷 Скриншоты пока не добавлены — см. docs/screenshots/, чтобы их подложить.
- Сервер с Docker
- Запущенный контейнер AmneziaWG (
amnezia-awg2) - Telegram Bot Token от @BotFather
Боту нужен доступ к Docker socket, чтобы выполнять docker exec в контейнер AWG. Самый простой способ — запустить бота тоже в Docker и пробросить /var/run/docker.sock.
# На сервере, где уже работает amnezia-awg2
cd /opt
git clone https://github.com/dato-dev/awgkeygen.git
cd awgkeygencp .env.example .env
nano .envМинимально нужно задать BOT_TOKEN, ADMIN_IDS и SERVER_ENDPOINT —
полная таблица в разделе Переменные окружения.
Узнать свой Telegram ID: @userinfobot.
docker ps | grep amnezia-awg2docker compose up -d --builddocker compose logs -fДолжно появиться: AWG container 'amnezia-awg2' is reachable и Polling started.
docker compose restart # перезапуск
docker compose down # остановка
docker compose up -d --build # обновление после git pull| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
BOT_TOKEN |
✅ | — | Токен Telegram-бота от @BotFather |
ADMIN_IDS |
✅ | — | Telegram ID администраторов через запятую |
SERVER_ENDPOINT |
✅ | — | Публичный IP или домен сервера (для клиентского конфига) |
DOCKER_CONTAINER |
amnezia-awg2 |
Имя Docker-контейнера AWG | |
AWG_CONFIG_PATH |
/opt/amnezia/awg/awg0.conf |
Путь к серверному конфигу внутри контейнера | |
AWG_PORT |
из awg0.conf |
UDP-порт AWG | |
DNS_PRIMARY |
1.1.1.1 |
Основной DNS для клиентов | |
DNS_SECONDARY |
1.0.0.1 |
Резервный DNS | |
AWG_CONTAINER_TYPE |
amnezia-awg2 |
Тип контейнера в vpn:// URI |
|
VPN_DESCRIPTION |
AWG Server |
Название подключения в AmneziaVPN | |
AWG_MTU |
1280 |
MTU в vpn:// URI |
|
DATABASE_PATH |
./data/bot.db |
Путь к SQLite-базе | |
LOG_LEVEL |
INFO |
Уровень логов: DEBUG / INFO / WARNING |
На сервере используйте docker-compose-prod.yml. Образ всегда dato1/awgkeygen:latest — версию в compose менять не нужно.
Один и тот же образ (один digest) публикуется в два реестра — выбирайте любой:
| Реестр | Образ |
|---|---|
| Docker Hub | dato1/awgkeygen |
| GitHub Container Registry | ghcr.io/dato-dev/awgkeygen |
GHCR-пакет публичный — docker pull работает без логина. Для приватного
доступа: echo $GITHUB_TOKEN | docker login ghcr.io -u <user> --password-stdin.
Чтобы тянуть из GHCR, раскомментируйте соответствующую строку image: в
docker-compose-prod.yml.
push в main → GitHub Actions публикует :latest в Docker Hub
↓
Watchtower на сервере (каждые 5 мин) видит новый digest
↓
docker pull + перезапуск awgkeygen-bot
Watchtower обновляет только контейнеры с label watchtower.enable=true. Контейнер amnezia-awg2 не затрагивается.
cd /opt/awgkeygen
cp .env.example .env # если ещё не настроен
docker compose -f docker-compose-prod.yml up -dЕсли не хотите отдельный контейнер — закомментируйте сервис watchtower в compose и добавьте в cron:
# каждые 5 минут
*/5 * * * * DEPLOY_PATH=/opt/awgkeygen /opt/awgkeygen/scripts/docker-watchdog.sh >> /var/log/awgkeygen-watchdog.log 2>&1Скрипт сравнивает digest образа на Hub и локально; при изменении делает compose up -d.
docker compose -f docker-compose-prod.yml down
# в compose временно укажите конкретный тег: image: dato1/awgkeygen:1.3.8
docker compose -f docker-compose-prod.yml up -dКаждый релиз доступен отдельным тегом
dato1/awgkeygen:X.Y.Z— удобно для отката.
Если не хотите контейнеризировать сам бот. Зависимости управляются через
uv (pyproject.toml + uv.lock):
cd /opt/awgkeygen
# Установить uv (если ещё нет)
curl -LsSf https://astral.sh/uv/install.sh | sh
uv sync # создаст .venv и поставит зависимости из uv.lock
cp .env.example .env
# Отредактируйте .env
uv run python -m bot.mainsudo cp awgkeygen.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now awgkeygen
sudo systemctl status awgkeygen| Команда | Описание |
|---|---|
/start |
Главное меню |
/help |
Справка и ссылки на AmneziaVPN |
/status |
Статус доступа и ключа |
/key |
Получить VPN-ключ |
/remint |
Перечеканить ключ |
/config |
Показать текущий конфиг |
| Команда | Описание |
|---|---|
/admin |
Панель администратора |
/onboard <id> |
Одобрить + выдать ключ (одной командой) |
/pending |
Заявки на доступ |
/users |
Все пользователи |
/user <id> |
Карточка + трафик + кнопки копирования |
/traffic |
Трафик всех peers (из awg show) |
/traffic <id> |
Трафик конкретного пользователя |
/approve <id> |
Одобрить |
/reject <id> |
Отклонить |
/revoke <id> |
Отозвать доступ |
/genkey <id> |
Выдать ключ |
/genkey <id> remint |
Перечеканить |
/delkey <id> |
Удалить ключ с сервера |
/repair <id> |
Починить PSK на сервере |
/resync |
Сверить базу с конфигом сервера (после переноса/переустановки) |
/keygen <метка> |
Автономный ключ для выдачи вручную (метка опциональна) |
/keys |
Список автономных ключей |
/keydel <метка> |
Удалить автономный ключ |
/notify_user <id> текст |
Уведомление одному пользователю (можно с файлом) |
/notify_all текст |
Рассылка всем одобренным (можно с файлом) |
Уведомления о новых заявках содержат кнопки — в том числе «📋 /onboard» для копирования команды в буфер.
bot/
├── main.py # Точка входа, регистрация команд
├── config.py # Настройки из .env
├── database.py # SQLite: пользователи и статусы
├── keyboards.py # Inline-клавиатуры Telegram
├── middleware.py # Логирование апдейтов
├── texts.py # Тексты сообщений (HTML)
├── utils.py # Генерация QR-кодов
├── version.py # Версия из файла VERSION
├── awg/
│ ├── config_parser.py # Парсер awg0.conf
│ ├── manager.py # Управление ключами через docker exec
│ ├── stats.py # Парсинг awg show (трафик)
│ └── vpnuri.py # Генерация vpn:// URI
├── handlers/
│ ├── user.py # Хендлеры пользователей
│ └── admin.py # Хендлеры администратора
└── services/
├── keys.py # Доставка ключей и QR
├── admin_actions.py # Бизнес-логика админ-действий
└── notify.py # Рассылки и уведомления
Версионирование и CHANGELOG.md автоматизированы через
release-please на основе
Conventional Commits — файл VERSION
вручную не правится. Подробнее в CONTRIBUTING.md.
коммиты feat:/fix: в main → release-please открывает release-PR
→ мёрж PR бампит VERSION + CHANGELOG, создаёт тег vX.Y.Z и Release
→ сборка образа dato1/awgkeygen:X.Y.Z + :latest
Секреты для публикации образа (Settings → Secrets → Actions):
DOCKERHUB_USERNAME и DOCKERHUB_TOKEN.
История изменений — в CHANGELOG.md. Планы — в ROADMAP.md.
- Бот и
amnezia-awg2должны работать на одном сервере (или бот должен иметь доступ к Docker socket этого сервера) - Каждому пользователю соответствует peer
tg_<telegram_id>вawg0.conf - Автономным ключам (
/keygen) соответствует peermanual_<метка>— без привязки к Telegram-аккаунту - При перечеканке старый ключ немедленно перестаёт работать
- Конфиг и QR-код совместимы с AmneziaWG клиентом
Контейнер 'amnezia-awg2' не найден
docker ps -a | grep awg # проверьте имя контейнера
# Если имя другое — поправьте DOCKER_CONTAINER в .envОшибка в контейнере: awg: not found
docker exec amnezia-awg2 awg --version # awg должен быть внутри AWG-контейнераБот не видит Docker (в Docker-режиме)
ls -la /var/run/docker.sock # socket должен существовать
docker compose exec awgkeygen-bot docker ps # тест изнутри бота