qc-custody binary, with its default and a one-line description. Source of truth: custody/config/config.go.
All variables are prefixed CUSTODY_. They may be set in the process environment, in a .env file, or via your orchestrator’s secret-injection mechanism.
Server
| Variable | Default | Description |
|---|---|---|
CUSTODY_SERVER_HOST | 0.0.0.0 | Bind address |
CUSTODY_SERVER_PORT | 8080 | HTTP API port |
CUSTODY_METRICS_PORT | 9090 | Prometheus metrics port |
CUSTODY_SERVER_READ_TIMEOUT | 30s | HTTP read timeout |
CUSTODY_SERVER_WRITE_TIMEOUT | 30s | HTTP write timeout |
CUSTODY_SERVER_SHUTDOWN_TIMEOUT | 15s | Graceful shutdown deadline |
CUSTODY_SERVER_REQUEST_TIMEOUT | 30s | Per-request timeout |
Database
| Variable | Default | Description |
|---|---|---|
CUSTODY_DB_HOST | localhost | PostgreSQL host |
CUSTODY_DB_PORT | 5432 | PostgreSQL port |
CUSTODY_DB_NAME | qc_custody | Database name |
CUSTODY_DB_USER | custody | Database user |
CUSTODY_DB_PASSWORD | (required unless IAM auth) | Database password |
CUSTODY_DB_SSLMODE | verify-full | TLS mode; use disable only for local dev |
CUSTODY_DB_SSL_ROOT_CERT | — | Path to CA cert (RDS) |
CUSTODY_DB_MAX_OPEN_CONNS | 25 | Pool max |
CUSTODY_DB_MAX_IDLE_CONNS | 5 | Pool idle |
CUSTODY_DB_CONN_MAX_LIFETIME | 5m | Connection lifetime |
CUSTODY_DB_MIGRATE_ON_START | true | Auto-run schema migrations |
CUSTODY_DB_IAM_AUTH | false | Use AWS RDS IAM auth (skips password) |
CUSTODY_DB_READ_REPLICA_ENABLED | false | Route reads to replica |
CUSTODY_DB_READ_HOST | — | Replica host |
CUSTODY_DB_READ_PORT | 5432 | Replica port |
Quantum Chain node
| Variable | Default | Description |
|---|---|---|
CUSTODY_NODE_RPC_URL | http://localhost:8545 | HTTP JSON-RPC endpoint (required) |
CUSTODY_NODE_WS_URL | ws://localhost:8546 | WebSocket endpoint (deposit watching) |
CUSTODY_NODE_BACKUP_RPC_URLS | — | Comma-separated failover endpoints |
CUSTODY_NODE_DIAL_TIMEOUT | 10s | Connection dial timeout |
CUSTODY_NODE_REQUEST_TIMEOUT | 15s | Per-request timeout |
CUSTODY_NODE_HEALTH_CHECK_INTERVAL | 30s | Health-check cadence |
Chain
| Variable | Default | Description |
|---|---|---|
CUSTODY_CHAIN_ID | 20803 | Chain ID |
CUSTODY_CONFIRMATION_DEPTH | 12 | Blocks before a tx is CONFIRMED |
CUSTODY_CONFIRMATION_POLL_INTERVAL | 5s | Confirmation poll interval |
CUSTODY_SIGNING_PAYLOAD_TTL | 10m | How long a PENDING_SIGNATURE payload is valid |
Authentication and SSO
| Variable | Default | Description |
|---|---|---|
CUSTODY_AUTH_ENABLED | true | Require bearer auth |
CUSTODY_WEBHOOK_SIGNING_KEY | — | HMAC key for webhook signatures (required in prod) |
CUSTODY_SSO_ENABLED | false | Enable SSO/OIDC |
CUSTODY_SSO_JWT_SIGNING_KEY | — | HMAC-SHA256 key for SSO tokens (required if SSO) |
CUSTODY_SSO_ACCESS_TOKEN_TTL | 15m | Access-token lifetime |
CUSTODY_SSO_REFRESH_TOKEN_TTL | 24h | Refresh-token lifetime |
CUSTODY_SSO_ALLOWED_ISSUERS | — | Comma-separated OIDC issuer URLs |
CUSTODY_SSO_AUTO_PROVISION | true | Auto-create users on first SSO login |
CUSTODY_SSO_DEFAULT_ROLE | viewer | Role assigned to auto-provisioned users |
Webhooks
| Variable | Default | Description |
|---|---|---|
CUSTODY_WEBHOOK_MAX_RETRIES | 5 | Per-delivery retry budget |
CUSTODY_WEBHOOK_RETRY_BASE_DELAY | 10s | Initial backoff |
CUSTODY_WEBHOOK_RETRY_MAX_DELAY | 1h | Max backoff |
CUSTODY_WEBHOOK_DELIVERY_TIMEOUT | 10s | Per-delivery HTTP timeout |
CUSTODY_WEBHOOK_WORKER_COUNT | 4 | Concurrent delivery workers |
CUSTODY_WEBHOOK_ENCRYPTION_KEY | — | 64 hex chars (32 bytes) for AES-256-GCM at-rest encryption of webhook secrets |
Signer
CUSTODY_SIGNER_* variables also accept CUSTODY_ENQLAVE_* aliases. If both are set, CUSTODY_SIGNER_* wins.
| Variable | Default | Description |
|---|---|---|
CUSTODY_SIGNER_TYPE | callback | One of callback, remote, grpc |
CUSTODY_SIGNER_BACKEND | enqlave | enqlave or qey (only for grpc) |
CUSTODY_SIGNER_ENDPOINT | — | Remote signer HTTPS URL |
CUSTODY_SIGNER_API_KEY | — | Remote signer bearer token |
CUSTODY_SIGNER_GRPC_TARGET | — | Signer gRPC host:port (required if type=grpc) |
CUSTODY_SIGNER_GRPC_TLS_CERT | — | Server TLS cert (one-way TLS) |
CUSTODY_SIGNER_GRPC_CLIENT_CERT | — | Client cert for mTLS |
CUSTODY_SIGNER_GRPC_CLIENT_KEY | — | Client private key for mTLS |
CUSTODY_SIGNER_GRPC_CA_CERT | — | CA cert verifying the signer |
CUSTODY_SIGNER_GRPC_TIMEOUT | 30s | Per-call timeout |
CUSTODY_SIGNER_GRPC_MAX_RECV_MSG_SIZE | 0 | Max gRPC response in bytes (0 = default 64 KB) |
CUSTODY_SIGNER_KEYGEN_MODE | local | local or qey (Qey-side keygen requires backend=qey) |
RBAC
| Variable | Default | Description |
|---|---|---|
CUSTODY_RBAC_ENABLED | false | Enforce role-based access control |
CUSTODY_RBAC_SEED_ON_STARTUP | true | Seed system roles on first boot |
Rate limiting
| Variable | Default | Description |
|---|---|---|
CUSTODY_RATE_LIMIT_ENABLED | true | Enable rate limiter |
CUSTODY_RATE_LIMIT_RPM | 120 | Requests per minute per key |
CUSTODY_RATE_LIMIT_BURST | 20 | Burst size |
CUSTODY_RATE_LIMIT_REDIS_URL | — | Redis URL; enables distributed limiting |
Telemetry (OpenTelemetry)
| Variable | Default | Description |
|---|---|---|
CUSTODY_OTEL_ENABLED | false | Emit traces |
CUSTODY_OTEL_ENDPOINT | — | OTLP endpoint (e.g. otel-collector:4317) |
CUSTODY_OTEL_SERVICE_NAME | qc-custody | Service name |
CUSTODY_OTEL_INSECURE | false | Disable TLS to collector |
CUSTODY_OTEL_SAMPLE_RATE | 1.0 | Sample fraction (0.0–1.0) |
Secrets provider
| Variable | Default | Description |
|---|---|---|
CUSTODY_SECRETS_PROVIDER | env | env or aws |
CUSTODY_SECRETS_AWS_REGION | — | Region for AWS Secrets Manager |
CUSTODY_SECRETS_CACHE_TTL | 5m | Local cache TTL |
Compliance / AML
| Variable | Default | Description |
|---|---|---|
CUSTODY_COMPLIANCE_ENABLED | false | Enable AML pre-broadcast screening |
CUSTODY_COMPLIANCE_PROVIDER | noop | noop, chainalysis, or shuftipro |
CUSTODY_CHAINALYSIS_API_KEY | — | Chainalysis API key (required if provider) |
CUSTODY_CHAINALYSIS_BASE_URL | https://api.chainalysis.com/api/kyt/v2 | Chainalysis endpoint |
CUSTODY_CHAINALYSIS_TIMEOUT | 30s | Per-call timeout |
CUSTODY_SHUFTIPRO_CLIENT_ID | — | Shufti Pro client ID |
CUSTODY_SHUFTIPRO_SECRET_KEY | — | Shufti Pro secret |
CUSTODY_SHUFTIPRO_BASE_URL | https://api.shuftipro.com | Shufti Pro endpoint |
CUSTODY_SHUFTIPRO_CALLBACK_URL | — | Public URL for async callbacks |
CUSTODY_SHUFTIPRO_TIMEOUT | 30s | Per-call timeout |
CUSTODY_SHUFTIPRO_ONGOING | false | Enable ongoing monitoring |
Validation rules
The service refuses to start if:CUSTODY_DB_PASSWORDis empty andCUSTODY_DB_IAM_AUTH=false.CUSTODY_NODE_RPC_URLis empty.CUSTODY_SSO_ENABLED=trueandCUSTODY_SSO_JWT_SIGNING_KEYis empty.CUSTODY_COMPLIANCE_PROVIDER=shuftiproand eitherCUSTODY_SHUFTIPRO_CLIENT_IDorCUSTODY_SHUFTIPRO_SECRET_KEYis empty.CUSTODY_COMPLIANCE_PROVIDER=chainalysisandCUSTODY_CHAINALYSIS_API_KEYis empty.CUSTODY_SIGNER_TYPE=grpcandCUSTODY_SIGNER_GRPC_TARGETis empty.CUSTODY_SIGNER_BACKENDis notenqlaveorqey.CUSTODY_SIGNER_BACKEND=qeyandCUSTODY_SIGNER_TYPEis notgrpc.CUSTODY_SIGNER_KEYGEN_MODEis notlocalorqey.CUSTODY_SIGNER_KEYGEN_MODE=qeyandCUSTODY_SIGNER_BACKENDis notqey.CUSTODY_WEBHOOK_ENCRYPTION_KEYis set but is not exactly 64 hex chars.