Production-развёртывание
systemd, Caddy + TLS, инициализация, бэкапы, anti-spoof контролы.
Production-развёртывание
Инструкция по первому production-развёртыванию wallet-scoring: единый бинарь PocketBase + модульные сценарии скоринга.
Архитектура деплоя
Internet ──TLS──► Caddy :443 ──► wallet-scoring serve (PocketBase, 127.0.0.1:8090)
│ │
│ └──► SurrealDB server :27182
│ (HTTP, rocksdb data dir,
│ 1 namespace = 1 tenant)
│
└──► pb_data/ (SQLite: tenancy, superusers)
WF_JOBS_DIR=/srv/wallet-scoring/jobs (очередь скоринга + DLQ)
scenarios/ — пакеты сценариев (источник для загрузки программ)- Production entrypoint — бинарь из
cmd/pb: хост PocketBase v0.40.1. Поднимает tenancy, Score API (/api/v1/score), Admin API, dashboard, ns-proxy. - State — два компонента:
- SurrealDB (
http://127.0.0.1:27182) — programs, credit ledger, API-ключи (хэши), job store, DLQ, audit. Обязателен: без него score/admin API не работают. - PocketBase SQLite (
pb_data/) — tenancy, superusers, служебное.
- SurrealDB (
- Очередь скоринга — файловая (
jobs/): задачи переживают рестарт процесса. DLQ — задачи, исчерпавшие ретраи.
Требования к серверу
| Параметр | Минимум | Рекомендовано |
|---|---|---|
| OS | Linux x86_64 (amd64), glibc ≥ 2.31 | Ubuntu 22.04/24.04 LTS |
| CPU | 1 vCPU | 2 vCPU |
| RAM | 1 GiB | 2 GiB (PB + SurrealDB) |
| Диск | 10 GiB | 20 GiB SSD |
| Сеть | исходящий HTTPS (TronGrid и т.п.) | + входящий 443 |
| ПО | surrealdb CLI ≥ 2.x, caddy | — |
Бинарь собирается с CGO_ENABLED=0 (SQLite — modernc.org/sqlite, чистый Go) — статически слинкован и не зависит от версии glibc на сервере.
systemd
Два юнита: surrealdb.service (БД) и wallet-scoring.service (приложение, After=surrealdb.service):
sudo systemctl daemon-reload
sudo systemctl enable --now surrealdb wallet-scoring
sudo systemctl status surrealdb wallet-scoring
journalctl -u wallet-scoring -fСтруктура на сервере:
/srv/wallet-scoring/
├── bin/wallet-scoring # бинарь приложения
├── env # EnvironmentFile для systemd (chmod 600)
├── data/
│ ├── pb/ # PB_DATA_DIR (PocketBase SQLite + backups)
│ └── surreal/ # SurrealDB rocksdb data
├── jobs/ # WF_JOBS_DIR: очередь задач скоринга, DLQ
├── scenarios/ # пакеты сценариев
└── backup/ # внешние бэкапы (tar)Конфигурация (env)
| Переменная | Назначение | Default | Production |
|---|---|---|---|
WF_JOBS_DIR | каталог очереди задач скоринга | $TMPDIR/... ⚠️ tmp! | /srv/wallet-scoring/jobs (обязательно!) |
PLATFORM_ED25519_SEED | seed приватного ключа платформы для подписи дистрибутивов | фиксированный e2e-seed | до закрытия Э2 не менять |
TRONGRID_API_KEY и др. | читаются из .env пакетов сценариев, не из окружения процесса | scenarios/default/.env.example | заполнить до сборки дистрибутива |
Порты:
| Порт | Процесс | Доступ |
|---|---|---|
| 8090 | wallet-scoring (PocketBase) | loopback, наружу — через Caddy :443 |
| 27182 | SurrealDB HTTP | только loopback, фаервол |
Инициализация
- Суперюзер PocketBase (admin UI
/_):
sudo -u wallexx /srv/wallet-scoring/bin/wallet-scoring \
--dir /srv/wallet-scoring/data/pb \
superuser upsert admin@example.com '<сильный пароль>'
sudo systemctl restart wallet-scoring- Проверка:
curl -s http://127.0.0.1:8090/api/health
# => {"code":200,"message":"API is healthy.","data":{}}
curl -s http://127.0.0.1:27182/health # SurrealDB-
Загрузка сценариев: заполнить
scenarios/default/.env(TRONGRID_API_KEY), собрать подписанный дистрибутив программы (cmd/dist), загрузить через CLItl/pbctlили админ-UI. Сценарии в рантайме читаются из SurrealDB, а не с диска. -
Первый тенант и API-ключ: создать organization (провижининг namespace автоматический), выдать ключ
wx_...(хранится как argon2-хэш), пополнить кредиты:POST /admin/api/credits/topup.
Caddy + TLS
deploy/Caddyfile (он же Caddyfile в корне репозитория) — готовый конфиг:
- проксирование
https://score.example.com→http://127.0.0.1:8090; request_body max_size 10MB(sync-скоринг, фичи в теле запроса);- таймауты ≥ 60 s (сценарии ходят во внешние API);
- доступ к
/_/(admin UI) ограничен allowlist IP; - TLS автоматический (ACME) — certbot не нужен.
sudo cp deploy/Caddyfile /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddyБэкап и восстановление
State = SurrealDB data + PocketBase + jobs/ + scenarios/*/.env. Консистентный бэкап (nightly cron, короткая остановка + tar):
systemctl stop wallet-scoring surrealdb
tar -C /srv/wallet-scoring -czf "`DEST/state-`TS.tar.gz" data jobs
systemctl start surrealdb wallet-scoring
# ретенция 14 дней
find "$DEST" -name 'state-*.tar.gz' -mtime +14 -deleteВосстановление: остановить сервисы → распаковать tar → chown wallexx → старт → проверить health.
Anti-spoof / безопасность
- API-ключи хранятся только как argon2-хэши (
api_keys), глобальный индекс — O(1) lookup; показ ключа — один раз при выдаче. - Подпись дистрибутивов программ ed25519: рантайм проверяет подпись платформенного ключа при загрузке — подмена сценария исключена.
- TLS only снаружи; порты приложения и SurrealDB — loopback.
- Admin UI
/_/закрыт allowlist IP в Caddyfile. - Секреты (
/srv/wallet-scoring/env,scenarios/*/.env) —chmod 600, владелец wallexx, не коммитятся. - Ledger кредитов immutable — любое изменение баланса имеет запись с actor/reason.
Чек-лист первого релиза
- Бинарь собран с
CGO_ENABLED=0, проверенldd - Оба systemd-сервиса активны, health OK
WF_JOBS_DIR— НЕ tmp- Порт 27182 закрыт снаружи (loopback only)
scenarios/default/.envзаполнен,chmod 600- Дистрибутив
defaultзагружен - Тестовый скоринг:
POST /api/v1/scoreс ключомwx_...→credits_spent - Caddy + TLS (авто-сертификат),
/_/закрыт allowlist IP - Бэкап-скрипт в cron, восстановление проверено на staging