VIZ Ledger nodes are configured via an INI file. The repository ships several templates in share/vizd/config/:
| Template | Use case |
|---|---|
config.ini |
Full mainnet node with public RPC |
config_witness.ini |
Validator node (localhost RPC, block production) |
config_testnet.ini |
Testnet / development |
config_stock_exchange.ini |
Market data consumer (minimal plugins) |
config_debug.ini |
Debug mode |
# Listen address for P2P connections (port 2001 standard)
p2p-endpoint = 0.0.0.0:2001
# Maximum peer connections (unlimited if unset)
p2p-max-connections = 200
# Seed nodes to bootstrap connectivity (repeatable)
p2p-seed-node = seed3.viz.world:2001
p2p-seed-node = seed1.viz.world:2001
p2p-seed-node = rpc.viz.cx:2001
# Checkpoints: trusted (block_num, block_id) pairs (repeatable)
# checkpoint = [12345,"0003039..." ]# HTTP JSON-RPC endpoint
webserver-http-endpoint = 0.0.0.0:8090
# WebSocket JSON-RPC endpoint
webserver-ws-endpoint = 0.0.0.0:8091
# RPC thread pool size
webserver-thread-pool-size = 2Security note: For validator nodes, bind to
127.0.0.1to prevent external access:webserver-http-endpoint = 127.0.0.1:8090 webserver-ws-endpoint = 127.0.0.1:8091
# Microseconds to wait for a read lock before retrying
read-wait-micro = 500000
# Maximum read lock retry attempts
max-read-wait-retries = 2
# Microseconds to wait for a write lock before retrying
write-wait-micro = 500000
# Maximum write lock retry attempts
max-write-wait-retries = 3
# Serialize all write operations on a single thread (recommended)
single-write-thread = true
# Run plugin notifications on push_transaction (adds latency; default false)
enable-plugins-on-push-transaction = falseThe blockchain state is stored in a memory-mapped file (shared_memory.bin).
# Initial size of the shared memory file
shared-file-size = 4G
# Minimum free space before triggering a resize
min-free-shared-file-size = 500M
# Amount to grow the file by on resize
inc-shared-file-size = 2G
# Check free space every N blocks
block-num-check-free-size = 1000Tune shared-file-size based on chain size. For mainnet, start at 4G and monitor growth.
# Each 'plugin' line adds a plugin (repeatable)
# Minimum set for a full API node:
plugin = chain p2p webserver json_rpc database_api network_broadcast_api
# Additional indexing plugins (comment out on low-memory nodes):
plugin = account_history account_by_key
plugin = committee_api invite_api paid_subscription_api custom_protocol_api
# For validator nodes only:
plugin = validator validator_api| Node type | Plugins |
|---|---|
| Full node | All above |
| Validator | chain p2p webserver json_rpc database_api network_broadcast_api validator validator_api |
| Low-memory seed | chain p2p |
| Stock exchange | chain p2p webserver json_rpc database_api network_broadcast_api account_history |
# Discard vote objects before this block (saves memory, default 0 = keep all)
clear-votes-before-block = 0
# Skip indexing virtual operations (saves memory on validators)
skip-virtual-ops = false
# Track account history only for accounts in range (optional)
# track-account-range = ["alice","alice.zzz"]
# Whitelist/blacklist specific operation types for history
# history-whitelist-ops = transfer_operation
# history-blacklist-ops = custom_operation
# Start indexing history from this block number
# history-start-block = 1000000
# Private message tracking range (optional, example plugin)
# pm-account-range = ["alice","alice.zzz"]Leave these unset on non-validator nodes.
# Allow production even if chain is stale (development/testnet only)
enable-stale-production = false
# Disable minority-fork detection (single-operator testnet/fork ONLY).
# Unlike enable-stale-production, this is never auto-cleared by healthy
# participation. Never enable on a real public network.
disable-minority-fork-detection = false
# Minimum participation % required to produce blocks (0–99)
required-participation = 33
# Validator account name (repeatable for multiple validators on one node)
validator = alice
# WIF signing key for the validator
private-key = 5JxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxWIF
# Emergency consensus private key (optional)
# emergency-private-key = 5Jxxx...See Validator Node for full validator configuration.
# Console logger (outputs to stderr)
log.console_appender.stderr.stream = std_error
# File logger for P2P messages
log.file_appender.p2p.filename = logs/p2p/p2p.log
# Log level: all, debug, info, warn, error, off
logger.default.level = warn
logger.default.appenders = stderr
logger.p2p.level = warn
logger.p2p.appenders = p2pThe file appender rotates by time: a new file every hour, kept for a day.
Both numbers and both switches are configuration of the section, not constants:
log.file_appender.p2p.filename = logs/p2p/p2p.log
log.file_appender.p2p.flush = true
log.file_appender.p2p.rotate = true
log.file_appender.p2p.rotation_interval = 3600 # seconds in one file
log.file_appender.p2p.rotation_limit = 86400 # seconds rotated files are keptflush, rotate, rotation_interval and rotation_limit are read from the ini; a section
without them keeps the historical values above, so an existing config behaves exactly as
before. Rotation requires rotation_interval >= 1 s and rotation_limit >=
rotation_interval (the appender asserts this pair). A value that cannot be parsed, a
violating pair, or an unknown key in a log.file_appender.* section is reported on stderr
and the default is kept — a typo must not cost the operator the log file, and a key that
does nothing is no longer accepted in silence. Binaries built before 2026-10-25 read only
filename: they honoured none of these keys and always rotated hourly with a one-day
retention.
Since 2026-10-25 the rotation is serviced by the appender's own thread, so it fires regardless of
what the main thread does. Binaries built before that date only rotated while the fc fiber
queue was serviced, and vizd does not service it after startup (measured 2026-10-20: a
testnet node wrote one 37 MB file in nine hours at info, with no hourly files; the mainnet
node ran four days without a new one) — such nodes still need external logrotate. Either
way, rotation bounds the file by time, not by size: at debug a node can write gigabytes
per hour. If all you need is the recent tail, use the optional capped appender:
a single file that keeps only the last max_lines lines (default 10000, 0 = unlimited).
It counts lines as it writes and compacts itself in place, so the file stays between
max_lines and about 1.1 x max_lines, with no timer involved. Nodes whose config has no
log.capped_file_appender.* section behave exactly as before, and the section itself is
safe to roll out ahead of the upgrade: an older binary ignores it and keeps logging to
stderr. If the configured path cannot be opened, the node still starts, prints one
capped_file_appender: cannot open log file … line to stderr, and simply leaves no file.
log.capped_file_appender.node.filename = logs/node/node.log
log.capped_file_appender.node.max_lines = 10000
# Route whatever you want into it; the appender alone writes nothing.
logger.default.appenders = stderr, nodeAll options listed by source file:
| Source | Options covered |
|---|---|
plugins/chain/plugin.hpp |
shared-file-size, min-free-shared-file-size, inc-shared-file-size, block-num-check-free-size, single-write-thread, enable-plugins-on-push-transaction, read-wait-micro, max-read-wait-retries, write-wait-micro, max-write-wait-retries, skip-virtual-ops, clear-votes-before-block, track-account-range, history-whitelist-ops, history-blacklist-ops, history-start-block |
plugins/p2p/p2p_plugin.hpp |
p2p-endpoint, p2p-max-connections, p2p-seed-node, checkpoint |
plugins/webserver/webserver_plugin.hpp |
webserver-http-endpoint, webserver-ws-endpoint, webserver-thread-pool-size |
plugins/validator/validator.hpp |
enable-stale-production, disable-minority-fork-detection, required-participation, validator, private-key, emergency-private-key, fork-collision-timeout-blocks, ntp-server, ntp-request-interval, debug-block-production |