Skip to main content

Self-Host a Node

You can host a node without using the ZenChain Station app. This guide will walk you through the steps to set up a node and become a validator. It requires technical expertise and is recommended for advanced users. If you choose to self-host, it’s assumed you’re familiar with Docker, shell commands, and general blockchain concepts.

warning

We recommend hosting the node in a cloud environment to ensure it runs 24/7 with minimal to no downtime. If your node goes offline unexpectedly, your stake could be slashed. Setting up a cloud environment is beyond the scope of this guide.

Run a node

We provide instructions on running a node using a Docker image, a pre-written Dockerfile, or without Docker. Although running the node on "bare metal" can give slight performance benefits, we recommend using the published Docker image as it’s the easiest option.

Docker Image

To help you get started quickly, we provide a Docker image of the latest release hosted on GitHub Container Registry (GHCR). The recommended production setup will be explained later.

You can pull the image directly with this command:

docker pull ghcr.io/zenchain-protocol/zenchain-testnet:latest

And run it from the command line.

# development
docker run \
-d \
--name zenchain \
-p 9944:9944 \
-v ./chain-data:/chain-data \
ghcr.io/zenchain-protocol/zenchain-testnet:latest \
./usr/bin/zenchain-node \
--dev

# production
docker run \
-d \
--name zenchain \
-p 9944:9944 \
-v ./chain-data:/chain-data \
ghcr.io/zenchain-protocol/zenchain-testnet:latest \
./usr/bin/zenchain-node \
--base-path=/chain-data \
--rpc-cors=all \
--validator \
--name=ILoveZenchain \
--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE \
--chain=zenchain_testnet

Alternatively, you can include this setup in a Docker Compose file.

# development
services:
zenchain:
image: ghcr.io/zenchain-protocol/zenchain-testnet:latest
platform: linux/amd64
container_name: zenchain
ports:
- "9944:9944"
command:
- "./usr/bin/zenchain-node"
- "--dev"

# production
services:
zenchain:
image: ghcr.io/zenchain-protocol/zenchain-testnet:latest
platform: linux/amd64
container_name: zenchain
ports:
- "9944:9944"
volumes:
- ./chain-data:/chain-data
command:
- "./usr/bin/zenchain-node"
- "--base-path=/chain-data"
- "--rpc-cors=all"
- "--validator"
- "--name=ILoveZenchain"
- "--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE"
- "--chain=zenchain_testnet"

Fresh Build With Docker

We provide a Dockerfile within the Zenchain node's GitHub repository that can be used to build a development image. We'll walk you through the steps.

Clone the Repo

First, clone the node repository from GitHub and navigate to the root directory.

git clone https://github.com/zenchain-protocol/zenchain-node.git
cd ./zenchain-node

Production or Development?

The main difference between the development image and the production image is the command used to build the node. If you will run the node as a Zenchain validator, you can modify the Dockerfile for a production build. Locate the build command cargo build --release and change it to use the "production" build profile.

# development
cargo build --release

# production
cargo build --profile=production

Build and Run

To build and run the image, run the following commands from the root of the repo. The image may take over 20 minutes to build initially. By default, the node uses port 9944.

docker build -t zenchain-node .

# development
docker run -t zenchain-node --dev

# production
docker run -t zenchain-node \
--base-path=/chain-data \
--rpc-cors=all \
--validator \
--name="Your node name" \
--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE \
--chain=zenchain_testnet

Fresh Build Without Docker

To run the node without Docker, you’ll need to have the Rust toolchain installed. If it’s not already installed, follow the instructions on the Rust programming language website.

For Linux, MacOS, and Windows, you may need extra dependencies.

Additional Dependencies for Linux

Execute the following command (Ubuntu as reference):

sudo apt install -y clang libssl-dev llvm libudev-dev pkg-config protobuf-compiler make

Additional Dependencies for MacOS

If you have an Apple M1 ARM system, you must install Apple Rosetta 2:

softwareupdate --install-rosetta

Execute the following command to install additional deps:

brew install openssl
brew install protobuf

Additional Dependencies for Windows

LLVM: Download and execute the installer "https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.2/LLVM-18.1.2-win64.exe"

Download the Protocol Buffers package: "https://github.com/protocolbuffers/protobuf/releases/download/v26.1/protoc-26.1-win64.zip"

Once downloaded, extracts all files in a choosen path; then create the PROTOC environment variable that points to the protocol buffer executable, for example:

setx PROTOC C:\protoc\bin\protoc.exe /m

then restart the shell.

Clone the Repo

Once your environment is set up, you are ready to clone the node repository from GitHub and navigate to the repository root directory.

git clone https://github.com/zenchain-protocol/zenchain-node.git
cd ./zenchain-node

Build the Node

