Wallexx — Документация
Деплой и эксплуатация

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 — два компонента:
    1. SurrealDB (http://127.0.0.1:27182) — programs, credit ledger, API-ключи (хэши), job store, DLQ, audit. Обязателен: без него score/admin API не работают.
    2. PocketBase SQLite (pb_data/) — tenancy, superusers, служебное.
  • Очередь скоринга — файловая (jobs/): задачи переживают рестарт процесса. DLQ — задачи, исчерпавшие ретраи.

Требования к серверу

ПараметрМинимумРекомендовано
OSLinux x86_64 (amd64), glibc ≥ 2.31Ubuntu 22.04/24.04 LTS
CPU1 vCPU2 vCPU
RAM1 GiB2 GiB (PB + SurrealDB)
Диск10 GiB20 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)

ПеременнаяНазначениеDefaultProduction
WF_JOBS_DIRкаталог очереди задач скоринга$TMPDIR/... ⚠️ tmp!/srv/wallet-scoring/jobs (обязательно!)
PLATFORM_ED25519_SEEDseed приватного ключа платформы для подписи дистрибутивовфиксированный e2e-seedдо закрытия Э2 не менять
TRONGRID_API_KEY и др.читаются из .env пакетов сценариев, не из окружения процессаscenarios/default/.env.exampleзаполнить до сборки дистрибутива

Порты:

ПортПроцессДоступ
8090wallet-scoring (PocketBase)loopback, наружу — через Caddy :443
27182SurrealDB HTTPтолько loopback, фаервол

Инициализация

  1. Суперюзер 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
  1. Проверка:
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
  1. Загрузка сценариев: заполнить scenarios/default/.env (TRONGRID_API_KEY), собрать подписанный дистрибутив программы (cmd/dist), загрузить через CLI tl/pbctl или админ-UI. Сценарии в рантайме читаются из SurrealDB, а не с диска.

  2. Первый тенант и API-ключ: создать organization (провижининг namespace автоматический), выдать ключ wx_... (хранится как argon2-хэш), пополнить кредиты: POST /admin/api/credits/topup.

Caddy + TLS

deploy/Caddyfile (он же Caddyfile в корне репозитория) — готовый конфиг:

  • проксирование https://score.example.comhttp://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