π»Baremetal
Authors: [man4ela | catapulta.eth]
System Requirements
16+ cores CPU
Debian 12/Ubuntu 22.04
=> 64 GB
500GB+ (SSD or NVMe)
HyperEVM
In this guide the installation process of nanoreth will be covered which is needed to sync an archival node able to serve historical requests on HyperEVM mainnet chain.
Pre-Requisites
sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y
sudo apt install -y git make wget aria2 gcc pkg-config libusb-1.0-0-dev libudev-dev jq gcc g++ curl libssl-dev screen apache2-utils build-essential pkg-configv unzip
Setting up Firewall
Set explicit default UFW rules
sudo ufw default deny incoming
sudo ufw default allow outgoing
Allow SSH
sudo ufw allow 22/tcp
Allow remote RPC connections with the node
sudo ufw allow from ${REMOTE.HOST.IP} to any port 3454
Allow remote P2P connections with Nanoreth and HL Nodes
sudo ufw allow 30303
sudo ufw allow 4002
sudo ufw allow 4001
sudo ufw allow 3999
Not advised to allow all or unknown IP address to RPC port
Enable Firewall
sudo ufw enable
To check the status of UFW and see the current rules
sudo ufw status verbose
Install dependencies
Install Rust
sudo apt update && sudo apt install -y clang llvm-dev libclang-dev
curl https://sh.rustup.rs -sSf | sh -s -- -y
export PATH="$HOME/.cargo/bin:$PATH"
source ~/.bashrc
Install AWS
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws configure
region = ap-northeast-1
output = json
aws_access_key_id = {Your AWS access key}
aws_secret_access_key = {Your AWS secret key}
Install Nanoreth
git clone https://github.com/hl-archive-node/nanoreth.git
cd nanoreth
git checkout nb-20250915 (make sure youβve pulled the latest build)
make install
Create systemd service for nanoreth
sudo nano /etc/systemd/system/hl-nanoreth.service
[Unit]
Description=Hyperliquid nanoreth Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/nanoreth/
ExecStart=/root/.cargo/bin/reth-hl node \
--block-source=/root/data/hl-nanoreth/evm-blocks \
# --local-ingest-dir=/root/hl/data/evm_block_and_receipts/ \
# --s3 \
--ws \
--port 30303 \
--discovery.port 30303 \
--ws.origins="*" \
--ws.addr=0.0.0.0 \
--http.port=3545 \
--ws.port=3555 \
--ws.api=ots,web3,debug,eth,txpool,net,trace \
--http \
--http.corsdomain="*" \
--http.addr=0.0.0.0 \
--http.api=ots,web3,debug,eth,txpool,net,trace \
--forward-call \
--rpc.gascap 650000000
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
Save by entering ctrl+X
and Y+ENTER
Before starting Nanoreth we want to obtain evm-blocks from block 0. There are two options for doing this:
Using a database shared by a community member - Fast but not recommended, as this relies on a third-party provider and archive availability is often unreliable
mkdir -p /root/data/hl-nanoreth/evm-blocks/ && cd /root/data/hl-nanoreth/evm-blocks/
aria2c --file-allocation=none -c -x 10 -s 10 https://hl-archive-node.xyz/snapshot/evm-blocks.tar.zst
Obtaining the official archive from AWS. This is the recommended method. Use the following command to download the blocks. Better do it in screen session as synchronizing is going to take up to 48 hrs
aws s3 sync s3://hl-mainnet-evm-blocks/ /root/data/hl-nanoreth/evm-blocks/ --request-payer requester
Once the database has finished syncing, start the NanoReth systemd service with the --block-source=/root/data/hl-nanoreth/evm-blocks
flag enabled.
This allows the node to load and process blocks from genesis up to the most recent available block before continuing live synchronization using either --s3 or local block sync (using Hl-visor)
--block-source=/root/data/hl-nanoreth/evm-blocks
flag enabled.
This allows the node to load and process blocks from genesis up to the most recent available block before continuing live synchronization using either --s3 or local block sync (using Hl-visor)
sudo systemctl daemon-reload
sudo systemctl enable hl-nanoreth.service
sudo systemctl start hl-nanoreth.service
sudo journalctl -u hl-nanoreth.service -f -n 100
Give Nanoreth some time to catch up and when it stops proceeding switch to --S3 sync by editing systemd service file:
sudo systemctl stop hl-nanoreth.service
sudo nano /etc/systemd/system/hl-nanoreth.service
[Unit]
Description=Hyperliquid nanoreth Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/nanoreth/
ExecStart=/root/.cargo/bin/reth-hl node \
# --block-source=/root/data/hl-nanoreth/evm-blocks \
# --local-ingest-dir=/root/hl/data/evm_block_and_receipts/ \
--s3 \
--ws \
--port 30303 \
--discovery.port 30303 \
--ws.origins="*" \
--ws.addr=0.0.0.0 \
--http.port=3545 \
--ws.port=3555 \
--ws.api=ots,web3,debug,eth,txpool,net,trace \
--http \
--http.corsdomain="*" \
--http.addr=0.0.0.0 \
--http.api=ots,web3,debug,eth,txpool,net,trace \
--forward-call \
--rpc.gascap 650000000
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl restart hl-nanoreth.service
With this option enabled, NanoReth will fetch any missing blocks directly from AWS, process them, and continue retrieving new data from there going forward.
From this point, you can choose to either continue using --s3-sync
or set up Hyperliquidβs hl-visor
node to fetch blocks locally, which provides lower latency and no reliability on AWS
Install HL-Visor
Download the binary and grant the necessary permissions to make it executable
mkdir -p /root/hyperliquid/ && cd /root/hyperliquid/
curl https://binaries.hyperliquid.xyz/Mainnet/hl-visor > /root/hyperliquid/hl-visor && chmod a+x /root/hyperliquid/hl-visor
Create a visor.json
which tells hl-visor
which chain to connect to
echo '{"chain": "Mainnet"}' > /root/hyperliquid/visor.json
Verify the authenticity of the hl-visor
binary
wget https://raw.githubusercontent.com/hyperliquid-dex/node/refs/heads/main/pub_key.asc
gpg --import /root/hyperliquid/pub_key.asc
gpg --verify hl-visor.asc hl-visor
Add peers for syncing with the network
curl -X POST --header "Content-Type: application/json" --data '{ "type": "gossipRootIps" }' https://api.hyperliquid.xyz/info
The above command will fetch the list of live peers
Create the gossip override configuration
Use the following command to create /root/hyperliquid/override_gossip_config.json
:
cat > /root/hyperliquid/override_gossip_config.json <<EOF
{
"root_node_ips": [
{ "Ip": "<IP from list>" },
{ "Ip": "<IP from list>" },
{ "Ip": "<IP from list>" }
],
"try_new_peers": false,
"chain": "Mainnet"
}
EOF
Replace
<IP from list>
with at least 5 additional IPs returned by the previouscurl
command
Create systemd file for hl-visor service:
sudo nano /etc/systemd/system/hl-visor.service
Paste:
[Unit]
Description=Hyperliquid Mainnet Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=500000
WorkingDirectory=/root/hyperliquid/
ExecStart=/root/hyperliquid/hl-visor run-non-validator --replica-cmds-style recent-actions --serve-eth-rpc --disable-output-file-buffering
KillSignal=SIGHUP
[Install]
WantedBy=multi-user.target
Launch hl-visor
sudo systemctl daemon-reload
sudo systemctl restart hl-visor.service
sudo systemctl enable hl-visor.service
sudo systemctl status hl-visor.service
sudo systemctl disable hl-visor.service
sudo journalctl -fu hl-visor.service -n 100
Troubleshooting
If you happen to run into following error:
hl-visor[289715]: invalid ip address: 2a01:4f8:272:55a1::2
hl-visor[289715]: invalid ip address: 2a01:4f8:272:55a1::2
hl-visor[289715]: unable to query enough endpoints for public ip n_endpoints=1 ip_to_endpoints={"xx.xx.0.xxx": ["api.ipify.org"]}
Disable IPv6:
nano /etc/sysctl.conf
Scroll to the bottom and add the following lines
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
Apply the changes
sysctl -p
Once hl-visor
has finished syncing, you can switch Nanoreth
to use the blocks produced by hl-visor
as its source:
[Unit]
Description=Hyperliquid nanoreth Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/nanoreth/
ExecStart=/root/.cargo/bin/reth-hl node \
--block-source=/root/data/hl-nanoreth/evm-blocks \
--local-ingest-dir=/root/hl/data/evm_block_and_receipts/ \
# --s3 \
--ws \
--port 30303 \
--discovery.port 30303 \
--ws.origins="*" \
--ws.addr=0.0.0.0 \
--http.port=3545 \
--ws.port=3555 \
--ws.api=ots,web3,debug,eth,txpool,net,trace \
--http \
--http.corsdomain="*" \
--http.addr=0.0.0.0 \
--http.api=ots,web3,debug,eth,txpool,net,trace \
--forward-call \
--rpc.gascap 650000000
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
Logs
hl-nanoreth.service
:
2025-09-30T05:38:08.590719Z INFO Forkchoice updated head_block_hash=0x6c24b5a41ed4749eeecb027927deca0f33a9fdbd1b69c55ac4665eec91e35ccc safe_block_hash=0x6c24b5a41ed4749eeecb027927deca0f33a9fdbd1b69c55ac4665eec91e35ccc finalized_block_hash=0x6c24b5a41ed4749eeecb027927deca0f33a9fdbd1b69c55ac4665eec91e35ccc
2025-09-30T05:38:09.479800Z INFO Loading block data from "/root/hl/data/evm_block_and_receipts/hourly/20250930/5"
2025-09-30T05:38:09.553961Z INFO Received block from consensus engine number=15207178 hash=0x2ccd43d458ee20aa22eb34757f8c7f463d19c2a574d7087bf2801706b3ff2349
2025-09-30T05:38:09.556894Z INFO State root task finished state_root=0x0000000000000000000000000000000000000000000000000000000000000000 elapsed=3.637Β΅s
2025-09-30T05:38:09.557031Z INFO Block added to canonical chain number=15207178 hash=0x2ccd43d458ee20aa22eb34757f8c7f463d19c2a574d7087bf2801706b3ff2349 peers=1 txs=6 gas_used=1.16Mgas gas_throughput=402.41Mgas/second gas_limit=2.00Mgas full=57.9% base_fee=0.52Gwei blobs=0 excess_blobs=0 elapsed=2.877896ms
2025-09-30T05:38:09.557121Z INFO Canonical chain committed number=15207178 hash=0x2ccd43d458ee20aa22eb34757f8c7f463d19c2a574d7087bf2801706b3ff2349 elapsed=51.146Β΅s
hl-visor.service:
2025-09-30T05:41:48.253Z WARN >>> hl-node @@ serialized abci state for greeting @@ [abci_state.initial_height(): 744217000] @ [abci_state.height(): 747340000] @ [height: 747340000] @ [app_hash: AppHash(0x26c7a24d0478d5642840223902bcbe9214c623bf72f69aa3ecebde8483ea9922)] @ [serialized_abci_state.len(): 796340359]
2025-09-30T05:41:49.185Z WARN >>> hl-node @@ new app hashes reached quorum: [(747340000, QuorumAppHash { app_hash: AppHash(0x26c7a24d0478d5642840223902bcbe9214c623bf72f69aa3ecebde8483ea9922), hot_user_to_signature: Map({User(0x263294039413b96d25e4173a5f7599f8b3801504): Signature { r: 11226097415728839685190038623666713917190623830926729210141813323781111584450, s: 41611733720057584615483157272637821957617442682069963495194403651334751946595, v: 27 }, User(0xda6816df552c3f9e0fb64979fb357800d690d79b): Signature { r: 64996816189104273047422151237300995979151712004356590728032981323771342471738, s: 43857914805416652328827852965788456878785485757437346182906383839811362321239, v: 27 }, User(0xef2364db5db6f5539aa0bc111771a94ee47637fc): Signature { r: 16083230333297748674825901868221088981578128627302424425982620981396746852805, s: 52642217192111573387864443495565731691625857210130769552404787153265046789557, v: 28 }}) })]
2025-09-30T05:41:53.922Z WARN >>> hl-node @@ applied block 747340200
2025-09-30T05:42:01.989Z WARN >>> hl-node @@ applied block 747340300
References
Last updated