Развёртывание на VPS¶
Как показать прототип с сервера: тот же Docker-образ, что в README, за обратным прокси с HTTPS. Два варианта:
- Caddy — всё в Docker: стек
compose.vps.yaml, запускdeploy.sh, настройкиdeploy/Caddyfile. Разделы ниже до «Вариант с nginx». - nginx на самом сервере перед
compose.yaml:deploy/nginx/, раздел «Вариант с nginx».
Что нужно¶
- Linux с Docker Engine и Docker Compose v2 (с поддержкой
up --wait): Ubuntu, Debian. Проверка:docker --versionиdocker compose version. - Свободные порты 80 и 443.
- Не меньше 2 ГБ памяти для сборки: образ собирает клиент и синтетический мир. При первой сборке сервер загружает образы и зависимости из интернета.
Код на сервере¶
Любой из двух способов:
git cloneрепозитория на сервер;- архив исходников: на своей машине
python scripts/package_vps.pyсоздаётalfa_hack-vps.zipрядом с папкой репозитория (без.env, баз и зависимостей, сMANIFEST.sha256— хэшами файлов). Загрузите его на сервер и распакуйте:unzip alfa_hack-vps.zip && cd alfa_hack. Проверка целостности:sha256sum -c MANIFEST.sha256.
Запуск по IP¶
Из папки с кодом:
bash deploy.sh http://YOUR_VPS_IP
Если Docker доступен только root — sudo bash deploy.sh http://YOUR_VPS_IP.
При первом запуске скрипт создаёт .env.vps с правами только для владельца: новые случайные POSTGRES_PASSWORD и STAFF_PASSWORD, APP_ORIGIN и пустые TELEGRAM_BOT_TOKEN, LLM_*. Существующий .env.vps не перезаписывается. Затем скрипт собирает образ и ждёт, пока сервисы станут здоровыми (до 240 с).
После запуска:
http://YOUR_VPS_IP/— кабинет клиента;http://YOUR_VPS_IP/mini/— mini app;http://YOUR_VPS_IP/staff— рабочее место сотрудника, пароль —STAFF_PASSWORDиз.env.vps;http://YOUR_VPS_IP/docs— OpenAPI.
Демо-учётки и сценарий проверки — те же, что в README («Демо-учётки», «Сценарий проверки»).
Домен и HTTPS¶
Направьте DNS домена на сервер (для IPv6 — тоже). При первом запуске:
bash deploy.sh https://business.example.com
Caddy получает и обновляет сертификат сам. Чтобы перейти с IP на домен у уже установленного приложения, измените в .env.vps APP_ORIGIN=https://business.example.com и COOKIE_SECURE=true, затем снова выполните bash deploy.sh https://business.example.com. Пароли БД и сотрудника оставьте прежними. Запуск внутри Telegram требует HTTPS и TELEGRAM_BOT_TOKEN; меню бота настраивается на <адрес>/mini/.
Языковая модель¶
Задайте в .env.vps LLM_BASE_URL и LLM_MODEL (OpenAI-совместимый сервер с моделью с открытыми весами; LLM_API_KEY — если сервер требует ключ) и перезапустите bash deploy.sh <адрес>. Без них работает справочный помощник по шаблонам. Подробно — README, раздел «Языковая модель».
Управление¶
Из папки с кодом:
docker compose --env-file .env.vps -f compose.vps.yaml ps
docker compose --env-file .env.vps -f compose.vps.yaml logs -f --tail=100
docker compose --env-file .env.vps -f compose.vps.yaml stop
Повторный запуск и обновление после git pull — снова bash deploy.sh <адрес>. PostgreSQL и сертификаты хранятся в томах Docker: остановка и пересборка их сохраняют. Для переноса на другой сервер отдельно переносите резервную копию БД.
Вариант с nginx¶
Если на сервере уже работает nginx (или другой сервис на 80/443), Caddy не нужен: стек поднимается из compose.yaml на 127.0.0.1:8000, а nginx принимает HTTPS и проксирует на этот адрес. deploy.sh в этом варианте не запускайте — он поднимает Caddy на тех же портах. Готовый конфиг для домена etabank.ru — deploy/nginx/etabank.ru.conf; для другого домена замените имя в server_name и путях сертификата.
compose.yaml рассчитан на локальный запуск и задаёт APP_ORIGIN=http://127.0.0.1:8000. За nginx браузер присылает Origin: https://etabank.ru, и API отвечает 403 на любой изменяющий запрос. Поэтому стек запускается вместе с deploy/nginx/compose.nginx.yaml, который берёт APP_ORIGIN и COOKIE_SECURE из .env.
- DNS: записи A (и AAAA, если есть IPv6) для
etabank.ru,docs.etabank.ruиумныйкредитныйкабинет.рфуказывают на сервер. .envв папке с кодом:python3 scripts/init_env.pyсоздаёт его со случайнымиSTAFF_PASSWORDиPOSTGRES_PASSWORD(илиcp .env.example .envи задайте их сами). Затем в.env:
dotenv
APP_ORIGIN=https://etabank.ru
COOKIE_SECURE=true
- Стек:
bash
docker compose -f compose.yaml -f deploy/nginx/compose.nginx.yaml up -d --build --wait
Эта Compose-конфигурация также собирает статический сайт документации из Markdown в docs-site/ и публикует его только на 127.0.0.1:8081. Для документации используется отдельный домен; APP_ORIGIN остаётся https://etabank.ru, поэтому проверка Origin и клиентские cookies демо не меняются.
- Сертификат Let's Encrypt (Ubuntu / Debian), до включения конфига — блок 443 без сертификата не пройдёт
nginx -t:
bash
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot certonly --nginx -d etabank.ru --deploy-hook "systemctl reload nginx"
sudo certbot certonly --nginx -d xn--80achddpccdgernff2bzbib6ni.xn--p1ai --deploy-hook "systemctl reload nginx"
Второй сертификат — для умныйкредитныйкабинет.рф: certbot и nginx принимают кириллический домен только в punycode.
certonly только получает сертификат и не меняет конфиги nginx. Продление выполняет таймер certbot; после продления nginx перезагружается.
- Конфиг nginx:
bash
sudo cp deploy/nginx/etabank.ru.conf /etc/nginx/sites-available/etabank.ru
sudo ln -s /etc/nginx/sites-available/etabank.ru /etc/nginx/sites-enabled/etabank.ru
sudo nginx -t
sudo systemctl reload nginx
- Документация на отдельном домене:
bash
sudo install -d -m 755 /var/www/certbot
sudo cp deploy/nginx/docs.etabank.ru-bootstrap.conf /etc/nginx/sites-available/docs.etabank.ru
sudo ln -s /etc/nginx/sites-available/docs.etabank.ru /etc/nginx/sites-enabled/docs.etabank.ru
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/certbot -d docs.etabank.ru --deploy-hook "systemctl reload nginx"
sudo cp deploy/nginx/docs.etabank.ru.conf /etc/nginx/sites-available/docs.etabank.ru
sudo nginx -t
sudo systemctl reload nginx
При повторном включении не создавайте ссылку повторно, если она уже есть. HTTP-конфигурация bootstrap нужна только для первичной выдачи сертификата. Финальная конфигурация оставляет путь ACME challenge открытым для автоматического продления. После установки статическая документация доступна по адресу https://docs.etabank.ru/; её контейнер обновляется вместе с API при деплое.
После этого кабинет — https://etabank.ru/, рабочее место — https://etabank.ru/staff, mini app — https://etabank.ru/mini/, документация — https://docs.etabank.ru/. Конфиг проверен nginx -t на версиях 1.18, 1.24 и 1.27; на 1.25 и новее nginx предупреждает, что listen … http2 устарел, — это не ошибка (можно заменить на listen 443 ssl; и http2 on;).
Что делает конфиг: умныйкредитныйкабинет.рф (по HTTP и HTTPS) перенаправляет на https://etabank.ru с тем же путём и строкой запроса; если в ссылке нет utm_source, добавляется utm_source=rf_domain, чтобы в аналитике был виден этот домен (/staff?utm_source=tg → https://etabank.ru/staff?utm_source=tg, /staff?utm_campaign=x → https://etabank.ru/staff?utm_campaign=x&utm_source=rf_domain, / → https://etabank.ru/?utm_source=rf_domain). Метку меняет map в начале блока .рф; HTTP → HTTPS, TLS 1.2–1.3, HSTS, gzip, тело запроса до 12 МБ (загрузка выписок — до 5 файлов по 2 МБ), заголовки Host, X-Forwarded-For, X-Forwarded-Proto. Заголовка X-Frame-Options нет намеренно: веб-версия Telegram открывает mini app во фрейме.
Управление — те же команды Compose с двумя файлами:
docker compose -f compose.yaml -f deploy/nginx/compose.nginx.yaml ps
docker compose -f compose.yaml -f deploy/nginx/compose.nginx.yaml logs -f --tail=100 api worker
docker compose -f compose.yaml -f deploy/nginx/compose.nginx.yaml up -d --build --wait
Автодеплой: при push в main workflow .github/workflows/deploy.yml заходит на сервер по SSH, делает git pull --ff-only в папке с кодом и выполняет последнюю команду выше. В настройках репозитория GitHub (Settings → Secrets and variables → Actions) задайте секреты VPS_HOST, VPS_USER, VPS_SSH_KEY (закрытый ключ, открытый — в ~/.ssh/authorized_keys пользователя на сервере), при нестандартном порте — VPS_PORT, и переменную VPS_APP_DIR — абсолютный путь к папке с кодом. Пользователю нужен доступ к Docker и право делать git pull (для приватного репозитория — deploy key).
В этом варианте сервисы читают .env целиком, как при локальном запуске: сценарий отказа БКИ для персоны source_down и остальные MOCK_SOURCES_*, SCORECARD_*, LOG_LEVEL, SOURCE_* работают.
Отличия от локального запуска (вариант с Caddy)¶
compose.vps.yamlпередаёт сервисам только явный список переменных, безMOCK_SOURCES_*,SCORECARD_*,LOG_LEVELиSOURCE_*. Поэтому на VPS персонаsource_downполучает обычный ответ БКИ и решается автоматически, а уровень журнала — по умолчанию. Это известное ограничение (docs/v2/NOTES.md, Unassigned).- Синтетический мир, как и в README, собирается в образ при сборке;
WORLD_*не действуют.
Прототип работает на синтетических данных, все внешние системы — моки (docs/SIMPLIFICATIONS.md).