12. Operations
12.1 Commands
bo-app start # HTTP server
bo-app start --worker # queue workers only (ingest, workflows)
bo-app start --server-and-worker # both, for small deployments
bo-app scheduler # runs the cron jobs in config/{env}.yaml
bo-app db migrate # apply migrations
bo-app task config_validate # load, validate and compile every definition, then exit
bo-app task schema_export [dir:schemas]
bo-app task retention_purge # drop parsed text older than policies.retention.parsed_markdown_days
bo-app task approval_expiry # mark pending approvals past expires_at as expired
bo-app task seed_demo [tenant:demo] [expiration:86400]
In development, prefix these with cargo run -p bo-app --. config_validate boots exactly as the
server does, so CI uses it to prove every definition loads.
The scheduler runs retention_purge daily at 03:00 and approval_expiry every 15 minutes.
Schedules have six fields, starting with seconds; bo-app scheduler --list shows what will run.
12.2 Production
config/production.yaml reads everything from the environment. deploy/.env.example lists the
variables:
| Variable | Notes |
|---|---|
DATABASE_URL | PostgreSQL with pgvector and pgcrypto |
JWT_SECRET | base64 (openssl rand -base64 32); Loco decodes it |
VLLM_CHAT_URL, VLLM_EMBED_URL, VLLM_API_KEY | OpenAI-compatible model servers |
DOCLING_URL, DOCLING_API_KEY | docling-serve |
OTLP_ENDPOINT | OpenTelemetry Collector (telemetry is on in production) |
PUBLIC_URL, WEB_ORIGIN, DOCUMENTS_DIR | server URL, the web app's origin (CORS), the upload directory |
ACCOUNTING_URL, ACCOUNTING_HMAC_SECRET | for a webhook accounting connector |
deploy/docker-compose.yml describes the full stack: PostgreSQL, vLLM (chat and embeddings),
docling-serve, the OpenTelemetry Collector, Jaeger, a migrate job, then server, worker,
scheduler and web. config/ is mounted read-only, so changing a workflow means editing the file
and restarting, never rebuilding. Optional profiles add Valkey and SeaweedFS for observability
tools. These images have not been built and run end to end yet; treat the compose file as a
starting point.
Production runs auto_migrate: false; run bo-app db migrate as a deploy step.
12.3 The web app in production
cd web
bun install --frozen-lockfile --omit optional # leaves out sharp (LGPL), which nothing uses
bun run build
BO_AGENT_URL=http://server:8080 bun run start
deploy/Dockerfile.web does the same on Bun. It runs bun run license:check, which fails the
build if any production dependency's license is outside license-policy.json.