Getting Started
System Requirements
Before setting up an ENI node, ensure your system meets the following minimum requirements:
Hardware Specifications
CPU
8 cores
16 cores
Modern processor (Intel Xeon/Core i7/i9 or AMD Epyc/Ryzen)
Memory
32GB
64GB
DDR4 or higher
Storage
1TB NVMe SSD
2TB NVMe SSD
High IOPS required; SATA SSD not recommended
Network
1Gbps
2Gbps
Low-latency connection is critical
Basic System Setup
Start with a fresh installation of Debian 12, Ubuntu 20.04 LTS (or higher). Then, update the system and install the necessary packages:
sudo apt update && sudo apt upgrade -y
sudo apt install make gcc git jq chrony curl lz4 wget tar build-essential -y
Tip: Ensure your system clock is synchronized (via
chrony
orntpd
) and your timezone is set to UTC to avoid potential issues with block validation, IBC transfers, etc.
Rapid deployment
Eni has a default configuration of four nodes for single-machine deployment, which can be used for rapid deployment and startup of the eni chain. If implementing commercialized deployment, please skip rapid deployment and start with custom deployment or automated setup scripts below.
Download the source code
git clone
Clone the go-eni project code from the eni code repository using the git tool.
git clone https://github.com/eni-chain/go-eni.git
One-click deployment
After downloading the code, enter the project directory go-eni. Then execute the following command to deploy and start a four-node eni blockchain on one machine with one click.
cd go-eni
git checkout main
make start4-node
The make start-4-node command will automatically perform the following operations:
Compile the go-eni project code, create the go-eni/build directory, and place the generated eni executable file in the go-eni/build directory.
Read node1~ node4 in the default configuration directory of go-eni/eni-nodes, and start the four nodes node1~ node4 according to the default configuration.
After the command execution is completed, if the following information is printed, it indicates that the chain compile deployment has started successfully.
Starting 4 eni nodes...
nohup ./build/enid start --home=./eni-nodes/node1 &> ./build/node1.log &
nohup ./build/enid start --home=./eni-nodes/node2 &> ./build/node2.log &
nohup ./build/enid start --home=./eni-nodes/node3 &> ./build/node3.log &
nohup ./build/enid start --home=./eni-nodes/node4 &> ./build/node4.log &
Done starting 4 eni nodes.
After startup, the log files of the node will be printed in the go-eni/build directory in real time. You can enter go-eni/build to view the log files of node1~ node4 and observe the operation of the chain and node.
% cd build
% ls
enid node1.log node2.log node3.log node4.log
% tail -f node1.log
6:27PM INF Time Commit end time=2025-04-17T18:27:48+08:00 module=server spend time=0
6:27PM INF Update fastMempool end block height=86 elapsedTime=0 module=mempool start time="Apr 17 18:27:48.572351" tx len=0
6:27PM INF committed state block_app_hash=FEADB503B8F5AA1D92C2E7D78DB10BD2F452ABD9E1EC1407E0937EC81C12A457 elapsed time=18826 height=86 module=state time now="Apr 17 18:27:48.572384"
6:27PM INF finalized block execute time elapsed=0.36 function elapsed =93.148 height=86 module=state time now="Apr 17 18:27:48.609816"
......
One-click close
Execute the following command to shut down the service with one click.
# return the upper directory "go-eni" from "build"
cd ..
# stop 4 node
make stop4-node
After the command is executed, if the following information is printed, it indicates that the service has been successfully shut down.
Stopping 4 eni nodes...
Done stopping 4 eni nodes.
After the service is shut down, it can be restarted by using the one-click deployment command make Start4-node. After startup, the chain still runs based on the last data. For example, if it was shut down when the block height was 88 last time, after this startup, the block height will start from 88.If you want to restart a chain from scratch, you need to clear the data from the last run and redeploy it with one click.
# clear the node data
make reset-multi-node
# build and start 4 node
make start4-node
Custom Deployment
If developers are not satisfied with rapid deployment based on default configuration and default Port Number, they can generate custom configurations and specify port deployment to start a chain.
Download the source code
git clone
Clone the go-eni project code from the eni code repository using the git tool.
git clone https://github.com/eni-chain/go-eni.git
Configuration generation
Enter the go-eni project directory and execute the following command to generate a custom configuration for the four nodes. The information such as the founder account and validator account in the configuration will be randomly generated. Because the default configuration already exists in the go-eni/eni-nodes directory, it is necessary to delete the default configuration directory before executing the custom configuration command.
cd go-eni
make build
#delete default config for 4 node
rm -rf eni-nodes
# Generate custom configuration. The current script supports 3 parameters.
# -1. Number of consensus nodes created (default 4);
# -2. Number of Staking accounts (default 4), which requires that the number of staking accounts must be greater than the number of consensus nodes;
# -3. Whether it is a single-machine deployment script (default true).
# Generate the multi-machine deployment configuration. After the configuration is generated, the persistent_peers ip of config.yaml needs to be modified manually. For details, please refer to the configuration Settings below
./generate_nodefile.sh 4 4 false
# Node peer id query command. Different configuration directories need to be specified on different nodes. For example, node2 needs to specify --home=./eni-nodes/node2
./build/enid comet show-node-id --home=./eni-nodes/node1
After the command is executed, a new custom configuration will be generated in the go-eni/eni-nodes directory, as shown in the following figure.

