/Users/v.tatarnikov/Projects/WhiteBox → деплой в /opt/WhiteBoxmirkwood.4gain.pro (94.25.50.91)whitebox (user whitebox)dep816.ru + www.dep816.ru). См. ssl-tg-routing.ssh root@94.25.50.91Платформа состоит из двух кодовых баз: WhiteBox (этот) для UI/курсов/лаб и AmneziaWG-stats для VPN/биллинга. Они общаются по HTTP через
shared/vpn_client.py.
| Сервис | Порт | Systemd | Что делает |
|---|---|---|---|
| Лендинг | 5010 | wb-landing.service |
dep816.ru — главная, курсы, лаб-стенды, тарифы |
| Кабинет | 5011 | wb-cabinet.service |
dep816.ru/cabinet — личный кабинет ученика, материалы, доступ к лабам |
| Админка | 5012 | wb-admin.service |
dep816.ru/admin — управление пользователями, тарифами, лабами, валидацией |
| TG-бот | 8444 | wb-tgbot.service |
Webhook бот @dep816WhiteBoxBot (TG-WebApp + меню) |
| Lab-агент | 5020 | wb-labs-agent.service |
Создаёт/удаляет docker-контейнеры лабораторий по REST |
Внешний AWG-сервис на этом же хосте — awg-web.service :5001 (см. amneziawg-stats).
MySQL whitebox, таблицы (только то, что хранит сам WhiteBox):
wb_validation_requests — заявки на валидацию (двойная: бот → админ)wb_whitelist — белый список Telegram IDwb_tariffs — тарифы (зеркало AWG Plan для UI)wb_news — новости/уведомления для кабинетаwb_messages — переписка ученик ↔ преподавательwb_materials — Markdown-материалы по лабам (50 шт., 3-5 шагов на каждую из 13 лаб)wb_tpay_pending_payments — связка order_id → payer/months для webhook T-PayЧего НЕТ:
wb_users — статус юзера всегда тянется из AWG Payerwb_connections — VPN-подключения только в AWG Userwb_labs_* — каталог лаб лежит в labs_agent/catalog.yml, текущее состояние — docker inspect| Тариф | Цена | Лаб | Стенды |
|---|---|---|---|
| Start250 | 250 ₽/мес | 2 | DVWA, Juice Shop |
| Start500 | 500 ₽/мес | 4 | + WebGoat, bWAPP |
| Personal1500 | 1500 ₽/мес | 8 | + Mutillidae, WP, DVGA, VAmPI |
| Personal5000 | 5000 ₽/мес | 13 | + Metasploitable, Hackazon, Rails/Node/Django |
Поля тарифа: price_monthly, опционально price_6m / price_12m (0 = автоскидка −10%/−20% от base × 6/12), trial_period_days (default 7). Дублируются в wb_tariffs и в AWG plans.
См. billing — расчёт цены, trial, throttle, T-Pay.
1. Юзер → @dep816WhiteBoxBot → "Запросить валидацию" → wb_validation_requests
2. Админ → /admin/validation-requests → "Одобрить" → создаётся Payer "WB_{tg_id}" в AWG VPN API
3. Юзер создаёт VPN-подключение → ВСЕГДА connection_type='iot' (изолированный)
4. Админ → /admin/connections → переключает iot → standard (полный доступ)
Без шага 4 юзер видит только свою лабу, не интернет. Защита: новый ученик не должен случайно прокатать тариф через VPN, не пройдя валидацию.
wb_lab_<sid>)wb-labs Docker bridge (172.30.0.0/16)memory=256m, cpus=0.25labs_agent/catalog.yml (13 типов)@dep816WhiteBoxBotnugush.4gain.pro/wb-webhook → awg0 → mirkwood nginx → :8444/wb-webhook_poll_tpay_loop каждые 2 мин (подстраховка если webhook не дошёл):5088/notify и :5088/broadcast — другие сервисы шлют сообщения админам через ботаПродакшен с 2026-04-16. Терминал боевой 1776164207893. См. подробно: billing.
shared/payment/ — tpay.py, yookassa.py (disabled fallback)/admin/internal/tpay/webhook — обработка CONFIRMED/REJECTED/REFUNDEDSID[:8])/delivery, /returns, /privacy, /privacy-policycd /Users/v.tatarnikov/Projects/WhiteBox
./dev/bin/deploy.sh # rsync только файлы
./dev/bin/deploy.sh -r # + рестарт сервисов
./dev/bin/deploy.sh -f # + рестарт + apply firewall AWG
Тесты: ./dev/bin/test.sh (151 тест), ./dev/bin/deploy-test.sh (29 проверок smoke на проде).
Подробно — runbooks/deploy.
shared/models.py — SQLAlchemy модели (WbValidationRequest, WbWhitelist, WbTariff, WbNews, WbMessage, WbMaterial)shared/vpn_client.py — HTTP клиент к AmneziaWGStatistic APIshared/labs_client.py — клиент к lab-агентуshared/payment/{core,tpay,yookassa,factory}.py — биллинг pluggabletgbot/bot.py — Telegram-бот (~1000 строк)admin/{app,auth,connections,users,labs,...}.py — Flask админкаcabinet/app.py, landing/app.py — UI-сервисыlabs_agent/{agent.py,catalog.yml} — Docker lab-агентconfig.yml (в .gitignore) / config.yml.example — конфигАудит 2026-04-10:
bleach.clean() на Markdown → HTMLsecrets.choice (не random.randint)config.yml (gitignored), пример в config.yml.examplewhitebox user без доступа к awg_stats — это нормально. Перекрёстных запросов не делаем, только через AWG REST API.User.lab_ip при recreate/delete через LabsClient.Changelog