Operations: health, backups, upgrades
8. Operations
8.1 Health and readiness
curl -fsS http://127.0.0.1:5000/health # -> ok
curl -fsS -H "Authorization: Bearer $KEY" \
https://social.example.com/public/v1/providers/status | jq
providers/status returns, per provider:
{
"identifier": "x",
"name": "X",
"configured": true,
"missing": [],
"connection": "oauth"
}
Only variable names are reported, never values. A provider with
configured:false is refused before an OAuth URL is generated; the error names
the missing variables and the redirect URI to register.
8.2 Logs
Logs go to stderr as plain-text tracing lines (the default subscriber format,
with fields appended). Useful filters:
RUST_LOG=info,rustiz=debug,sqlx=warn,tower_http=info rustiz serve
Do not send MCP stdio logs to stdout. If you wrap rustiz mcp in a supervisor,
route stderr to a file and leave stdout for the protocol.
8.3 Backups
Back up both the database and JWT_SECRET.
# Online, consistent backup (WAL aware).
sqlite3 /var/lib/rustiz/rustiz.db \
".backup '/var/backups/rustiz-$(date +%F).db'"
# Or stop the service and copy the database plus any -wal/-shm files.
systemctl stop rustiz
cp -a /var/lib/rustiz/rustiz.db* /var/backups/
systemctl start rustiz
Also back up config.env (or at least JWT_SECRET and RUSTIZ_API_KEY) and
the upload directory or bucket. A database restored without the original
secret can no longer decrypt customFields credentials or custom-instance
client information, so those channels must be reconnected. Provider access
tokens remain readable because they are stored in plain text in the database —
which also means a database backup is a bearer-credential backup: encrypt it
and restrict access to it.
Test restores on a separate copy. Do not run two servers against the same SQLite file over NFS or a network filesystem.
8.4 Upgrades
- Back up.
- Build/copy the new binary.
rustiz migrate(or just start; migrations run automatically).- Restart
serveandworker; graceful shutdown closes MCP subscription streams. - Check
/healthandproviders --status.
Schema migrations are applied in order and are not automatically reversible. Read the release notes before a downgrade.
8.5 Scaling
- One SQLite file supports one writer at a time. Scale vertically first:
WORKER_CONCURRENCY,MCP_SUBSCRIPTIONS_MAX_STREAMS,REQUEST_LIMIT. - Multiple
servereplicas are possible only with a shared database; SQLite on a shared local volume is not safe across hosts. Object storage is required for media if replicas do not share a volume. - Rate limits are per process, so N replicas mean N× the configured budget.
- Use one
workerunless you have measured lease contention; the job table uses five-minute leases and heartbeats and can handle several workers, but SQLite write contention is the practical limit. - Long-lived MCP streams are cheapest on a single instance; a proxy with buffering disabled is mandatory.
8.6 Security checklist
-
FRONTEND_URLis HTTPS and matches the registered redirect URIs. -
JWT_SECRETis random and stable,config.envis0600, and both are backed up. It protects custom credentials, not OAuth tokens. - The SQLite file and its backups are encrypted at rest: provider access tokens (including OAuth tokens and some API keys) are stored in plain text in the database.
- Rustiz binds
127.0.0.1(or a private interface) behind a TLS proxy. -
ALLOW_PRIVATE_NETWORKis unset unless the deployment is single-tenant and the network is trusted. - API keys are distributed over a secret manager, not chat or URLs.
-
TRUSTED_PROXY_HOPSmatches the real proxy chain and the origin is firewalled to those proxies. - The
/datavolume andUPLOAD_DIRECTORYare writable only by the service user. - The object bucket is public only for media, and its write credentials are not exposed to clients.
- Backups are encrypted and restore-tested.
-
RUST_LOGdoes not log request bodies containing credentials (the port redacts bodies stored inErrors, but proxy logs are your responsibility).