Configuration
Complete reference for all blockd configuration settings.
All deployments require a configuration file. The default path is conf/blockd.yml —
the file must use .yml or .yaml format.
Quick Example
Section titled “Quick Example”A minimal working configuration:
server: log_path: "var/log"
api: enabled: true key: "REPLACE_ME_secret_token"
bitcoind: host: "127.0.0.1" port: 28256 user: "rpcuser" pass: "rpcpassword" zmq: hashtx: 9500 rawtx: 9501 hashblock: 9502 rawblock: 9503 sequence: 9504
electrum: host: "127.0.0.1" port: 50001
data_stores: rocks: path: "var/rocks" blocks: path: "var/blocks"Environment Variables
Section titled “Environment Variables”blockd supports two categories of environment variable: startup variables that control
blockd’s own behavior, and BLOCKD__ prefixed variables that override individual values
within the configuration file.
Startup variables:
| Variable | Description |
|---|---|
BLOCKD_CONF | Path to the configuration file. Default: conf/blockd.yml |
BLOCKD_DEBUG | If set to any value, prints log_path to the console on startup — useful for troubleshooting log path issues before the logger is initialized |
Override variables:
Any value in the configuration file can be overridden using the BLOCKD__ prefix and
__ as the separator for nested keys. Environment variables take precedence over values
in the configuration file.
BLOCKD__BITCOIND__USER=myusernameBLOCKD__BITCOIND__PASS=mypasswordBLOCKD__ELECTRUM__HOST=192.168.1.50Managing Secrets
Section titled “Managing Secrets”Environment variable overrides are useful for keeping secrets out of the configuration
file. Rather than storing sensitive values like API keys and RPC credentials in
blockd.yml, set placeholder values in the file and supply the real values via
environment variables at runtime:
# blockd.yml — safe to commitapi: key: "REPLACE_ME"bitcoind: user: "REPLACE_ME" pass: "REPLACE_ME"# Supply real values at runtimeBLOCKD__API__KEY=my_secret_keyBLOCKD__BITCOIND__USER=myusernameBLOCKD__BITCOIND__PASS=mypasswordThis keeps secrets out of version control and configuration backups without requiring a separate secrets management system. Environment variables can be set in a systemd unit, a Docker environment, or any other mechanism your deployment uses.
server
Section titled “server”Controls the HTTP server, logging, and developer tooling.
server: name: "node-12345" host: "127.0.0.1" port: 21000 log_path: "var/log" log_level: "info" console: false cors: enabled: false origins: []| Parameter | Type | Default | Description |
|---|---|---|---|
name | string | null | Server identifier returned in the version response |
host | string | "127.0.0.1" | Network interface to bind to. Use "0.0.0.0" to accept external connections |
port | integer | 21000 | Listening port |
log_path | string | null | null | Directory for log files. Set to null to log to stdout only (recommended for Docker) |
log_level | string | "info" | Log verbosity: off, error, warn, info, debug, trace |
console | boolean | false | Enable tokio-console on port 6669 for async task inspection. Development only — adds performance overhead. When enabled, log_level is forced to trace |
server.cors
Section titled “server.cors”server: cors: enabled: true origins: - "http://localhost:3000"| Parameter | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable CORS headers |
debug | boolean | false | Enable CORS headers logging for debugging |
origins | string[] | null | null | Allowed origins. See below. |
origins accepts a list of allowed origin URLs. Set to null (YAML null) or [] to allow all origins.
# Inlineorigins: ["https://myapp.com", "https://www.myapp.com"]
# Block sequenceorigins: - "https://myapp.com" - "https://www.myapp.com"CORS Examples
Section titled “CORS Examples”Development:
server: cors: enabled: true debug: true origins: []Production:
server: cors: enabled: true origins: - "https://myapp.com" - "https://www.myapp.com"Controls the user-facing API key.
api: enabled: true key: "your-api-key-here"| Parameter | Type | Default | Description |
|---|---|---|---|
enabled | boolean | required | Enable API key authentication. Must be present in the config file or blockd will not start |
key | string | null | null | API key. Can be omitted from the config file and supplied via the BLOCKD__API__KEY environment variable instead. The final resolved value must be 16–64 characters |
bitcoind
Section titled “bitcoind”Connection and permission settings for Bitcoin Core.
bitcoind: host: "127.0.0.1" port: 8332 user: "rpcuser" pass: "rpcpassword" zmq: hashtx: 9500 rawtx: 9501 hashblock: 9502 rawblock: 9503 sequence: 9504 rpc_permissions: opt_in: [ "getblocktemplate" ] deny: [ "getblock", "getblockchaininfo" ]| Parameter | Type | Description |
|---|---|---|
host | string | Bitcoin Core RPC host |
port | integer | Bitcoin Core RPC port |
user | string | RPC username |
pass | string | RPC password |
zmq | map | ZMQ topic-to-port mappings — see below |
rpc_permissions | object | Method allow/deny overrides — see below |
bitcoind.zmq
Section titled “bitcoind.zmq”Maps ZMQ notification topics to ports. blockd connects to tcp://{host}:{port} for
each topic. All five topics are required — blockd will not function correctly if any
are missing.
bitcoind: zmq: hashtx: 9500 rawtx: 9501 hashblock: 9502 rawblock: 9503 sequence: 9504Multiple topics can share a port, though separate ports are recommended. For example, to consolidate onto three ports:
bitcoind: zmq: hashtx: 9500 rawtx: 9500 hashblock: 9500 rawblock: 9501 sequence: 9502Ports must match the ZMQ configuration in your bitcoin.conf:
zmqpubhashtx=tcp://0.0.0.0:9500zmqpubrawtx=tcp://0.0.0.0:9501zmqpubhashblock=tcp://0.0.0.0:9502zmqpubrawblock=tcp://0.0.0.0:9503zmqpubsequence=tcp://0.0.0.0:9504bitcoind.rpc_permissions
Section titled “bitcoind.rpc_permissions”blockd proxies a subset of Bitcoin Core RPC methods. Most read-only methods are allowed
by default. Use opt_in and deny to adjust access.
Permission resolution order:
- Start with the set of Default-allowed methods (others are restricted)
opt_inpromotes a restricted method to alloweddenyoverrides everything — it blocks a method even if it would otherwise be allowed
bitcoind: rpc_permissions: opt_in: [ "getblocktemplate" ] deny: [ "getblock", "getblockchaininfo" ]For the full list of supported methods, default permissions, and the reasoning behind each restriction, see Core RPC Methods.
electrum
Section titled “electrum”Connection settings for an Electrum-compatible server (e.g. Fulcrum).
electrum: host: "127.0.0.1" port: 50001| Parameter | Type | Description |
|---|---|---|
host | string | Electrum server hostname or IP |
port | integer | Electrum server port |
tls | object | null | TLS settings. Omit for plain TCP |
electrum.tls
Section titled “electrum.tls”electrum: host: "192.168.1.100" port: 50002 tls: enabled: true ca: verify: false client_cert: cert_path: "certs/client.crt" key_path: "certs/client.key"| Parameter | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Enable TLS |
ca.verify | boolean | true | Verify the server certificate against system CAs. Set to false for self-signed certificates |
ca.path | string | null | null | Path to a custom CA certificate file |
client_cert.cert_path | string | null | null | Path to client certificate (mTLS) |
client_cert.key_path | string | null | null | Path to client private key (mTLS) |
ca.verify defaults to true, requiring explicit opt-out for self-signed
certificates.
engine
Section titled “engine”History
Section titled “History”The workflow engine retains a history of finished workflows. A finished workflow will have a state of completed, cancelled, or failed.
Workflow results are retrieved by the endpoints GET /workflows and GET /workflows/{id}.
Default values are suitable for most use cases but can be tuned if needed.
engine: history_ttl: 120 history_max: 200| Parameter | Type | Default | Description |
|---|---|---|---|
history_ttl | integer | 120 | How long (in seconds) a finished workflow remains visible in the history |
history_max | integer | 200 | Maximum number of finished workflows to retain. Oldest are evicted first when the limit is reached |
Operational Notes:
- A workflow is added to history the moment it reaches a terminal state —
completed,cancelled, orfailed - Once
history_maxis reached, the oldest entry is evicted to make room for the newest, regardless of its age - Once
history_ttlexpires, a workflow will no longer appear in query results even if it is still within thehistory_maxlimit
data_stores
Section titled “data_stores”data_stores.rocks
Section titled “data_stores.rocks”RocksDB is the primary persistent store for workflow results and cached wallet data.
data_stores: rocks: path: "var/rocks" cache_size: "8MB"| Parameter | Type | Default | Description |
|---|---|---|---|
path | string | "var/rocks" | Directory for the RocksDB database |
cache_size | string | "8MB" | Block cache size allocated to RocksDB |
cache_size accepts human-readable byte sizes: B, KB / K, MB / M, GB / G,
TB / T. For example: "64MB", "1GB", "512M".
data_stores.blocks
Section titled “data_stores.blocks”A filesystem-backed cache for raw block data retrieved via core.getblock. Cached
blocks expire after time_to_live seconds. A cleanup task runs periodically to remove
expired entries.
data_stores: blocks: path: "var/blocks" time_to_live: 180 cleanup_interval: 5 cleanup_batch: 1000| Parameter | Type | Default | Description |
|---|---|---|---|
path | string | "var/blocks" | Directory for cached block data |
time_to_live | integer | 180 | Seconds before a cached block expires |
cleanup_interval | integer | 5 | Seconds between cleanup runs |
cleanup_batch | integer | 1000 | Maximum entries removed per cleanup run |
Advanced Tuning
Section titled “Advanced Tuning”data_stores.cache
Section titled “data_stores.cache”Named in-memory cache instances backed by Moka.
Three instances are used internally — workflow_data, core_batches, and
core_results — and all default to sensible values. Most deployments will not need
to adjust these.
data_stores: cache: workflow_data: max_capacity: 10000 time_to_live: 900 time_to_idle: 300 core_batches: max_capacity: 10000 time_to_live: 900 time_to_idle: 300 core_results: max_capacity: 10000 time_to_live: 900 time_to_idle: 300| Parameter | Type | Default | Description |
|---|---|---|---|
max_capacity | integer | 10000 | Maximum number of entries |
time_to_live | integer | 900 | Seconds before an entry expires after creation |
time_to_idle | integer | 300 | Seconds before an entry expires after last access |