Установка

Личный кабинет (WEBSITE)

Веб-кабинет для клиентов: просмотр подписки, оплата, управление устройствами. Модуль уже находится в файлах бота, но требует отдельной настройки и запуска.

Личный кабинет
RM-Only 1.5+ Nginx + SSL ~20 минут
💡
Файлы модуля уже есть в папке бота — /root/bot/website/. Ничего скачивать дополнительно не нужно. Требуется только настроить .env, создать systemd-сервис и поднять прокси.
⚠️
Платёжные системы. Технически бот и сайт могут работать с одними ключами, но сами кассы это запрещают: один магазин нельзя использовать одновременно в Telegram и на сайте — чаще всего это касается YooKassa (ЮKassa). За нарушение правил провайдер может отозвать ключи.
  • Для сайта заведите отдельный магазин и укажите его ключи в /root/bot/.env с префиксом WEBSITE_* (см. блок ниже). Если переменные пустые — сайт берёт те же реквизиты из веб-админки, что и бот.
  • Для отдельного магазина в кабинете YooKassa / Platega / YooMoney укажите URL webhook такой же, как в веб-админке: Настройки → Основные → Методы оплаты (полный адрес на карточке шлюза).
  • Не указывайте домен личного кабинета (SITE_URL) — сайт не принимает webhook'и платежей. Их обрабатывает бот на домене connect_page_url.

Подробнее о шлюзах и webhook — в разделе Методы оплат.

⚙️

Мастер настройки — подставьте свои данные

Заполните IP, домен и бота один раз — значения автоматически подставятся во все примеры ниже. Всё хранится только в браузере через localStorage.

Подставленные значения в коде подсвечены зелёным.
1

Требования

Сервер с ботом (основной)
Ubuntu 24.04 · Python 3.12 · RM-Only 1.5+
Проксирующий сервер (отдельный VPS)
Ubuntu 20.04+ · Nginx · Certbot · Порты 80, 443
⚠️
Важно: WEBSITE нельзя разворачивать на одном сервере с ботом без прокси. Реальный IP бота должен быть скрыт — все запросы клиентов идут через проксирующий сервер, который перенаправляет их на бота.
💡
Для домена создайте A-запись, указывающую на IP проксирующего сервера, а не на сервер с ботом.
2

Настройка почты

Почта используется для отправки кодов подтверждения при входе клиентов. Поддерживаются два варианта:

Resend API (рекомендуется)
Работает через HTTPS, не требует открытых портов. Регистрация: resend.com
  • 1Создайте аккаунт и подтвердите домен
  • 2Создайте API-ключ
  • 3Укажите RESEND_API_KEY и SMTP_FROM в .env
SMTP (резервный вариант)
Используется если RESEND_API_KEY не задан. Подходит Gmail, Яндекс, свой сервер.
  • >Укажите SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM
⚠️
При использовании Resend: адрес отправителя SMTP_FROM должен быть на верифицированном домене. В тестовом режиме письма приходят только на ваш собственный email.
3

Настройка .env файла

Создайте или отредактируйте файл конфигурации на сервере с ботом:

bash
nano /root/bot/.env
/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

# -- Лимит платёжных запросов ---------------------------------------------
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 ---------------------------------------------------------
# Рекомендуется: OpenID Connect (OAuth 2.0)
# @BotFather → Open (mini-app) → Login Widget → Switch to OpenID Connect Login (если OAuth 2.0 не активирован)
# Trusted Origins: https://ваш-домен (без пути; / Telegram подставит сам)  |  Redirect URL: .../auth/telegram/callback
TELEGRAM_OIDC_CLIENT_ID=123456789
TELEGRAM_OIDC_CLIENT_SECRET=ваш_client_secret

# При OAuth 2.0 BOT_USERNAME не нужен — закомментируйте или удалите строку ниже:
# BOT_USERNAME=myvpnbot
# Legacy-виджет (только без OIDC): @BotFather → Open (mini-app) → Login Widget, домен без https://
BOT_USERNAME=ваш_бот

# -- Yandex SmartCaptcha (опционально) ------------------------------------
YANDEX_CAPTCHA_SITE_KEY=
YANDEX_CAPTCHA_SECRET_KEY=

