LaTanda
Manual node installation
Official operator documentationProject websiteSource repositoryExplorer
BonyNode setup profile
No seed phrases or private keysConfigure once โ generate every command
These values update the LaTanda installation, wallet, validator, sync and firewall commands below.
Recommended hardware: 2 CPU, 4GB RAM, 50GB SSD minimum; 4 CPU, 8GB RAM and 200GB SSD recommendedProfile is valid โ commands are ready
Network: Testnet
Chain ID: latanda-testnet-1
Guide review: 2026-07-14 ยท 3 source references
Recommended hardware: 2 CPU, 4GB RAM, 50GB SSD minimum; 4 CPU, 8GB RAM and 200GB SSD recommended
Go version: 1.25.6
Binary: latandad
Node home: ~/.latanda
The guide was reviewed against current project metadata and official operator documentation. Hosted BonyNode infrastructure is not implied; confirm the selected release and network parameters before using a production host.
1. Prepare the node host
set -euo pipefail
sudo apt-get update
sudo apt-get install -y ca-certificates curl git jq make build-essential
GO_VERSION="1.25.6"
case "$(uname -m)" in
x86_64) GO_ARCH="amd64" ;;
aarch64|arm64) GO_ARCH="arm64" ;;
*) echo "Unsupported CPU architecture: $(uname -m)" >&2; exit 1 ;;
esac
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT
GO_FILE="go1.25.6.linux-$GO_ARCH.tar.gz"
GO_META_URL="https://go.dev/dl/?mode=json&include=all"
GO_SHA256=$(curl --fail --silent --show-error --proto '=https' --max-filesize 5242880 --max-time 30 "$GO_META_URL" | jq -er --arg file "$GO_FILE" '.[] | .files[] | select(.filename == $file) | .sha256' | head -n 1)
test -n "$GO_SHA256"
curl --fail --location --show-error --retry 3 --proto '=https' --proto-redir '=https' --max-filesize 268435456 --max-time 900 "https://go.dev/dl/$GO_FILE" -o "$WORK_DIR/$GO_FILE"
printf '%s %s\n' "$GO_SHA256" "$WORK_DIR/$GO_FILE" | sha256sum --check -
tar -tzf "$WORK_DIR/$GO_FILE" >/dev/null
if [ -d /usr/local/go ]; then
sudo mv /usr/local/go "/usr/local/go.backup.$(date -u +%Y%m%dT%H%M%SZ)"
fi
sudo tar -C /usr/local -xzf "$WORK_DIR/$GO_FILE"
grep -qxF 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' "$HOME/.profile" 2>/dev/null || printf '%s\n' 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> "$HOME/.profile"
export PATH="$PATH:/usr/local/go/bin:$HOME/go/bin"
mkdir -p "$HOME/go/bin"
go version | grep -F "go1.25.6"2. Build the pinned node binary
set -euo pipefail
cd "$HOME"
test ! -e la-tanda-chain || { echo 'Stop: $HOME/la-tanda-chain already exists; review it before continuing.' >&2; exit 1; }
git clone https://github.com/INDIGOAZUL/la-tanda-chain.git la-tanda-chain
cd la-tanda-chain
git checkout --detach 2f135e55d596a765c83bf4bec65ca91a6e1ee535
test "$(git rev-parse HEAD)" = "2f135e55d596a765c83bf4bec65ca91a6e1ee535"
go build -o latandad ./cmd/latandad
mkdir -p "$HOME/go/bin"
install -m 0755 latandad "$HOME/go/bin/latandad"
# Verify which binary will be used before initialization.
command -v "latandad"
"latandad" version3. Initialize a new node home
set -euo pipefail
BIN="latandad"
CHAIN_ID="latanda-testnet-1"
MONIKER='validator-name'
NODE_HOME="$HOME/.latanda"
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="latanda-testnet-1"
NODE_HOME="$HOME/.latanda"
GENESIS_URL='https://latanda.online/chain/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
' '98fc9871d6a3b7b12b3f7fcaa1ca3303ffcfad0f209d61355975a15069ac3907' "$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 client and selected RPC port
set -euo pipefail
CHAIN_ID="latanda-testnet-1"
NODE_HOME="$HOME/.latanda"
CLIENT_TOML="$NODE_HOME/config/client.toml"
LOCAL_RPC="tcp://127.0.0.1:10657"
test -f "$CLIENT_TOML"
cp --no-clobber "$CLIENT_TOML" "$CLIENT_TOML.bonynode-backup" || true
sed -i -E -e "s|^chain-id[[:space:]]*=.*|chain-id = \"$CHAIN_ID\"|" -e 's|^keyring-backend[[:space:]]*=.*|keyring-backend = "os"|' -e "s|^node[[:space:]]*=.*|node = \"$LOCAL_RPC\"|" "$CLIENT_TOML"
grep -E '^(chain-id|keyring-backend|node)[[:space:]]*=' "$CLIENT_TOML"6. Apply ports, pruning, indexer and Prometheus settings
set -euo pipefail
NODE_HOME="$HOME/.latanda"
APP_TOML="$NODE_HOME/config/app.toml"
CONFIG_TOML="$NODE_HOME/config/config.toml"
test -f "$APP_TOML"
test -f "$CONFIG_TOML"
cp --no-clobber "$APP_TOML" "$APP_TOML.bonynode-backup" || true
cp --no-clobber "$CONFIG_TOML" "$CONFIG_TOML.bonynode-backup" || true
# Application API, gRPC and optional EVM ports.
sed -i -e 's|:1317|:10317|g' -e 's|:8080|:10080|g' -e 's|:9090|:10090|g' -e 's|:9091|:10091|g' -e 's|:8545|:10545|g' -e 's|:8546|:10546|g' -e 's|:6065|:10065|g' "$APP_TOML"
# CometBFT RPC, P2P, proxy-app, pprof and Prometheus ports.
sed -i -e 's|:26658|:10658|g' -e 's|:26657|:10657|g' -e 's|:6060|:10060|g' -e 's|:26656|:10656|g' -e 's|:26660|:10660|g' "$CONFIG_TOML"
sed -i -E -e 's|^pruning[[:space:]]*=.*|pruning = "custom"|' -e 's|^pruning-keep-recent[[:space:]]*=.*|pruning-keep-recent = "100"|' -e 's|^pruning-keep-every[[:space:]]*=.*|pruning-keep-every = "0"|' -e 's|^pruning-interval[[:space:]]*=.*|pruning-interval = "19"|' "$APP_TOML"
sed -i -E 's|^indexer[[:space:]]*=.*|indexer = "null"|' "$CONFIG_TOML"
sed -i -E 's|^prometheus[[:space:]]*=.*|prometheus = true|' "$CONFIG_TOML"
grep -E '^(pruning|pruning-keep-recent|pruning-interval)[[:space:]]*=' "$APP_TOML"
grep -E '^(indexer|prometheus)[[:space:]]*=' "$CONFIG_TOML"
printf 'RPC=%s P2P=%s API=%s gRPC=%s Prometheus=%s\n' '10657' '10656' '10317' '10090' '10660'7. Configure minimum gas prices
set -euo pipefail
APP_TOML="$HOME/.latanda/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.001ultd"|' "$APP_TOML"
else
printf '
minimum-gas-prices = "0.001ultd"
' >> "$APP_TOML"
fi
grep '^minimum-gas-prices' "$APP_TOML"8. Configure reviewed seeds
set -euo pipefail
CONFIG_TOML="$HOME/.latanda/config/config.toml"
SEEDS='[email protected]: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"9. Create the service, start and verify the node
set -euo pipefail
BIN="latandad"
CHAIN_ID="latanda-testnet-1"
NODE_HOME="$HOME/.latanda"
SERVICE="latandad.service"
BIN_PATH=$(command -v "$BIN")
SERVICE_USER="$USER"
LOCAL_RPC_PORT="10657"
test -x "$BIN_PATH"
test -s "$NODE_HOME/config/genesis.json"
sudo tee "/etc/systemd/system/$SERVICE" >/dev/null <<EOF
[Unit]
Description=LaTanda 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:$LOCAL_RPC_PORT/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 1Node sync checker
Compare the selected local RPC height with the chain-verified BonyNode reference. Stop with Ctrl+C.
#!/usr/bin/env bash
set -euo pipefail
CHAIN_ID="latanda-testnet-1"
LOCAL_RPC="http://127.0.0.1:10657"
REFERENCE_RPC="https://latanda.online/chain/rpc"
read_height() {
local endpoint="$1"
curl --fail --silent --show-error --max-time 10 "$endpoint/status" | jq -er --arg chain "$CHAIN_ID" '
select(.result.node_info.network == $chain)
| .result.sync_info.latest_block_height
| select(test("^[0-9]+$"))
'
}
while true; do
if LOCAL_HEIGHT=$(read_height "$LOCAL_RPC") && NETWORK_HEIGHT=$(read_height "$REFERENCE_RPC"); then
BLOCKS_LEFT=$((NETWORK_HEIGHT - LOCAL_HEIGHT))
[ "$BLOCKS_LEFT" -ge 0 ] || BLOCKS_LEFT=0
printf 'Local: %s | Network: %s | Blocks left: %s\n' "$LOCAL_HEIGHT" "$NETWORK_HEIGHT" "$BLOCKS_LEFT"
else
printf 'Unable to validate one of the chain-ID checked RPC heights; retrying...\n' >&2
fi
sleep 5
doneCreate or restore wallet
set -euo pipefail
BIN="latandad"
WALLET='wallet'
[[ "$WALLET" =~ ^[a-zA-Z0-9_-]{1,64}$ ]] || { echo "Invalid wallet name" >&2; exit 1; }
# Create a new key. Store the mnemonic offline; it cannot be recovered by BonyNode.
"$BIN" keys add "$WALLET"
# To restore an existing key, run this separately:
# "$BIN" keys add "$WALLET" --recover
WALLET_ADDRESS=$("$BIN" keys show "$WALLET" -a)
"$BIN" query bank balances "$WALLET_ADDRESS"Create validator
BIN="latandad"
CHAIN_ID="latanda-testnet-1"
WALLET='wallet'
MONIKER='validator-name'
IDENTITY=''
WEBSITE=''
DETAILS='Independent validator'
AMOUNT="1000000ultd"
MIN_SELF_DELEGATION="1"
COMMISSION_RATE="0.10"
COMMISSION_MAX_RATE="0.20"
COMMISSION_MAX_CHANGE="0.01"
"$BIN" tx staking create-validator --amount "$AMOUNT" --from "$WALLET" --commission-rate "$COMMISSION_RATE" --commission-max-rate "$COMMISSION_MAX_RATE" --commission-max-change-rate "$COMMISSION_MAX_CHANGE" --min-self-delegation "$MIN_SELF_DELEGATION" --pubkey "$("$BIN" tendermint show-validator)" --moniker "$MONIKER" --identity "$IDENTITY" --website "$WEBSITE" --details "$DETAILS" --chain-id "$CHAIN_ID" --gas auto --gas-adjustment 1.5 --gas-prices 0.001ultd -yBasic host firewall
set -euo pipefail
P2P_PORT="10656"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw allow "$P2P_PORT/tcp"
sudo ufw enable
sudo ufw status verbose
# RPC/API/gRPC remain private unless you deliberately add authenticated
# reverse-proxy rules. Never expose validator signing services publicly.Reversible decommission
This procedure stops and disables the service but retains the node home, binary and service file. Verify the backup before any later deletion.
set -euo pipefail
SERVICE="latandad"
NODE_HOME="$HOME/.latanda"
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
RETIRED_HOME="$NODE_HOME.retired.$STAMP"
KEY_BACKUP="$HOME/latandad-validator-keys-$STAMP.tar.gz"
NODE_STOPPED=0
rollback() {
trap - ERR INT TERM
if [ "$NODE_STOPPED" -eq 1 ]; then sudo systemctl start "$SERVICE" || true; fi
exit 1
}
trap rollback ERR INT TERM
test -d "$NODE_HOME"
test ! -e "$RETIRED_HOME"
test -s "$NODE_HOME/config/priv_validator_key.json"
test -s "$NODE_HOME/data/priv_validator_state.json"
sudo systemctl stop "$SERVICE"
NODE_STOPPED=1
# Back up validator identity/state before moving anything.
tar -czf "$KEY_BACKUP" -C "$NODE_HOME" config/priv_validator_key.json config/node_key.json data/priv_validator_state.json
test -s "$KEY_BACKUP"
mv "$NODE_HOME" "$RETIRED_HOME"
sudo systemctl disable "$SERVICE"
NODE_STOPPED=0
trap - ERR INT TERM
echo "Node home was retained at: $RETIRED_HOME"
echo "Critical key backup: $KEY_BACKUP"
echo "No binary, service file or node data was deleted."