Node Configuration
Introduction
CKB uses configuration files stored in <config-dir>
, which by default is the current working directory. You can change this using the -C <path>
argument to specify a different directory. For example:
ckb -C node1 run
- This command tells CKB to use the
node1/
directory as the config directory, where it expects to findckb.toml
and related files.
Different subcommands expect different config filenames:
ckb run
usesckb.toml
ckb miner
usesckb-miner.toml
ckb import
andckb export
also useckb.toml
The ckb init
command helps initialize a config directory by generating the necessary files. Some config files may refer to other files, such as chain.spec
in ckb.toml
, or system_cells
in a chain spec file. These referenced paths can be either absolute or relative to the config file’s own location. For example, with this directory structure:
ckb.toml
└── specs/dev.toml
└── cells/secp256k1_sighash_all
ckb.toml
would refer tospecs/dev.toml
dev.toml
would refer to the cell file ascells/secp256k1_sighash_all
This article covers the following configuration topics:
- Light client support and WSS access
- Proxy and onion routing support
- Fee estimator
- Run multiple nodes
Light Client Support & WSS Access
CKB full nodes support the Light Client Protocol by default. No configuration is needed — if you're running a standard full node, it will automatically respond to light client peers using the built-in P2P protocol.
Browsers cannot connect to P2P networks directly. Instead, they must connect to your node over WebSocket with TLS (wss://
). To support this, you need to deploy a TLS proxy in front of your node that converts WSS traffic into standard TCP.
Prerequisites for WSS Setup
Before you begin, ensure the following:
- Your CKB node running and listening on its default P2P port (
8115
) - You have deployed a CKB node (v0.200.0 or later) and it is running normally.
- You own a domain name and can modify its DNS records (e.g., via Cloudflare, Namecheap, or Alibaba Cloud).
- You have a valid TLS certificate for your domain (You can use a commercial provider like DigiCert or a free tool like Certbot.)
- Your server has ports 80 and 443 open to the public.
- Nginx is installed with the Stream module enabled, which will be used to forward encrypted WebSocket traffic to the CKB node.
Check If Nginx Has the Stream Module
nginx -V 2>&1 | grep -- --with-stream
If you see --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module
, you're good to go.
If not, you must recompile Nginx with these flags:
./configure \
--prefix=/usr/local/nginx \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module
Working Example of Nginx Config
Here’s a working example that:
- Routes TCP (P2P) and WSS traffic differently based on TLS version
- Proxies WSS traffic to a separate internal port (8443)
You need to replace:
ckb.example.com
with your domain8118
with your node’s P2P port443
with the external public port- TLS cert paths with your actual file paths
# Global settings
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
# TCP/TLS stream routing
stream {
log_format stream_log '$remote_addr - $remote_port [$time_local] '
'Protocol: $ssl_preread_protocol '
'Status: $status '
'Bytes_Sent: $bytes_sent '
'Bytes_Received: $bytes_received '
'Session_Time: $session_time '
'Upstream: $upstream_addr';
map $ssl_preread_protocol $upstream {
default backend_tcp;
"TLSv1.2" backend_wss_http;
"TLSv1.3" backend_wss_http;
}
upstream backend_tcp {
server 127.0.0.1:8118;
}
upstream backend_wss_http {
server 127.0.0.1:8443;
}
server {
listen 443;
proxy_pass $upstream;
ssl_preread on;
access_log /var/log/nginx/stream_access.log stream_log;
error_log /var/log/nginx/stream_error.log;
}
}
# WSS HTTP proxy (for browsers)
http {
sendfile on;
keepalive_timeout 65;
client_max_body_size 10m;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
server {
listen 8443 ssl;
server_name ckb.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8118;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
}
Traffic Routing Summary
Client Type | Route |
---|---|
TCP | TCP Client -> ckb.example.com:443 -> Nginx (stream, ssl_preread) -> backend_tcp -> [ckb node 8118] |
WSS | WSS Client -> ckb.example.com:443 -> Nginx (stream, ssl_preread) -> backend_wss_http -> 127.0.0.1:8443 -> Nginx (http, TLS decryption, WebSocket) -> [ckb node 8118] |
Reload Nginx
sudo nginx -t
sudo nginx -s reload
Add DNS Record
Go to your DNS provider and add an A record pointing ckb.example.com
to your server’s public IP.
Modify Config to Advertise Your Public Address
Uncomment the public_addresses
in your ckb.toml
.
### Specify the public and routable network addresses
public_addresses = ["/dns4/ckb.example.com/tcp/443"]
Remember to replace ckb.example.com
with your own domain.
Then restart your CKB node.
Verify Configuration
- Check your node’s public address:
- Command
- Response
curl -s -H "Content-Type: application/json" \
-d '{ "id": 2, "jsonrpc": "2.0", "method": "local_node_info", "params": [] }' \
http://127.0.0.1:8114 | jq '.result.addresses[].address'
"/dns4/ckb.example.com/tcp/443/p2p/<PeerID>"
- Use it as a bootnode in another node
Initialize a new CKB node (v.0.200.0 or later). Update the bootnodes section in ckb.toml
to the following:
bootnodes = ["/dns4/ckb.example.com/tcp/443/p2p/<PeerID>"]
Remember to replace <PeerID>
with the one you retrieved from step 1.
For the wasm-based light client in browsers, the address should start with wss
:
bootnodes = ["/dns4/ckb.example.com/tcp/443/wss/p2p/<PeerID>"]
- Start the second node
Start the second node and check the logs. If it begins syncing blocks successfully, your WSS setup is complete.
Proxy and Onion Routing Support
CKB supports advanced networking configurations for users who want to:
- Preserve privacy by hiding their node’s IP address
- Route traffic through a proxy (e.g., SOCKS5)
- Expose their node on the Tor network using an
.onion
address
These are useful for censorship resistance, secure relayers, and privacy-focused deployments.
ProxyConfig
The [network.proxy]
section allows your node to route outbound P2P connections through a SOCKS5 proxy, such as the one provided by a Tor server.
[network.proxy]
proxy_url = "socks5://127.0.0.1:9050"
proxy_random_auth = true
proxy_url
: The URL of your SOCKS5 proxy.- Default Tor proxy:
socks5://127.0.0.1:9050
- If you're running a local Tor server, this will work out of the box.
- Default Tor proxy:
proxy_random_auth
: When enabled, CKB generates a random username and password per connection, improving privacy (like Tor'sIsolateSOCKSAuth
).- Recommended for Tor usage
- If using a non-Tor proxy that supports but doesn’t require authentication, you may need to set this to
false
to avoid connection failures.
OnionConfig
The [network.onion]
section in ckb.toml
allows your node to act as a Tor hidden service, accepting inbound connections over the .onion
network.
[network.onion]
listen_on_onion = true
onion_service_target = "127.0.0.1:8115"
onion_server = "127.0.0.1:9050"
tor_controller = "127.0.0.1:9051"
tor_password = ""
listen_on_onion
: Enables listening for incoming connections over the Tor network. Iftrue
, your node will publish a.onion
address and accept Tor traffic.onion_service_target
: The local address your Onion service will forward to — usually your CKB node’s P2P port. It sets to127.0.0.1:8115
by default.onion_server
: SOCKS5 proxy used to connect to other.onion
addresses.- If unset, CKB will use the proxy defined in
[network.proxy]
.
- If unset, CKB will use the proxy defined in
tor_controller
: The address of the Tor ControlPort, which CKB uses to register or manage Onion services. It sets to127.0.0.1:9051
by default.tor_password
: Password used to authenticate with the Tor ControlPort.- You can leave it empty if the Tor ControlPort allows unauthenticated access (not recommended for production).
- The password must match the
HashedControlPassword
in yourtorrc
file.
Fee Estimator
The Fee Estimator is an experimental feature introduced in CKB v0.120.0 to help developers and users determine optimal transaction fee rates based on recent block activity.
To use the Fee Estimator, you must:
- Specify a fee estimation algorithm in
ckb.toml
[fee_estimator]
## Specifies the fee estimates algorithm. Current algorithms: ConfirmationFraction, WeightUnitsFlow.
algorithm = "WeightUnitsFlow"
- Make sure the
Experiment
module is included in the list inckb.toml
. This module is enabled by default.
# List of API modules: ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment", "Debug", "Indexer", "RichIndexer"]
modules = ["Net", "Pool", "Miner", "Chain", "Stats", "Subscription", "Experiment"]
Once your node is running and synced, you can query the estimated fee rate using:
echo '{ "id": 1, "jsonrpc": "2.0", "method": "estimate_fee_rate", "params": [] }' \
| curl -s -H "Content-Type: application/json" -d @- "http://localhost:8114" \
| jq
result:
{
"jsonrpc": "2.0",
"result": "0x3e8",
"id": 1
}
Check out this spec to learn more about fee estimator.
Run Multiple Nodes
You can run multiple CKB nodes on the same machine (e.g., for local Devnet testing) by setting up separate configuration directories and customizing their ports.
- Create separate directories for each node by running :
mkdir node1 node2
- Initialize each node with the same dev chain and genesis message.
Each CKB node requires its own configuration directory. You can specify the directory using the -C <path>
option, which tells CKB where to store the node’s config files and chain data.
When using the dev
chain, nodes will generate a random genesis block unless you explicitly set the same --genesis-message
. Nodes with different genesis blocks cannot connect to each other, so it’s important to use the same message across all Devnet nodes.
ckb -C node1 init --chain dev --genesis-message dev-genesis
ckb -C node2 init --chain dev --genesis-message dev-genesis
dev-genesis
is just an example — you can replace it with any string as long as it’s identical.
genesis-message
is only required for the dev
chain. Mainnet and testnet use fixed genesis blocks and do not require --genesis-message
.
- Edit
node2/ckb.toml
to avoid port conflicts: In your node2’sckb.toml,
change the default ports:- RPC port (
8114
) →8116
- P2P port (
8115
) →8117
- RPC port (
[rpc]
listen_address = "127.0.0.1:8116"
[p2p]
listen_address = "/ip4/0.0.0.0/tcp/8117"
- Start node1:
ckb -C node1 run
- Optional: Connect node2 to node1
- Find the P2P address from node1 logs (e.g.,
/ip4/127.0.0.1/tcp/8115/p2p/PeerID
) - Add it to
bootnodes
innode2/ckb.toml
:
bootnodes = ["/ip4/127.0.0.1/tcp/8115/p2p/PeerID"]
Remeber to replace PeerID
with your actual one.
- Start node2:
ckb -C node2 run