An asynchronous Telegram bot and Mini App backend for selling, provisioning, and managing VPN subscriptions through one or more 3x-ui panels.
The project combines a Telegram Stars wallet, tariff management, multi-device subscriptions, automatic renewal, backend load distribution, and an administrative dashboard in one Python application.
This repository is a technical portfolio project. Configure your own infrastructure, credentials, branding, security controls, and legal requirements before production use.
- Telegram bot entry point with a Mini App button;
- wallet top-ups through Telegram Stars;
- tariff selection and subscription purchase;
- multiple VPN devices per user;
- subscription and JSON URLs;
- traffic and expiration information;
- manual renewal and optional auto-renewal;
- platform metadata for connected devices.
- single-panel and multi-panel 3x-ui configurations;
- weighted least-load backend selection;
- VLESS client creation through the 3x-ui API;
- subscription URL and fallback config generation;
- traffic and client IP inspection;
- subscription extension and deactivation;
- configurable server, port, inbound, title, weight, and availability.
- persistent wallet and transaction history;
- Telegram Stars invoice links;
- idempotent payment confirmation;
- transactional balance updates;
- balance checks before purchase;
- automatic refund when VPN provisioning fails;
- configurable tariffs, durations, prices, and traffic limits.
- overview metrics for users, devices, balances, and transactions;
- tariff create, update, disable, and delete operations;
- user and device search;
- payment and subscription monitoring;
- manual balance adjustments;
- subscription extension and deactivation;
- traffic-sharing indicators based on observed client IPs;
- product analytics by day, tariff, and platform.
- Telegram polling and aiohttp WebApp server in one asyncio process;
- async PostgreSQL pool with asyncpg;
- automatic schema and default tariff initialization;
- background auto-renewal checks;
- Nginx reverse-proxy example;
- database bootstrap script;
- lightweight deployment restart helper.
flowchart LR
U[Telegram user] --> TG[Telegram Bot API]
TG --> B[aiogram bot]
B --> WA[Telegram Mini App]
WA --> API[aiohttp WebApp API]
B --> ST[Telegram Stars]
ST --> B
B --> DB[(PostgreSQL)]
API --> DB
API --> REG[3x-ui backend registry]
REG --> P1[3x-ui panel A]
REG --> P2[3x-ui panel B]
REG --> PN[3x-ui panel N]
API --> AR[Auto-renewal worker]
AR --> DB
AR --> REG
ADMIN[Admin dashboard] --> API
The bot handles Telegram events and successful Stars payments. The WebApp API manages wallets, tariffs, subscriptions, and administration. PostgreSQL stores user, transaction, tariff, and device state, while 3x-ui remains the VPN control plane.
| Area | Technologies |
|---|---|
| Runtime | Python 3.11+ |
| Telegram | aiogram 3, Telegram Mini Apps, Telegram Stars |
| HTTP server/client | aiohttp, httpx |
| Database | PostgreSQL, asyncpg |
| VPN control plane | 3x-ui API, VLESS |
| Configuration | python-dotenv, dataclasses |
| Infrastructure | Nginx, Linux, Bash |
.
+-- app/
| +-- bot/
| | +-- handlers/ # Telegram commands and payment updates
| | +-- main.py # Bot and WebApp lifecycle
| +-- services/
| | +-- backends.py # Multi-panel selection
| | +-- subscriptions.py
| | +-- tariffs.py
| | +-- users.py
| | +-- wallet.py
| +-- webapp/
| | +-- server.py # Customer and admin WebApp API
| +-- config.py
| +-- db.py
| +-- threexui_client.py
+-- deploy/
| +-- nginx-webapp.conf.example
+-- scripts/
| +-- create_database.py
+-- .env.example
+-- requirements.txt
+-- restart.sh
+-- README.md
- The WebApp creates a pending wallet transaction.
- The bot creates a Telegram Stars invoice link.
- Telegram sends a successful payment update.
- The transaction is locked and verified in PostgreSQL.
- The user balance is increased exactly once.
- The user selects a tariff and device platform.
- The price is deducted in a database transaction.
- The least-loaded enabled 3x-ui backend is selected.
- A VLESS client is created in the selected inbound.
- Subscription metadata is persisted in PostgreSQL.
- If provisioning fails, the wallet charge is refunded.
Every five minutes, the background worker selects subscriptions that expire within 24 hours and have auto-renewal enabled. It charges the saved tariff price, extends the client in 3x-ui, updates the database, and refunds the charge if renewal fails.
- Python 3.11+
- PostgreSQL
- a Telegram bot token from @BotFather
- a running 3x-ui panel
- a public HTTPS domain for the Telegram Mini App
git clone https://github.com/nGrUnD/vpn_template.git
cd vpn_template
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .envOn Windows:
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txtBOT_TOKEN=replace-with-your-bot-token
BOT_ADMIN_IDS=123456789
DATABASE_URL=postgresql://vpn_app:strong-password@localhost:5432/vpn_app
THREEXUI_BASE_URL=https://panel.example.com
THREEXUI_USERNAME=panel-user
THREEXUI_PASSWORD=strong-panel-password
THREEXUI_INBOUND_ID=1
THREEXUI_TITLE=Primary
VLESS_SERVER=vpn.example.com
VLESS_PORT=443
WEBAPP_URL=https://app.example.com
WEBAPP_PORT=8081Use THREEXUI_BACKENDS_JSON instead of the single-panel variables:
THREEXUI_BACKENDS_JSON=[{"key":"nl","title":"Netherlands","base_url":"https://nl-panel.example.com","username":"admin","password":"secret","vless_server":"nl.example.com","vless_port":443,"inbound_id":1,"weight":1,"enabled":true},{"key":"de","title":"Germany","base_url":"https://de-panel.example.com","username":"admin","password":"secret","vless_server":"de.example.com","vless_port":443,"inbound_id":1,"weight":2,"enabled":true}]
THREEXUI_DEFAULT_KEY=nlNew subscriptions are assigned using the number of active devices divided by backend weight.
Create the database manually or use the included helper:
export PG_SUPER_DSN='postgresql://postgres:superuser-password@localhost:5432/postgres'
export RACCASTER_DB_NAME='vpn_app'
export RACCASTER_DB_USER='vpn_app'
export RACCASTER_DB_PASSWORD='strong-password'
python scripts/create_database.pyTables and default tariffs are initialized during application startup.
python -m app.bot.mainThe process starts:
- Telegram long polling;
- the WebApp HTTP server on WEBAPP_PORT;
- the subscription auto-renewal loop.
Telegram Mini Apps require HTTPS. Use the included Nginx example as a starting point:
sudo cp deploy/nginx-webapp.conf.example /etc/nginx/sites-available/vpn-webapp
sudo ln -s /etc/nginx/sites-available/vpn-webapp /etc/nginx/sites-enabled/vpn-webapp
sudo nginx -t
sudo systemctl reload nginxReplace the domain and upstream port, then issue a TLS certificate and set WEBAPP_URL to the public HTTPS address.
Health check:
GET /health
The application maintains four main entities:
| Entity | Purpose |
|---|---|
| users | Telegram profile and Stars wallet balance |
| subscriptions | VPN clients, backend assignment, tariff snapshot, and expiration |
| tariffs | duration, Stars price, traffic allowance, badge, and availability |
| wallet_transactions | top-ups, purchases, refunds, and admin adjustments |
Wallet spending and refunds use PostgreSQL transactions to keep balance and transaction history consistent.
- never commit .env, bot tokens, database passwords, or 3x-ui credentials;
- validate Telegram Mini App init data before exposing user or admin operations publicly;
- do not trust a client-provided Telegram ID without cryptographic verification;
- serve the WebApp only through HTTPS;
- restrict PostgreSQL and the internal WebApp port with a firewall;
- use a dedicated, least-privileged database role;
- put administrative actions behind verified authentication and authorization;
- rotate any credential that has ever been committed or shared publicly.
Semen Teneshev - Python Backend Developer
GitHub: @nGrUnD