# -- Мои устройства (требует запущенного SUBPAGE) --------------------------
WEBSITE_DEVICES_ENABLED=0

# Настройки кабинета в веб-админке (RM-Only): Настройки → Веб-кабинет
#   • Белый список EMAIL — разрешённые домены для входа и регистрации
#   • Приложения — ссылки на скачивание и deep_link для автодобавления подписки

# -- Google OAuth (опционально) --------------------------------------------
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=

# -- Yandex OAuth (опционально) --------------------------------------------
# YANDEX_CLIENT_ID=
# YANDEX_CLIENT_SECRET=

# -- Отдельные реквизиты касс для сайта (опционально) ---------------------
# Если не заданы — используются настройки из БД (те же что у бота).
# Рекомендуется: отдельный магазин для сайта (требование касс, не техническое).
# Webhook для отдельного магазина — URL из веб-админки (Методы оплаты),
# НЕ домен SITE_URL: платежи принимает бот (connect_page_url), не website.
# 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_KEYAPI-ключ Resend для отправки email-кодов входа.Optional
SMTP_FROMEmail отправителя (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
PAYMENT_RATE_LIMITМаксимум попыток создать платёж за одно окно времени. По умолчанию 3.Optional
PAYMENT_RATE_WINDOWОкно лимита платежей в секундах. По умолчанию 300 = 5 минут.Optional
TRIAL_DAYSПробный период для регистраций через сайт. 0 = отключено. Кол-во дней берётся из настроек бота.Optional
TELEGRAM_OIDC_CLIENT_*Telegram OIDC (OAuth 2.0). Настройка: @BotFather → Open (mini-app) → Login Widget → Switch to OpenID Connect Login (Trusted Origins + Redirect URL https://ваш_домен/auth/telegram/callback). При OIDC BOT_USERNAME закомментируйте или удалите.Optional
BOT_USERNAMELegacy Telegram Login Widget. Только если OIDC не настроен. Домен: @BotFather → Open (mini-app) → Login Widget (без https:// и слэша).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. Удалить устройство клиент может только после первой успешной оплаты подписки (та же проверка, что для докупки GB). Подробнее — HWID → Управление устройствами.Optional
Веб-админка → Настройки → Веб-кабинет (RM-Only, не в .env)
email_whitelistВкладка Белый список EMAIL: разрешённые почтовые домены для входа и регистрации на сайте (gmail.com, yandex.ru и т.д.).Admin
appsВкладка Приложения: ссылки на скачивание (iOS, Android, Windows…) и deep_link для кнопки «Автодобавление» в разделе «Подключить» кабинета.Admin
Отдельные реквизиты для сайта (WEBSITE_*)
WEBSITE_YOOKASSA_*Shop ID и Secret Key отдельного магазина YooKassa для сайта (один магазин нельзя использовать и в боте, и на сайте — риск блокировки ключей). Webhook — URL из веб-админки на домене connect_page_url, не SITE_URL.Optional
WEBSITE_PLATEGA_*Merchant ID и API Secret для Platega на сайте. Callback — как в карточке Platega в веб-админке.Optional
WEBSITE_YOOMONEY_*Account, token и notification secret для YooMoney на сайте. Webhook — как в веб-админке.Optional
WEBSITE_WATA_*Access token и terminal public ID для Wata на сайте.Optional
Веб-админка · RM-Only

Часть настроек личного кабинета задаётся не в .env, а в панели бота: Настройки → Веб-кабинет (/settings/website-cabinet). Изменения применяются сразу, без перезапуска website.

  • 1Белый список EMAIL — какие почтовые домены могут входить и регистрироваться на сайте (gmail.com, mail.ru, корпоративный домен). Можно разрешить уже существующим пользователям с «неразрешённым» доменом.
  • 2Приложения — Happ, INCY и др.: ссылки на скачивание по платформам и deep_link (например happ://add/) для автодобавления подписки в разделе «Подключить» кабинета.
4

Виртуальное окружение и зависимости

bash · Сервер с ботом
# Переходим в папку сайта
cd /root/bot/website

# Создаём виртуальное окружение
python3 -m venv venv

# Активируем
source venv/bin/activate

# Устанавливаем зависимости
pip install -r /root/bot/service/website.txt
💡
pytailwindcss уже включён в requirements.txt — устанавливается автоматически. Сборка CSS запускается при каждом старте сервиса.
Иконки интерфейса

Распакуйте архив с иконками website/static/icon.zip — без этого часть иконок в кабинете не отобразится.

bash
# При необходимости установите unzip
sudo apt install -y unzip

# Распаковываем иконки в static/
cd /root/bot/website
unzip -o static/icon.zip -d static/
5

Systemd сервис

Создайте файл сервиса на сервере с ботом: /etc/systemd/system/website.service (в service/ его нет — только зависимости service/website.txt). Замените XX.XX.XX.XX на реальный IP вашего проксирующего сервера. Остальные юниты: сервисные шаблоны.

bash
nano /etc/systemd/system/website.service
ini · /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
bash · Запуск и автозапуск
systemctl daemon-reload
systemctl enable website
systemctl start website
systemctl status website
⚠️
--forwarded-allow-ips должен содержать только IP вашего проксирующего сервера. Если указать * — любой сможет подделать свой IP через заголовок X-Forwarded-For.
6

Настройка UFW (файрвол)

Выполните на сервере с ботом. Порт 3012 открываем только для проксирующего сервера.

bash · Сервер с ботом
# 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-соединение оборвётся и доступ к серверу будет потерян.
7

Проксирующий сервер — Nginx + SSL

Выполняется на отдельном VPS. Замените cabinet.ваш-домен.ru и IP-бота на реальные значения.

Установка Nginx и Certbot

bash · Проксирующий сервер
apt update && apt install -y nginx certbot python3-certbot-nginx

Получение SSL-сертификата

bash
certbot certonly --nginx -d cabinet.ваш-домен.ru

Конфиг Nginx

bash
nano /etc/nginx/conf.d/website.conf
nginx · /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;
    }
}
bash · Проверка и перезагрузка
nginx -t && systemctl reload nginx
8

Активация в боте

  • 1Откройте веб-админку > Настройки > Основные
  • 2Найдите параметр show_website_button и установите значение 1
  • 3Сохраните настройки
💡
После активации в главном меню бота у пользователей появится кнопка «Личный кабинет», ведущая на сайт.
9

Проверка работоспособности

Статус сервиса
bash
systemctl status website
Логи в реальном времени
bash
journalctl -u website -f

Установка завершена

Кабинет https://cabinet.ваш-домен.ru
Страница входа https://cabinet.ваш-домен.ru/auth
9.1

Вход через Telegram

Опционально. Кнопка «Войти через Telegram» на /auth — вход без email.

Способ A — OpenID Connect (рекомендуется)

OAuth 2.0 через oauth.telegram.org, как Google/Яндекс.

BotFather
@BotFather → Open (mini-app) → Login Widget
  (Switch to OpenID Connect Login — если OAuth 2.0 ещё не активирован)

Trusted Origins: https://cabinet.ваш-домен.ru
  (только origin, без пути; завершающий / Telegram подставит сам)

Redirect URL: https://cabinet.ваш-домен.ru/auth/telegram/callback
  (полный callback — обязателен для server-side OAuth)

Скопируйте Client ID и Client Secret с этого же экрана
.env
TELEGRAM_OIDC_CLIENT_ID=123456789
TELEGRAM_OIDC_CLIENT_SECRET=ваш_client_secret

# При OAuth 2.0 BOT_USERNAME не нужен — закомментируйте или удалите:
# BOT_USERNAME=myvpnbot
Способ B — Legacy-виджет (старый)

Только если OIDC-ключи не заданы.

Шаг 1 — Разрешить домен в BotFather
BotFather
@BotFather → Open (mini-app) → Login Widget

Укажите домен без https:// и слэша
Пример: cabinet.ваш-домен.ru
Шаг 2 — Добавить переменную в .env
.env
# Legacy — только без OIDC
BOT_USERNAME=myvpnbot
⚠️
Trusted Origins и Redirect URL должны совпадать с SITE_URL. Работает только по HTTPS. Client Secret — не bot token.
11

Настройка 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.
bash
systemctl restart website
journalctl -u website -f