Личный кабинет (WEBSITE)
Веб-кабинет для клиентов: просмотр подписки, оплата, управление устройствами. Модуль уже находится в файлах бота, но требует отдельной настройки и запуска.
/root/bot/website/. Ничего скачивать дополнительно не нужно. Требуется только настроить .env, создать systemd-сервис и поднять прокси.
- Для сайта заведите отдельный магазин и укажите его ключи в
/root/bot/.envс префиксомWEBSITE_*(см. блок ниже). Если переменные пустые — сайт берёт те же реквизиты из веб-админки, что и бот. - Для отдельного магазина в кабинете YooKassa / Platega / YooMoney укажите URL webhook такой же, как в веб-админке: Настройки → Основные → Методы оплаты (полный адрес на карточке шлюза).
- Не указывайте домен личного кабинета (
SITE_URL) — сайт не принимает webhook'и платежей. Их обрабатывает бот на доменеconnect_page_url.
Подробнее о шлюзах и webhook — в разделе Методы оплат.
Мастер настройки — подставьте свои данные
Заполните IP, домен и бота один раз — значения автоматически подставятся во все примеры ниже. Всё хранится только в браузере через localStorage.
Требования
Ubuntu 24.04 · Python 3.12 · RM-Only 1.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 # -- Лимит платёжных запросов --------------------------------------------- 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_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 |
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_USERNAME | Legacy 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 |
Часть настроек личного кабинета задаётся не в .env, а в панели бота:
Настройки → Веб-кабинет (/settings/website-cabinet). Изменения применяются сразу, без перезапуска website.
- 1Белый список EMAIL — какие почтовые домены могут входить и регистрироваться на сайте (
gmail.com,mail.ru, корпоративный домен). Можно разрешить уже существующим пользователям с «неразрешённым» доменом. - 2Приложения — Happ, INCY и др.: ссылки на скачивание по платформам и
deep_link(напримерhapp://add/) для автодобавления подписки в разделе «Подключить» кабинета.
Виртуальное окружение и зависимости
# Переходим в папку сайта 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 — без этого часть иконок в кабинете не отобразится.
# При необходимости установите unzip sudo apt install -y unzip # Распаковываем иконки в static/ cd /root/bot/website unzip -o static/icon.zip -d static/
Systemd сервис
Создайте файл сервиса на сервере с ботом: /etc/systemd/system/website.service (в service/ его нет — только зависимости service/website.txt). Замените 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» на /auth — вход без email.
OAuth 2.0 через oauth.telegram.org, как Google/Яндекс.
@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 с этого же экрана
TELEGRAM_OIDC_CLIENT_ID=123456789 TELEGRAM_OIDC_CLIENT_SECRET=ваш_client_secret # При OAuth 2.0 BOT_USERNAME не нужен — закомментируйте или удалите: # BOT_USERNAME=myvpnbot
Только если OIDC-ключи не заданы.
@BotFather → Open (mini-app) → Login Widget Укажите домен без https:// и слэша Пример: cabinet.ваш-домен.ru
# Legacy — только без OIDC BOT_USERNAME=myvpnbot
SITE_URL. Работает только по HTTPS. Client Secret — не bot token.Настройка 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