The Zenchain node and runtime are written in Rust, so we will use the Cargo CLI tool to build the node. If you will use the node as a validator, make sure to build it with the "production" build profile instead of "release".

# development
cargo build --release

# production
cargo build --profile=production

The node can take more than 20 minutes to build for the first time. Subsequent builds are significantly faster due to caching. The "release" build profile compiles faster by skipping performance optimizations.

Run the Node

You can now run the node with the executable you built in the previous step. The node uses port 9944 by default. The recommended production configuration will be explained shortly.

# development
./target/production/zenchain-node --dev

# production
./target/production/zenchain-node \
--base-path=/chain-data \
--rpc-cors=all \
--validator \
--name="Your node name" \
--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE \
--chain=zenchain_testnet

Configuration

We recommend initially running a validator node with the following command line arguments. The table explains the purpose of each option. We will soon change this configuration to prevent unsafe RPC calls, but for now it is important to use the --unsafe-rpc-external argument so you can update the node's "session keys" and connect the node to your Ethereum account.

--base-path=/chain-data
--rpc-cors=all
--unsafe-rpc-external
--validator
--name="Your node name"
--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE
--chain=zenchain_testnet
OptionExplanation
--base-path=/chain-dataWhere your node's database will be stored
--rpc-cors=allEnable CORS to allow RPC requests that originate in a browser environment
--unsafe-rpc-externalEnable all RPC methods, including unsafe methods
--validatorRun as a validator node
--nameAny name you want!
--bootnodes=...Node's initial bridge to the network. Do not change this!
--chain=zenchain_testnetTells the node to know which chain specification to use. Do not change this!

Session Keys

Your node is identified in Zenchain's consensus protocol by Session Keys, which are comprised of accounts for three consensus mechanisms: RAGE, GUARDIAN, and "I'm Online". RAGE is responsible for block production, GUARDIAN is responsible for block finality, and "I'm Online" tells the network that your node is online during the active session.

Generate Session Keys

To generate Session Keys for your node, you need to complete an RPC call author_rotateKeys using your node's RPC endpoint. The RPC method will generate new Session Keys, insert them into your node's secure keyring, and return the full set of public keys in serialized form as a hex string. You will need the output of the RPC call for the next step.

info

Zenchain nodes support the JSON-RPC 2.0 standard format.

Set Keys for your Ethereum Account

Using the output from the author_rotateKeys RPC call, submit a transaction calling the setKeys function of the KeyManager precompile. The transaction will associate the Session Keys with your Ethereum account.

Key Manager Precompile

ContractEthereum AddressSolidity Interface
KeyManager0x0000000000000000000000000000000000000802GitHub

Using the polkadotjs-apps Tool

Zenchain is compatible with some tools in the Substrate ecosystem. You can use the polkadotjs-apps tool, originally created for the Polkadot blockchain, for a simple session key generation UX. Refer to the polkadotjs-apps documentation here for more information: https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#generating-the-session-keys.

You can use the polkadotjs-apps tool with an injected Ethereum wallet, such as MetaMask. To ensure the app works correctly with your wallet, you'll need to make sure an app setting is configured correctly. Go to the app's "Settings" in the top toolbar. From the "General" tab, make sure the "in-browser account creation" option is set to "Allow local in-browser account storage". Your wallet should now work as expected.

Update Node Configuration and Restart

Now that you've set your session keys with the rotateKeys RPC method and the setKeys transaction, you can restart your node with an updated configuration to prevent unsafe RPC calls. You can also remove CORS support from the configuration since RPC will be disabled.

--base-path=/chain-data
--validator
--name="Your node name"
--bootnodes=/dns4/node-7242611732906999808-0.p2p.onfinality.io/tcp/26266/p2p/12D3KooWLAH3GejHmmchsvJpwDYkvacrBeAQbJrip5oZSymx5yrE
--chain=zenchain_testnet

Unlike an archive node, which may be used as a secure RPC endpoint, it is not possible to run a validator node with the --rpc-external and --rpc-methods=Safe options. If you do not enable RPC requests, you will not be able to submit transactions or make other RPC requests to the node. However, validator nodes are not typically used as RPC endpoints. Keeping the --unsafe-rpc-external option enabled is insecure. We highly recommend restarting your validator node with the --unsafe-rpc-external flag removed from your configuration.

Stake ZCX and Request to Validate

Once you've set your Session Keys, you're ready to submit a request to validate.

You can use the Zenchain Station to stake ZCX and change your staker status to "Validator".

Alternatively, you can stake ZCX via transactions and call the validate() function in the NativeStaking precompile contract.

Please refer to our staking guide, How to Stake, for step-by-step instructions.

info

To be a validator, you must have a minimum amount of ZCX staked. Learn more about staking, validating, and the minimum amount of staked ZCX required for validators.