logo
X PrimeFlow

Manual node installation

Official operator documentationProject websiteSource repositoryExplorer

Network: Testnet

Chain ID: safro-testnet-1

Guide review: 2026-07-14 ยท 4 source references

Recommended hardware: 4 Cores, 8GB RAM, 200GB NVMe

Go version: 1.23.9

Binary: safrochaind

Node home: ~/.safrochain-testnet

1. Prepare the node host

sudo apt-get update
sudo apt-get install -y ca-certificates curl git jq make build-essential

# Install the exact Go version required by this network from https://go.dev/dl/,
# verify its published checksum, then confirm it before building.
go version  # required by project metadata: 1.23.9

2. Build the pinned node binary

set -euo pipefail
REPOSITORY="https://github.com/Safrochain-Org/safrochain-node"
COMMIT="fbb961b7ec4c448b0c6aeb1c4532da6f51694ff6"
cd "$HOME"
test ! -e safrochain-node || { echo 'Stop: $HOME/safrochain-node already exists; review it before continuing.' >&2; exit 1; }
git clone --filter=blob:none --no-checkout "$REPOSITORY" safrochain-node
cd safrochain-node
git fetch --depth 1 origin "$COMMIT"
git checkout --detach "$COMMIT"
test "$(git rev-parse HEAD)" = "$COMMIT"
make install

# Verify which binary will be used before initialization.
command -v "safrochaind"
"safrochaind" version

3. Initialize a new node home

set -euo pipefail
BIN="safrochaind"
CHAIN_ID="safro-testnet-1"
MONIKER='validator-name'
NODE_HOME="$HOME/.safrochain-testnet"

command -v "$BIN"
test ! -e "$NODE_HOME" || { echo "Stop: $NODE_HOME already exists; back it up and review it first." >&2; exit 1; }
"$BIN" init "$MONIKER" --chain-id "$CHAIN_ID" --home "$NODE_HOME"
test -f "$NODE_HOME/config/genesis.json"

4. Install and validate genesis

set -euo pipefail
CHAIN_ID="safro-testnet-1"
NODE_HOME="$HOME/.safrochain-testnet"
GENESIS_URL='https://genesis.safrochain.com/testnet/genesis.json'
GENESIS_DOWNLOAD="$NODE_HOME/config/genesis.json.download"

test -d "$NODE_HOME/config"
test ! -e "$GENESIS_DOWNLOAD" || { echo "Stop: review the existing $GENESIS_DOWNLOAD first." >&2; exit 1; }
curl --fail --show-error --location --proto "=https" --max-time 120   --output "$GENESIS_DOWNLOAD" "$GENESIS_URL"
jq -e --arg chain "$CHAIN_ID" '.chain_id == $chain' "$GENESIS_DOWNLOAD" >/dev/null
printf '%s  %s
' 'a168fab2e9a82ad1f45f943688218254f87e5717c01c0e79efb713295de142d9' "$GENESIS_DOWNLOAD" | sha256sum --check -
cp --no-clobber "$NODE_HOME/config/genesis.json" "$NODE_HOME/config/genesis.json.init-backup" || true
install -m 0644 "$GENESIS_DOWNLOAD" "$NODE_HOME/config/genesis.json"
jq -r '.chain_id' "$NODE_HOME/config/genesis.json"

5. Configure minimum gas prices

set -euo pipefail
APP_TOML="$HOME/.safrochain-testnet/config/app.toml"
test -f "$APP_TOML"
cp --no-clobber "$APP_TOML" "$APP_TOML.bonynode-backup" || true

if grep -q '^minimum-gas-prices' "$APP_TOML"; then
  sed -i 's|^minimum-gas-prices *=.*|minimum-gas-prices = "0.05usaf"|' "$APP_TOML"
else
  printf '
minimum-gas-prices = "0.05usaf"
' >> "$APP_TOML"
fi
grep '^minimum-gas-prices' "$APP_TOML"

6. Configure reviewed seeds

set -euo pipefail
CONFIG_TOML="$HOME/.safrochain-testnet/config/config.toml"
SEEDS='fe71717889a8a2ee528ada4558dd9b03f578157c@seed.testnet.safrochain.com:26656'
test -f "$CONFIG_TOML"
cp --no-clobber "$CONFIG_TOML" "$CONFIG_TOML.bonynode-backup" || true
sed -i "s|^seeds *=.*|seeds = "$SEEDS"|" "$CONFIG_TOML"
grep '^seeds' "$CONFIG_TOML"

7. Create the service, start and verify the node

set -euo pipefail
BIN="safrochaind"
CHAIN_ID="safro-testnet-1"
NODE_HOME="$HOME/.safrochain-testnet"
SERVICE="safrochaind.service"
BIN_PATH=$(command -v "$BIN")
SERVICE_USER="$USER"

test -x "$BIN_PATH"
test -s "$NODE_HOME/config/genesis.json"
sudo tee "/etc/systemd/system/$SERVICE" >/dev/null <<EOF
[Unit]
Description=Safrochain node
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=${SERVICE_USER}
ExecStart=${BIN_PATH} start --home ${NODE_HOME}
Restart=on-failure
RestartSec=5
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now "$SERVICE"
sudo systemctl status "$SERVICE" --no-pager

# Wait briefly for the local RPC listener and require the configured chain ID.
for attempt in {1..30}; do
  if STATUS=$(curl --fail --silent http://127.0.0.1:26657/status); then
    jq -e --arg chain "$CHAIN_ID" '.result.node_info.network == $chain' <<<"$STATUS"
    exit 0
  fi
  sleep 2
done
echo 'Local RPC did not become ready; inspect the service journal.' >&2
sudo journalctl -u "$SERVICE" -n 100 --no-pager
exit 1