Личный кабинет (WEBSITE)
Веб-кабинет для клиентов: просмотр подписки, оплата, управление устройствами. Модуль уже находится в файлах бота, но требует отдельной настройки и запуска.
/root/bot/website/. Ничего скачивать дополнительно не нужно. Требуется только настроить .env, создать systemd-сервис и поднять прокси.
Мастер настройки — подставьте свои данные
Заполните IP, домен и бота один раз — значения автоматически подставятся во все примеры ниже. Всё хранится только в браузере через localStorage.
Требования
Ubuntu 24.04 · Python 3.12 · Бот ≥ 3.4.5
Ubuntu 20.04+ · Nginx · Certbot · Порты 80, 443
Настройка почты
Почта используется для отправки кодов подтверждения при входе клиентов. Поддерживаются два варианта:
Работает через HTTPS, не требует открытых портов. Регистрация: resend.com
- 1Создайте аккаунт и подтвердите домен
- 2Создайте API-ключ
- 3Укажите
RESEND_API_KEYиSMTP_FROMв.env
Используется если
RESEND_API_KEY не задан. Подходит Gmail, Яндекс, свой сервер.
- >Укажите
SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASSWORD,SMTP_FROM
SMTP_FROM должен быть на верифицированном домене. В тестовом режиме письма приходят только на ваш собственный email.Настройка .env файла
Создайте или отредактируйте файл конфигурации на сервере с ботом:
nano /root/bot/.env
# -- Сессии --------------------------------------------------------------- # Если пустой — сессии сбрасываются при каждом рестарте! # Сгенерировать: python3 -c "import secrets; print(secrets.token_hex(32))" WEBSITE_SESSION_SECRET=сгенерируйте_командой_выше # -- Администратор --------------------------------------------------------- # Секретный email для входа без кода. Если пусто — отключён. WEBSITE_ADMIN_EMAIL= # -- Почта ----------------------------------------------------------------- RESEND_API_KEY=re_xxxxxxxxxxxx SMTP_FROM=noreply@ваш-домен.ru # SMTP (используется если RESEND_API_KEY не задан) # SMTP_HOST=smtp.example.com # SMTP_PORT=465 # SMTP_USER=user@example.com # SMTP_PASSWORD=password # -- Адреса ---------------------------------------------------------------- SITE_URL=https://cabinet.ваш-домен.ru XUIWEB_INTERNAL_URL=http://127.0.0.1:8282 # -- Поддержка ------------------------------------------------------------- SUPPORT_SITE=https://t.me/ваш_бот_поддержки PRIVACY_URL= TERMS_URL= # -- Внешний вид ----------------------------------------------------------- # Тема для новых посетителей: light или dark DEFAULT_THEME=dark # -- Режим отдачи ключа ---------------------------------------------------- # happcrypto — ссылка шифруется, кнопка «Открыть в Happ» # subscription — ссылка как есть, кнопка «Скопировать» для любого клиента DEF_SUB_MODE=happcrypto # -- Лимит платёжных запросов --------------------------------------------- PAYMENT_RATE_LIMIT=3 PAYMENT_RATE_WINDOW=300 # -- Пробный период для регистраций через сайт ----------------------------- # 0 = отключено. Фактические дни берутся из настроек бота (trial_days) TRIAL_DAYS=0 BOT_INTERNAL_URL=http://127.0.0.1:8081 # -- Telegram Login Widget ------------------------------------------------- # Имя бота без @ — добавляет кнопку «Войти через Telegram» на странице входа # Требует /setdomain в BotFather BOT_USERNAME=ваш_бот # -- Yandex SmartCaptcha (опционально) ------------------------------------ YANDEX_CAPTCHA_SITE_KEY= YANDEX_CAPTCHA_SECRET_KEY= # -- Мои устройства (требует запущенного SUBPAGE) -------------------------- WEBSITE_DEVICES_ENABLED=0 # -- Deep-link кнопки «Открыть в приложении» ------------------------------ # Варианты: happ://add/ incy://add/ v2raytun://import/ ADD_LINK=happ://add/ # -- Google OAuth (опционально) -------------------------------------------- # GOOGLE_CLIENT_ID= # GOOGLE_CLIENT_SECRET= # -- Yandex OAuth (опционально) -------------------------------------------- # YANDEX_CLIENT_ID= # YANDEX_CLIENT_SECRET= # -- Отдельные реквизиты касс для сайта (опционально) --------------------- # Если не заданы — используются настройки из БД (те же что у бота) # WEBSITE_YOOKASSA_SHOP_ID= # WEBSITE_YOOKASSA_SECRET_KEY= # WEBSITE_PLATEGA_MERCHANT_ID= # WEBSITE_PLATEGA_API_SECRET= # WEBSITE_YOOMONEY_ACCOUNT= # WEBSITE_YOOMONEY_TOKEN= # WEBSITE_YOOMONEY_NOTIFICATION_SECRET= # WEBSITE_WATA_ACCESS_TOKEN= # WEBSITE_WATA_TERMINAL_PUBLIC_ID=
Справочник переменных
| Переменная | Описание | |
|---|---|---|
WEBSITE_SESSION_SECRET | Ключ подписи cookie-сессий. Без него сессии сбрасываются при каждом рестарте. | Required |
RESEND_API_KEY | API-ключ Resend для отправки email-кодов входа. | Optional |
SMTP_FROM | Email отправителя (Resend или SMTP). | Required |
SITE_URL | Публичный URL кабинета. Используется в реферальных ссылках. | Required |
XUIWEB_INTERNAL_URL | Внутренний адрес xuiweb. По умолчанию http://127.0.0.1:8282. | Optional |
SUPPORT_SITE | Ссылка на поддержку в футере сайта. | Optional |
DEFAULT_THEME | Тема для новых посетителей: light или dark. | Optional |
DEF_SUB_MODE | happcrypto — кнопка «Открыть в Happ». subscription — ссылка как есть, для любого VPN-клиента. | Optional |
PAYMENT_RATE_LIMIT | Максимум попыток создать платёж за одно окно времени. По умолчанию 3. | Optional |
PAYMENT_RATE_WINDOW | Окно лимита платежей в секундах. По умолчанию 300 = 5 минут. | Optional |
TRIAL_DAYS | Пробный период для регистраций через сайт. 0 = отключено. Кол-во дней берётся из настроек бота. | Optional |
BOT_USERNAME | Имя бота без @. Добавляет кнопку «Войти через Telegram». Требует /setdomain в BotFather. | Optional |
YANDEX_CAPTCHA_* | Yandex SmartCaptcha на странице входа. Если ключи пустые — капча не показывается. | Optional |
GOOGLE_CLIENT_* | OAuth-вход через Google. Callback: https://ваш_домен/auth/google/callback. | Optional |
YANDEX_CLIENT_* | OAuth-вход через Яндекс. Callback: https://ваш_домен/auth/yandex/callback. | Optional |
WEBSITE_DEVICES_ENABLED | Показывает раздел «Мои устройства» в кабинете. 1 = вкл. Требует запущенного SUBPAGE. | Optional |
ADD_LINK | Deep-link кнопки «Открыть в приложении». Работает только при DEF_SUB_MODE=subscription. | Optional |
Виртуальное окружение и зависимости
# Переходим в папку сайта cd /root/bot/website # Создаём виртуальное окружение python3 -m venv venv # Активируем source venv/bin/activate # Устанавливаем зависимости pip install -r /root/bot/service/website.txt # Или из локального requirements.txt pip install -r requirements.txt
pytailwindcss уже включён в requirements.txt — устанавливается автоматически. Сборка CSS запускается при каждом старте сервиса.Systemd сервис
Создайте файл сервиса на сервере с ботом. Замените XX.XX.XX.XX на реальный IP вашего проксирующего сервера.
nano /etc/systemd/system/website.service
[Unit]
Description=VPN Website
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/root/bot/website
ExecStart=/root/bot/website/venv/bin/uvicorn run:app \
--host 0.0.0.0 \
--port 3012 \
--log-level info \
--proxy-headers \
--forwarded-allow-ips=XX.XX.XX.XX
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
systemctl daemon-reload systemctl enable website systemctl start website systemctl status website
--forwarded-allow-ips должен содержать только IP вашего проксирующего сервера. Если указать * — любой сможет подделать свой IP через заголовок X-Forwarded-For.Настройка UFW (файрвол)
Выполните на сервере с ботом. Порт 3012 открываем только для проксирующего сервера.
# SSH — обязательно до ufw enable! ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp # Порт сайта — только с IP проксирующего сервера ufw allow from XX.XX.XX.XX to any port 3012 ufw --force enable ufw status verbose
ufw allow 22/tcp до ufw enable, иначе SSH-соединение оборвётся и доступ к серверу будет потерян.Проксирующий сервер — Nginx + SSL
Выполняется на отдельном VPS. Замените cabinet.ваш-домен.ru и IP-бота на реальные значения.
Установка Nginx и Certbot
apt update && apt install -y nginx certbot python3-certbot-nginx
Получение SSL-сертификата
certbot certonly --nginx -d cabinet.ваш-домен.ru
Конфиг Nginx
nano /etc/nginx/conf.d/website.conf
server {
listen 80;
server_name cabinet.ваш-домен.ru;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name cabinet.ваш-домен.ru;
ssl_certificate /etc/letsencrypt/live/cabinet.ваш-домен.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cabinet.ваш-домен.ru/privkey.pem;
location / {
proxy_pass http://IP-бота:3012;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
}
}
nginx -t && systemctl reload nginx
Активация в боте
- 1Откройте веб-админку > Настройки > Основные
- 2Найдите параметр
show_website_buttonи установите значение1 - 3Сохраните настройки
Проверка работоспособности
systemctl status website
journalctl -u website -f
Установка завершена
Вход через Telegram (виджет)
Опционально. Добавляет кнопку «Войти через Telegram» на странице входа — пользователи могут авторизоваться без email.
/setdomain > выберите бота > введите домен без https:// и слэша Пример: cabinet.ваш-домен.ru
BOT_USERNAME=myvpnbot
SITE_URL. Виджет работает только по HTTPS.Настройка OAuth входа
Опционально: можно добавить вход через Google и Яндекс. После получения ключей добавьте их в /root/bot/.env и перезапустите website.
Google OAuth
- 1Google Cloud Console → APIs & Services → Credentials → OAuth client ID.
- 2Тип: Web application.
- 3Authorized redirect URI:
https://ваш_домен/auth/google/callback - 4Добавьте
GOOGLE_CLIENT_IDиGOOGLE_CLIENT_SECRETв.env.
Яндекс OAuth
- 1oauth.yandex.ru → Создать приложение.
- 2Платформа: Веб-сервисы, права:
login:email,login:info. - 3Callback URI:
https://ваш_домен/auth/yandex/callback - 4Добавьте
YANDEX_CLIENT_IDиYANDEX_CLIENT_SECRETв.env.
systemctl restart website journalctl -u website -f