Here we need to focus on three documents:
node_key is the private key we use for network communication.
priv_validator_key is the private key used during the consensus period.
Keyring-test/validator1.info is the key file for collecting gas fee and block reward (there is no key by default, you can export the private key by the following command:
echo y | ./enid keys export validator1 --unarmored-hex --unsafe --home ../eni-nodes/node1
897c2fc636602de4e1ca89409ebd006edb927ec8bfa5aabd26ec94e51c0bd4d1
Configuration settings
After the custom configuration is generated, some configuration fields can be modified according to one's own needs.
app.toml configuration
The automatically generated app.toml file is missing EniDB Configuration and evm Configuration, so we need to manually append its content to the end of the app.toml file.
cat >> eni-nodes/node1/config/app.toml <<EOF
#############################################################################
### EniDB Configuration ###
#############################################################################
[state-commit]
# Enable defines if the state-commit (memiavl) should be enabled to override existing IAVL db backend.
sc-enable = true
# ZeroCopy defines if memiavl should return slices pointing to mmap-ed buffers directly (zero-copy),
# the zero-copied slices must not be retained beyond current block's execution.
# the sdk address cache will be disabled if zero-copy is enabled.
sc-zero-copy = false
# AsyncCommitBuffer defines the size of asynchronous commit queue, this greatly improve block catching-up
# performance, <=0 means synchronous commit.
sc-async-commit-buffer = 100
# SnapshotKeepRecent defines how many state-commit snapshots (besides the latest one) to keep
# defaults to 1 to make sure ibc relayers work.
sc-keep-recent = 1
# SnapshotInterval defines the block interval the snapshot is taken, default to 10000 blocks.
sc-snapshot-interval = 1000
# SnapshotWriterLimit defines the max concurrency for taking commit store snapshot
sc-snapshot-writer-limit = 2
# CacheSize defines the size of the LRU cache for each store on top of the tree, default to 100000.
sc-cache-size = 1000
[state-store]
# Enable defines if the state-store should be enabled for historical queries.
# In order to use state-store, you need to make sure to enable state-commit at the same time
ss-enable = true
# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "leveldb"
# AsyncWriteBuffer defines the async queue length for commits to be applied to State Store
# Set <= 0 for synchronous writes, which means commits also need to wait for data to be persisted in State Store.
# defaults to 100
ss-async-write-buffer = 100
# KeepRecent defines the number of versions to keep in state store
# Setting it to 0 means keep everything, default to 0
ss-keep-recent = 10000
# PruneIntervalSeconds defines the minimum interval in seconds + some random delay to trigger pruning.
# It is more efficient to trigger pruning less frequently with large interval.
# default to 600 seconds
ss-prune-interval = 60
# ImportNumWorkers defines the concurrency for state sync import
# defaults to 1
ss-import-num-workers = 1
[evm]
http_enabled = true
http_port = 8545
ws_enabled = true
ws_port = 8546
EOF
In the configuration of app.toml, the commonly used configuration item modifications are mainly the various fields under the state-store module and the evm module. Other fields generally use default values.
State-store module:
The ss-backend field specifies the database type. The optional database types can be found in the configuration comments. However, in daily life, the main choice is between leveldb and pebbledb. It is recommended that consensus nodes choose leveldb, which does not store historical data and can ensure higher consensus efficiency. It is recommended to choose pebbledb for synchronization nodes. For details, please refer to the appendix
EVM module:
http_enabled: whether the http service is enabled;
http_port: http Port Number, if it is a single deployment of multiple nodes, to avoid port conflicts, each node must be configured to different values.
ws_enabled: whether the websocket service is enabled;
ws_port: websocket Port Number, if it is a single machine deployment of multiple nodes, to avoid port conflicts, each node must be configured to different values.
[state-store]
# Enable defines if the state-store should be enabled for historical queries.
# In order to use state-store, you need to make sure to enable state-commit at the same time
ss-enable = true
# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "leveldb"
[evm]
http_enabled = true
http_port = 8545
ws_enabled = true
ws_port = 8546
Note: The configuration fields of the above common modification items can be configured to different values for each node according to its own situation, which will not affect the consensus consistency.
Contract administrator configuration
If the chain does not start the dpos mechanism, the consensus node set is the initial value configured by the genutil.gen_txs configuration item in the genesis.json configuration file (see the genesis.json configuration section for details). In the current version, we use the consensus mechanism that does not start the dpos, which has met the needs during the x play period.
However, for chain security, we still need to pay attention to the setting of the dpos administrator address to ensure that the key pair corresponding to the administrator address is managed by the official.Administrator privileges are crucial for the DPOS mechanism and consensus system. Therefore, if it is a custom-deployed chain, the default administrator address needs to be modified. The system contract of the DPOS series has a default administrator who is used to do some chain management work, including:
Set the initialization random value seed: In the DPOS mechanism, multiple block generation intervals can be set to one epoch period. Within each epoch period, the validator needs to send random values to the VRF contract of the DPOS for participation in consensus elections. The random values sent in each round are signed by the validator using their own private key for the previous random seed. The initial random value seed is passed in by the system admin, and subsequent random value seeds are generated by adding the random values of this round.
Verifier application review: If a user applies to become a verifier, the system admin needs to review the applicant's qualifications. If approved, it can be called a formal verifier participating in consensus election and block generation.
Verifier withdrawal: If a verifier requests to withdraw, the system admin also needs to pass the review to avoid a large number of verifiers suddenly withdrawing, exceeding the maximum consensus fault tolerance rate and causing the chain to fail to reach consensus.
System Contract Upgrade: The system contract uses a delegated call mechanism, where the proxy contract calls the logical contract to perform specific system functions. Administrators can deploy new logical contracts, pass in the address of the logical contract to replace the old one, and upgrade the system contract.
System admin change: system admin can transfer administrative permissions to other users, and will lose administrative permissions after transfer.
Modify the value of the update.contract_admin_addr field in the go-eni/app.toml configuration file to modify the default contract administrator address. Note that the default contract administrator address must be the same for all nodes on the chain.
[update]
contract_admin_addr = "0x110b6FB6675Fb2a310394ac3a43b23Fc23aB9BC6"
Gas administrator configuration
The gas administrator has the authority to adjust the gas fee coefficients of the chain to adjust the transaction pressure and frequency of the chain, including:
base_fee_per_gas
maximum_fee_per_gas
max_dynamic_base_fee_upward_adjustment
max_dynamic_base_fee_downward_adjustment
target_gas_used_per_block
Modify the value of the update.gas_admin_addr field in the go-eni/app.toml configuration file to modify the default gas administrator address. Note that the default gas administrator address must be the same for all nodes on the chain, and the address must be of the eni address type.
[update]
gas_admin_addr = "eni1wklu5t7ctecdlfr465lm6ms709xneg0rf45ajt"
Upgrade effective block high configuration
Each time the chain is upgraded, in order to ensure the consistency of the consensus across the network, a unified effective block height must be set for each node to be upgraded before the upgrade. When the block height reaches the effective block height, the upgraded logic will be executed concurrently.
When ENI fixed a bug caused by the consensus node slash mechanism, it had already undergone a mainnet upgrade. If other nodes want to join the ENI mainnet, they must also modify the effective block height to the same value as the mainnet before joining: 1982800. If the blockchain is deployed independently instead of joining the ENI mainnet, this value can be freely set.
Modify the value of the update.slashing_skip_height field in the go-eni/app.toml configuration file to modify the effective block height. Note that all nodes on the value chain must be the same.
[update]
slashing_skip_height = 1982800
config.toml configuration
note: the default configuration is already supported for commercial teams.
In the config.toml configuration file, commonly used configurations include the following fields:
Moniker: Node name, each node can be customized according to its own situation.
log_level: Log level, logs below the specified value will not be printed, for example, when it is info level, logs of debug and trace levels below info will not be printed.
genesis_file: Genesis file directory name.
p2p:
Laddr: The P2P port of this node, used for P2P communication between nodes. If deploying multiple nodes on a single machine, to avoid port conflicts, each node must be configured with different values.
persistent_peers: This node continues to link to the end node address and p2p port, similar to the seed node. If you create a configuration file to select multiple machines, you need to manually modify the IP here.
Mempool (default configuration already meets commercial requirements):
Size: The maximum number of transactions that can be stored in the transaction pool. It is recommended to configure the same value between nodes.
max_txs_bytes: the maximum total number of bytes of transactions that can be stored in the transaction pool;
cache_size: The maximum number of transactions that can be cached in the transaction pool. Cache is generally used for transaction plagiarism detection. The larger the cache, the larger the range of plagiarism detection, but it also consumes more memory.
Pending-size: Ethereum-type transactions with discontinuous nonce values will be placed in the pending transaction queue. Pending-size records the maximum value of the pending transaction queue.
max-pending-txs-bytes: records the total maximum number of bytes of pending transaction queue cache transactions.
Consensus (Consensus Configuration)
timeout_commit: Block interval, default is 5s, 1 s is recommended for commercial scenarios
# A custom human readable name for this node
moniker = "node1"
# Output level for logging, including package level options
log_level = "info"
[p2p]
# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "aeae7d4753419b11c958248de72fc8ba26460701@localhost:26656,c816663066d786f89e61c23076a37e0c0c81be7d@localhost:26666,9b6526775a0b81e72b2e1ed9a1ad7c58601618ff@localhost:26676,66594928af8120b4af318125b5d23f5545cf03a7@localhost:26686,"
# Note that for multi-machine deployment, each localhost in each persistent_peers needs to be modified to the ip of the machine where each node is located, for example:
# persistent_peers = "[email protected]:26656,[email protected]:26656,[email protected]:26656,[email protected]:26656,"
[mempool]
# Maximum number of transactions in the mempool
size = 5000
# Limit the total size of all txs in the mempool.
# This only accounts for raw transactions (e.g. given 1MB transactions and
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
max_txs_bytes = 1073741824
# Size of the cache (used to filter transactions we saw earlier) in transactions
cache_size = 10000
pending-size = 5000
max-pending-txs-bytes = 1073741824
[consensus]
# How long we wait after committing a block, before starting on the new
# height (this gives us a chance to receive some more precommits, even
# though we already have +2/3).
timeout_commit = "5s"
genesis .json configuration
note: the default configuration is already supported for commercial teams
The configuration in genesis .json is a genesis configuration. Each node must be completely consistent, otherwise the chain will not be able to reach consensus at genesis. Generally, an error will be reported after startup, and the block cannot be grown.In the Genesis configuration, focus on whether the following fields need to be modified according to your own situation. It is recommended to use the default configuration values for configurations not mentioned.
app_state various configuration items under evm.params:
base_fee_per_gas: the base fee in the dynamic gas rate calculation;
minimum_fee_per_gas: the minimum value of gas price;
maximum_fee_per_gas: the maximum value of gas price;
max_dynamic_base_fee_upward_adjustment: the upper limit of the adjustment parameters in the dynamic rate;
max_dynamic_base_fee_downward_adjustment: the lower limit of the adjustment parameters in the dynamic rate;
init_eni_address: A list of account addresses generated by default at creation;
init_eni_amount: When creating, set the initial chain native token value for the default account address, that is, the ueni initial balance of the default account. Note that the assignment order must be the same as the init_eni_address, otherwise it will cause the problem of incorrect initial account balance.
Genesis transactions under Genutil.gen_txs body messages (these genesis transactions are transactions where staked tokens become consensus nodes):
pubkey.@type: Node public key type of the initial validator at chain startup;
Pubkey.key: The public key of the initial validator's node at chain startup. The public key is base64-encoded data used for message signing and verification during the consensus process.
Note: how many body configuration items are under genutil.gen_txs, how many initial validators will there be when the chain starts, and everything in the genesis .json configuration file must be exactly the same for each node in the chain.
{
......
"app_state": {
......
"evm": {
"params": {
......
"base_fee_per_gas": "0.000000000000000000",
"minimum_fee_per_gas": "100.000000000000000000",
"max_dynamic_base_fee_upward_adjustment": "0.018900000000000000",
"max_dynamic_base_fee_downward_adjustment": "0.003900000000000000",
"target_gas_used_per_block": "250000",
"maximum_fee_per_gas": "1000000000000.000000000000000000",
"init_eni_amount": "100000000000000000000000000,100000000000000000000000000,100000000000000000000000000,100000000000000000000000000",
"init_eni_address": "3140aedbf686A3150060Cb946893b0598b266f5C,B680152a597c937164941e77cbF4a6b2F866675c,5746036C781851B9eF234219e770E1591104561f,7B6ba0Fe2610BF3c69Fc571C37aeC7bB87A281D2"
},
}
}
......
"genutil": {
"gen_txs": [
"body": {
"messages": [
......
"pubkey": {
"@type": "/cosmos.crypto.ed25519.PubKey",
"key": "oRBlTVa0kOY9+6Wk3tx/8ImsJPjwGkffUzpkREEmAmg="
},
....
]
}
"body": {
......
}
"body": {
......
}
"body": {
......
}
]
}
......
}
Multi-machine deployment
After the configuration settings are completed, the eni needs to be deployed to different machines, and the machines must be able to communicate normally. Before deployment, package and send the compiled go-eni project to different designated machines.
# exit to the upper directory of go-eni
cd ../
# the path of go-eni needs to be replaced with its your own path
tar -jcv -f eni.tar.bz2 ./go-eni
# send the eni.tar.bz2 package to the designated directory of each machine. The directory needs to be specified as its own directory
scp ./eni.tar.bz2 [email protected]:/path/to/your/dir
# Log in to the directory of each machine and extract the compressed package
tar -jxv -f eni.tar.bz2 -C ./
Start eni on each node. Note that different nodes specify different configuration paths. For example, on node 1, specify./eni-nodes/node1, and on node 2, specify./eni-nodes/node2.
# log in to the go-eni directory of node 1 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node1 &> ./build/node1.log &
# log in to the go-eni directory of node 2 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node2 &> ./build/node2.log &
# log in to the go-eni directory of node 3 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node3 &> ./build/node3.log &
# log in to the go-eni directory of node 4 and execute the following command
% nohup ./build/enid start --home=./eni-nodes/node4 &> ./build/node4.log &
Full Node Deployment
Full nodes are asynchronous nodes that do not participate in the consensus of the chain and only synchronize blocks. If full nodes are not deployed, this chapter process can be skipped.
Copy configuration
Copy a configuration from any consensus node.
cp rf eni-nodes/node4 eni-nodes/node5
Modify config.toml
Modify the identity nickname moniker of the full node to avoid having the same name as other nodes.
moniker = "node5"
Modify app.toml (optional modification, can be skipped)
Modify the database type in app.toml and enable historical data storage.
[state-store]
# DBBackend defines the backend database used for state-store.
# Supported backends: pebbledb, rocksdb, sqlite
# defaults to pebbledb (recommended)
ss-backend = "pebbledb"
ss-keep-last-version = true
Delete nodes and validator key files
Non-consensus nodes must delete node_key and priv_validator_key files, otherwise they will interfere with consensus. After deletion, full nodes will regenerate their own node_key and priv_validator_key files.
rm -rf eni-nodes/node5/config/node_key.json
rm -rf eni-nodes/node5/config/priv_validator_key.json
Start the full node
After the configuration file is set up, compile the go-eni project and start the full node.
make build
nohup ./build/enid start --home=./eni-nodes/node5 &> ./build/node.log &
Automated setup scripts (development/testing)
In addition to one-click quick deployment and custom deployment, we also provide script automation deployment. This option is ideal when you want to quickly start a node without delving into manual configuration.
git clone https://github.com/eni-chain/go-eni.git
cd go-eni
make build
python3 scripts/run-node.py
This script will guide you to choose:
Network: (mainnet, testnet or local)
Database backend: (recommended to use
eni-db
)Basic configuration options
Advanced Synchronization Options
Choose one of the following synchronization methods based on your operational needs:
State Sync Configuration (Non-Archive Nodes)
State sync allows your node to catch up quickly by retrieving a recent snapshot from trusted peers instead of replaying all historical blocks.
Steps
Edit the [statesync]
section: In ~/.eni/config/config.toml
, update or add the following persistent peers:
p2p.state-sync-0.eniac-1.eniac.network:26656,
Automate Trust Parameter Configuration:
Use the following script to dynamically set the trust height and hash based on the provided RPC endpoint:
Usage:
chmod +x script.sh
./script.sh <rpc_url>
Ensure the [statesync]
section already includes the persistent peers listed above.
Mempool Configuration Tuning
To optimize transaction processing and resource management, it’s recommended to update the mempool settings in the config.toml
file as follows:
#######################################################
### Mempool Configuration Options ###
#######################################################
[mempool]
# Broadcast transactions to other nodes
broadcast = true
# Maximum number of transactions in the mempool
size = 5000
# Limit the total size of all transactions in the mempool
max-txs-bytes = 10737418240
# Cache size (for filtering duplicate transactions)
cache-size = 10000
# Do not remove invalid transactions from the cache
keep-invalid-txs-in-cache = false
# Maximum size of a single transaction
max-tx-bytes = 2048576
# Maximum size of transaction batches sent to peers
max-batch-bytes = 0
# Time-to-live duration for transactions in the mempool
ttl-duration = "3s"
# Maximum number of blocks a transaction can remain in the mempool
ttl-num-blocks = 5
tx-notify-threshold = 0
check-tx-error-blacklist-enabled = false
check-tx-error-threshold = 0
pending-size = 5000
max-pending-txs-bytes = 1073741824
pending-ttl-duration = "3s"
pending-ttl-num-blocks = 5
Suggestion: Adjust these parameters if you encounter performance or resource issues.
Set Up Service with systemd
Setting up a systemd service ensures your node starts automatically on boot and restarts if it crashes.
sudo tee /etc/systemd/system/enid.service > /dev/null << EOF
[Unit]
Description=ENI Node
After=network-online.target
[Service]
User=$USER
ExecStart=$(which enid) start
Restart=always
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable enid
sudo systemctl start enid
Note: Confirm that the
User
field suits your environment. Update it accordingly if running under a different user.
Validation and Troubleshooting
Validate Your Setup
Run the following commands to confirm the node’s status:
# Check sync status
enid status | jq .SyncInfo
# View live logs
journalctl -u enid -f -o cat
Your node is correctly set up when:
Sync status shows
"catching_up": false
Logs indicate blocks are being processed
Common Troubleshooting Tips
Sync Issues
Verify sufficient disk space.
Ensure a stable network connection.
Confirm the system time is correctly synchronized.
Use state sync for rapid initial sync (note: not applicable for archive nodes).
Performance Issues
Monitor system resources (CPU, memory, I/O).
Evaluate disk performance and network bandwidth.
Adjust mempool and persistent peer settings if necessary.
Network Connectivity
Confirm firewall rules allow required ports (e.g., 26656, 26657, 9090).
Check that DNS resolution is functioning.
View system logs and node info via RPC [localhost:26657/net_info] to verify peer connections.
Next Steps
Once your node is up and running, consider the following:
Monitoring and Alerts: Set up tools to monitor node health and performance.
Security Best Practices: Harden your server (firewall, SSH keys, etc.).
Backup Procedures: Regularly back up your configuration and data directories.
Additional documentation can be found at:
Advanced Configuration and Monitoring Guide
Node Operators Guide
Validators Guide
Last updated