ChainOS Node Configuration
Configuration Overview
This guide provides detailed information on configuring your ChainOS node for optimal performance and security. Proper configuration is essential for stable node operation and network participation.
Configuration Files
ChainOS uses several configuration files located in the ~/.chainosd/config/
directory:
Primary Configuration Files
- config.toml: Main configuration file for the node (consensus, p2p, etc.)
- app.toml: Application-specific configuration (API, state sync, etc.)
- client.toml: Client configuration for the CLI
- genesis.json: Initial state of the blockchain
- priv_validator_key.json: Private key for validator operations (validators only)
- node_key.json: Private key for p2p communication
Security Warning
The priv_validator_key.json
file contains sensitive private key information. For validators, it's crucial to secure this file properly. Consider using a Hardware Security Module (HSM) for production validators.
config.toml Configuration
The config.toml
file contains settings for the consensus engine and networking components. Here are the key sections and parameters:
Base Configuration
# TCP or UNIX socket address of the ABCI application,
# or the name of an ABCI application compiled in with the Tendermint binary
proxy_app = "tcp://127.0.0.1:26658"
# A custom human readable name for this node
moniker = "my-node-name"
# Database backend: goleveldb | cleveldb | boltdb | rocksdb
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
# * cleveldb (uses levigo wrapper)
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
# * rocksdb (uses github.com/tecbot/gorocksdb)
db_backend = "goleveldb"
# Database directory
db_dir = "data"
# Output level for logging, including package level options
log_level = "info"
Recommended changes:
- moniker: Set a unique, descriptive name for your node
- db_backend: For high-performance nodes, consider using "rocksdb"
- log_level: Use "info" for normal operation, "debug" for troubleshooting
RPC Configuration
[rpc]
# TCP or UNIX socket address for the RPC server to listen on
laddr = "tcp://127.0.0.1:26657"
# A list of origins a cross-domain request can be executed from
# Default value '[]' disables cors support
# Use '["*"]' to allow any origin
cors_allowed_origins = []
# Maximum number of simultaneous connections
max_open_connections = 1000
# Maximum number of unique client subscriptions
max_subscription_clients = 100
Recommended changes:
- laddr: For public nodes, change to "tcp://0.0.0.0:26657" to allow external connections
- cors_allowed_origins: For API services, set appropriate CORS origins
- max_open_connections: Adjust based on expected load (higher for public API nodes)
Security Note
When exposing RPC endpoints publicly, ensure you have proper firewall rules and rate limiting in place to prevent abuse.
P2P Configuration
[p2p]
# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"
# Maximum number of inbound peers
max_num_inbound_peers = 40
# Maximum number of outbound peers to connect to, excluding persistent peers
max_num_outbound_peers = 10
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
unconditional_peer_ids = ""
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
private_peer_ids = ""
# Toggle to disable guard against peers connecting from the same ip
allow_duplicate_ip = false
# Peer connection configuration
handshake_timeout = "20s"
dial_timeout = "3s"
# Comma separated list of seed nodes to connect to
seeds = "2b89c755963a03a2a2c846d5efb97c06e6d2cdfe@seed.chainos.network:26656,3b89c755963a03a2a2c846d5efb97c06e6d2cdfe@seed2.chainos.network:26656"
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "2b89c755963a03a2a2c846d5efb97c06e6d2cdfe@chainos.network:26656"
Recommended changes:
- max_num_inbound_peers, max_num_outbound_peers: Increase for better network connectivity (60/20 for validators)
- seeds, persistent_peers: Update with reliable seed nodes and peers
- handshake_timeout, dial_timeout: Increase for nodes with slower network connections
Consensus Configuration
[consensus]
# How long we wait for a proposal block before prevoting nil
timeout_propose = "3s"
# How long we wait after receiving +2/3 prevotes for "anything" (i.e. not a single block or nil)
timeout_prevote = "1s"
# How long we wait after receiving +2/3 precommits for "anything" (i.e. not a single block or nil)
timeout_precommit = "1s"
# How long we wait after committing a block, before starting on the new height
timeout_commit = "1s"
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
skip_timeout_commit = false
# EmptyBlocks mode and possible interval between empty blocks
create_empty_blocks = true
create_empty_blocks_interval = "0s"
Recommended changes:
- timeout_commit: Default is optimal for most cases
- create_empty_blocks: Set to false to reduce chain bloat (but may affect some applications)
State Sync Configuration
[statesync]
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
# snapshot from peers instead of fetching and replaying historical blocks
enable = false
# RPC servers (comma-separated) for light client verification of the synced state machine and
# retrieval of state data for node bootstrapping
rpc_servers = "chainos.network:26657,chainos-backup.network:26657"
# Trusted block height
trust_height = 0
# Trusted block hash
trust_hash = ""
# Trusted block header provider
trust_period = "168h0m0s"
To enable state sync (for faster node synchronization):
- Set
enable = true
- Set
rpc_servers
to reliable RPC endpoints - Get a recent block height and its hash from a trusted source
- Set
trust_height
to that block height - Set
trust_hash
to that block's hash
State Sync Tip
You can get a recent block height and hash by running:
curl -s "chainos.network:26657/block?height=3500000" | jq -r '.result.block_id.hash'
Replace 3500000 with a recent block height.
app.toml Configuration
The app.toml
file contains application-specific settings. Here are the key sections:
API Configuration
[api]
# Enable defines if the API server should be enabled.
enable = true
# Address defines the API server to listen on.
address = "tcp://0.0.0.0:1317"
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
enabled-unsafe-cors = false
Recommended changes:
- enable: Set to true to enable the REST API
- address: Change to "tcp://127.0.0.1:1317" for local-only access, or "tcp://0.0.0.0:1317" for public access
- enabled-unsafe-cors: Only enable if you need cross-origin requests (with proper security measures)
gRPC Configuration
[grpc]
# Enable defines if the gRPC server should be enabled.
enable = true
# Address defines the gRPC server address to bind to.
address = "0.0.0.0:9090"
Recommended changes:
- enable: Set to true if you need gRPC services
- address: Change to "127.0.0.1:9090" for local-only access
Telemetry Configuration
[telemetry]
# Enabled enables the application telemetry functionality. When enabled,
# an in-memory sink is also enabled by default. Operators may also enabled
# other sinks such as Prometheus.
enabled = true
# Enable prefixing gauge values with hostname.
enable-hostname = false
# Enable adding hostname to labels.
enable-hostname-label = false
# Enable adding service to labels.
enable-service-label = false
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
prometheus-retention-time = 0
Recommended changes:
- enabled: Set to true to enable metrics collection
- prometheus-retention-time: Set to 60 (seconds) to enable Prometheus metrics
Pruning Configuration
[pruning]
# Pruning strategy:
# - "nothing": All historic states will be saved, nothing will be deleted (i.e. archiving node).
# - "everything": All saved states will be deleted, storing only the current state.
# - "custom": Allow pruning options to be manually specified through 'pruning-keep-recent',
# 'pruning-keep-every', and 'pruning-interval'.
pruning = "default"
# These are applied if and only if the pruning strategy is custom.
pruning-keep-recent = "100"
pruning-keep-every = "0"
pruning-interval = "10"
Recommended settings for different node types:
- Archive Node: Set
pruning = "nothing"
- Full Node: Use default settings
- Validator Node: Set
pruning = "custom"
withpruning-keep-recent = "100"
- Resource-Constrained Node: Set
pruning = "everything"
(minimal storage requirements)
client.toml Configuration
The client.toml
file contains settings for the CLI client:
# Chain ID to sign with
chain-id = "chainos-1"
# Keyring backend, options: os|file|kwallet|pass|test|memory
keyring-backend = "os"
# CLI output format (text|json)
output = "text"
# Node to connect to
node = "tcp://localhost:26657"
# Transaction broadcast mode (sync|async|block)
broadcast-mode = "sync"
Recommended changes:
- chain-id: Set to the correct chain ID ("chainos-1" for mainnet)
- keyring-backend: Use "file" for better security on servers
- node: Set to your preferred RPC endpoint
- broadcast-mode: Use "sync" for normal operations, "block" when you need immediate confirmation
Performance Optimization
Here are some recommended configurations for different types of nodes:
Validator Node Configuration
Recommended Settings
- db_backend: "rocksdb" for better performance
- max_num_inbound_peers: 60
- max_num_outbound_peers: 20
- pruning: "custom" with pruning-keep-recent = "100"
- indexer: "null" (disable indexing to save resources)
- persistent_peers: Add multiple reliable peers
API Node Configuration
Recommended Settings
- api.enable: true
- api.address: "tcp://0.0.0.0:1317" (with proper firewall rules)
- grpc.enable: true
- grpc.address: "0.0.0.0:9090" (with proper firewall rules)
- rpc.max_open_connections: 1000 or higher
- pruning: "default" or "custom" with larger keep-recent value
- indexer: "kv" (enable indexing for API queries)
Archive Node Configuration
Recommended Settings
- pruning: "nothing" (keep all historical states)
- indexer: "kv" (enable indexing for historical queries)
- state_sync.enable: false (archive nodes should sync from genesis)
- db_backend: "rocksdb" for better performance with large datasets
Advanced Configuration
For advanced users, here are some additional configuration options:
Custom Indexer Configuration
[tx_index]
# What indexer to use for transactions
#
# The application will set which txs to index. In some cases a node operator will be able
# to decide which txs to index based on configuration set in the application.
#
# Options:
# 1) "null"
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
indexer = "kv"
# The events to index.
# Example:
# index_events = ["message.sender", "message.recipient"]
index_events = []
For better transaction querying capabilities:
- Set
indexer = "kv"
- Add relevant events to
index_events
, such as["message.sender", "message.recipient", "transfer.recipient"]
Mempool Configuration
[mempool]
# Maximum number of transactions in the mempool
size = 5000
# Maximum size of a single transaction
max_tx_bytes = 1048576
# Maximum size of all transactions in the mempool
max_txs_bytes = 1073741824
# Size of the cache (used to filter transactions we saw earlier)
cache_size = 10000
For high-throughput nodes:
- Increase
size
to 10000 or higher - Increase
cache_size
to 20000 or higher
Configuration Examples
Here are some example configurations for different node types:
Validator Node Example
# config.toml
[rpc]
laddr = "tcp://127.0.0.1:26657" # Local access only for security
[p2p]
laddr = "tcp://0.0.0.0:26656"
max_num_inbound_peers = 60
max_num_outbound_peers = 20
persistent_peers = "2b89c755963a03a2a2c846d5efb97c06e6d2cdfe@chainos.network:26656,3b89c755963a03a2a2c846d5efb97c06e6d2cdfe@chainos-backup.network:26656"
[mempool]
size = 10000
cache_size = 20000
[tx_index]
indexer = "null" # Save resources by disabling indexing
# app.toml
[pruning]
pruning = "custom"
pruning-keep-recent = "100"
pruning-keep-every = "0"
pruning-interval = "10"
[api]
enable = false # Disable API for security
[grpc]
enable = false # Disable gRPC for security
[telemetry]
enabled = true
prometheus-retention-time = 60 # Enable Prometheus metrics
API Node Example
# config.toml
[rpc]
laddr = "tcp://0.0.0.0:26657" # Public access
max_open_connections = 1000
cors_allowed_origins = ["*"] # Allow all origins (with proper security measures)
[p2p]
laddr = "tcp://0.0.0.0:26656"
max_num_inbound_peers = 40
max_num_outbound_peers = 10
[tx_index]
indexer = "kv"
index_events = ["message.sender", "message.recipient", "transfer.recipient"]
# app.toml
[pruning]
pruning = "default"
[api]
enable = true
address = "tcp://0.0.0.0:1317"
enabled-unsafe-cors = true # Enable CORS (with proper security measures)
[grpc]
enable = true
address = "0.0.0.0:9090"
[telemetry]
enabled = true
prometheus-retention-time = 60
Need Help?
If you need assistance with your node configuration, join our Discord community where our team and other node operators can help.