This guide covers running an Autheo node from scratch. Two deployment methods are provided: Method A — systemd (build from source) and Method B — Docker (official GHCR image).
1. Chain reference
| Property | Value |
|---|
| Binary | autheod |
| Cosmos chain ID | autheo_2127-1 (mainnet) |
| EVM chain ID | 2127 (0x84f) |
| Native denom | aauth |
| Denom decimals | 18 (1 THEO = 10^18 aauth) |
| Default home dir | $HOME/.autheo |
| Key algorithm | eth_secp256k1 |
| Block time | ~5 seconds |
| Block max gas | 30000000 |
| Min gas prices | 10000000000000aauth |
Ports (single node defaults):
| Port | Protocol | Purpose |
|---|
26656 | TCP | CometBFT P2P |
26657 | TCP | CometBFT RPC |
9090 | TCP | gRPC |
1317 | TCP | REST API |
8545 | TCP | EVM JSON-RPC |
8546 | TCP | EVM WebSocket |
2. Infrastructure requirements
Size your server to meet the following minimums before proceeding. Under-provisioned nodes are more likely to miss blocks and get jailed.
| Resource | Minimum | Recommended |
|---|
| CPU | 8 vCPU | 16 vCPU |
| RAM | 32 GB | 64 GB |
| Storage | 1 TB NVMe SSD | 2 TB NVMe SSD |
| Network | 1 Gbps | 10 Gbps |
| OS | Ubuntu 22.04 LTS | Ubuntu 22.04 LTS |
3. Method A: systemd
3.1 Prerequisites
# Ubuntu / Debian
sudo apt update && sudo apt install -y \
git make gcc build-essential \
jq curl wget
# Go (must match go.mod — verify exact version at https://go.dev/dl/)
GO_VERSION=1.25.0
wget https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> ~/.bashrc
source ~/.bashrc
go version
3.2 Build the binary
git clone https://github.com/autheo-blockchain/autheo-chain-core
cd autheo-chain-core
make build
Install to PATH:
sudo cp ./build/autheod /usr/local/bin/autheod
autheod --help
3.3 Join the network
All official configuration files are in the autheo-blockchain/networks repository.
# 1. Clone the networks repo
git clone https://github.com/autheo-blockchain/networks
# 2. Initialize the node
autheod init <moniker> \
--chain-id $(cat networks/mainnet/chain-id) \
--home $HOME/.autheo
# 3. Copy the official genesis
cp networks/mainnet/genesis.json $HOME/.autheo/config/genesis.json
# 4. Set persistent peers
CONFIG=$HOME/.autheo/config/config.toml
sed -i "s|^persistent_peers = .*|persistent_peers = \"$(cat networks/mainnet/persistent_peers.txt)\"|" $CONFIG
# 5. Set minimum gas prices
APP=$HOME/.autheo/config/app.toml
sed -i 's|^minimum-gas-prices = .*|minimum-gas-prices = "10000000000000aauth"|' $APP
Then choose a sync method from section 5.
$HOME/.autheo/config/config.toml
CONFIG=$HOME/.autheo/config/config.toml
# Expose RPC to all interfaces (default is 127.0.0.1)
sed -i 's|laddr = "tcp://127.0.0.1:26657"|laddr = "tcp://0.0.0.0:26657"|' $CONFIG
$HOME/.autheo/config/app.toml
APP=$HOME/.autheo/config/app.toml
# Enable REST API (disabled by default)
sed -i '/^\[api\]/,/^\[/{s/^enable = false/enable = true/}' $APP
sed -i 's|address = "tcp://localhost:1317"|address = "tcp://0.0.0.0:1317"|' $APP
# Expose EVM JSON-RPC (enabled by default, bound to 127.0.0.1)
sed -i 's|address = "127.0.0.1:8545"|address = "0.0.0.0:8545"|' $APP
sed -i 's|ws-address = "127.0.0.1:8546"|ws-address = "0.0.0.0:8546"|' $APP
# Add debug and txpool namespaces
sed -i 's|api = "eth,net,web3"|api = "eth,net,web3,debug,txpool"|' $APP
# Expose gRPC (default is localhost:9090)
sed -i 's|address = "localhost:9090"|address = "0.0.0.0:9090"|' $APP
$HOME/.autheo/config/client.toml
CLIENT=$HOME/.autheo/config/client.toml
sed -i 's|^keyring-backend = .*|keyring-backend = "file"|' $CLIENT
3.5 Start with systemd
Create /etc/systemd/system/autheod.service, adjusting User, WorkingDirectory, and ExecStart for your system user:
[Unit]
Description=Autheo Chain Node
After=network-online.target
Wants=network-online.target
[Service]
User=autheo
WorkingDirectory=/home/autheo
ExecStart=/usr/local/bin/autheod start --home /home/autheo/.autheo
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
StandardOutput=journal
StandardError=journal
SyslogIdentifier=autheod
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable autheod
sudo systemctl start autheod
sudo systemctl status autheod
sudo journalctl -u autheod -f
4. Method B: Docker
The official image is published at ghcr.io/autheo-blockchain/autheod.
Available tags:
| Tag | Use |
|---|
latest | Current mainnet release |
testnet | Current testnet release |
X.Y.Z | Pinned mainnet release |
X.Y.Z-testnet | Pinned testnet release |
For production validators, pin to a specific release tag rather than latest so that container restarts do not pull an unexpected upgrade. Find release tags on the GHCR package page.
4.1 Pull the image
docker pull ghcr.io/autheo-blockchain/autheod:latest
4.2 Prepare the data directory
The node home inside the container is /root/.autheo. Mount a host directory to persist state across container restarts.
All autheod commands inside the container must use --home /root/.autheo. To run commands against a running container from the host, use docker exec autheo-node autheod <command> --home /root/.autheo.
4.3 Join the network
# 1. Clone the networks repo (on the host)
git clone https://github.com/autheo-blockchain/networks
# 2. Initialize the node
docker run --rm \
-v $HOME/.autheo:/root/.autheo \
ghcr.io/autheo-blockchain/autheod:latest \
autheod init <moniker> --chain-id autheo_2127-1 --home /root/.autheo
# 3. Copy the official genesis
cp networks/mainnet/genesis.json $HOME/.autheo/config/genesis.json
# 4. Set persistent peers
CONFIG=$HOME/.autheo/config/config.toml
sed -i "s|^persistent_peers = .*|persistent_peers = \"$(cat networks/mainnet/persistent_peers.txt)\"|" $CONFIG
# 5. Set minimum gas prices
APP=$HOME/.autheo/config/app.toml
sed -i 's|^minimum-gas-prices = .*|minimum-gas-prices = "10000000000000aauth"|' $APP
Then apply the sync method of your choice from section 5 using the host-side config files.
Apply config changes directly to the host-side directory. Use the same sed commands from section 3.4 — they operate on $HOME/.autheo/config/ which is mounted into the container.
4.5 Run the container
docker run -d \
--name autheo-node \
--restart unless-stopped \
-v $HOME/.autheo:/root/.autheo \
-p 26656:26656 \
-p 26657:26657 \
-p 9090:9090 \
-p 1317:1317 \
-p 8545:8545 \
-p 8546:8546 \
ghcr.io/autheo-blockchain/autheod:latest \
autheod start --home /root/.autheo
View logs:
docker logs -f autheo-node
Stop and restart:
docker stop autheo-node
docker start autheo-node
5. Sync methods
After completing the join and configure steps for your chosen method, select one of the following sync strategies.
Option A: State sync (recommended)
Downloads a recent snapshot from a live sentry and syncs only the remaining blocks.
TRUST_HEIGHT=$(curl -s https://sentry1.autheo.com/block | jq -r '.result.block.header.height')
TRUST_HASH=$(curl -s "https://sentry1.autheo.com/block?height=$TRUST_HEIGHT" | jq -r '.result.block_id.hash')
CONFIG=$HOME/.autheo/config/config.toml
sed -i '/^\[statesync\]/,/^\[/{s/^enable = false/enable = true/}' $CONFIG
sed -i "s|^rpc_servers = .*|rpc_servers = \"https://sentry1.autheo.com,https://sentry2.autheo.com,https://sentry3.autheo.com\"|" $CONFIG
sed -i "s|^trust_height = .*|trust_height = $TRUST_HEIGHT|" $CONFIG
sed -i "s|^trust_hash = .*|trust_hash = \"$TRUST_HASH\"|" $CONFIG
sed -i 's|^trust_period = .*|trust_period = "336h"|' $CONFIG
State sync does not retain historical data before the snapshot height. If you need a full archive node, use genesis sync instead.
Option B: Genesis sync
Replays every block from block 1. Required only for a full archive node.
The chain has had no governance upgrades since genesis — no additional setup is needed for current genesis sync.
If governance upgrades occur in the future, genesis sync will require cosmovisor to manage binary swaps at each upgrade height. Historical upgrade plan names, heights, and binaries will be listed in mainnet/upgrades.json in the networks repo, following this structure:
[
{
"plan_name": "v1.7",
"height": 1000000,
"binary_version": "v1.7.0",
"binary_url": "https://github.com/autheo-blockchain/autheo-chain-core/releases/download/v1.7.0/autheod_linux_amd64"
}
]
plan_name is the exact string used in MsgSoftwareUpgrade. For each entry, create a matching cosmovisor directory with the corresponding binary.
go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@latest
export DAEMON_NAME=autheod
export DAEMON_HOME=$HOME/.autheo
mkdir -p $DAEMON_HOME/cosmovisor/genesis/bin
cp <genesis-binary> $DAEMON_HOME/cosmovisor/genesis/bin/autheod
# For each upgrade in mainnet/upgrades.json:
# mkdir -p $DAEMON_HOME/cosmovisor/upgrades/<plan_name>/bin
# cp <binary> $DAEMON_HOME/cosmovisor/upgrades/<plan_name>/bin/autheod
# The directory name must exactly match the plan_name field.
6. Verify the node
Sync status — catching_up must be false when fully synced:
# systemd
autheod status --node http://localhost:26657 | jq '.sync_info'
# Docker
docker exec autheo-node autheod status --node http://localhost:26657 | jq '.sync_info'
EVM and REST checks — run from the host for both methods:
# EVM - result must be "0x84f" (2127)
curl -s -X POST http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
# EVM - block number
curl -s -X POST http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# REST API
curl -s http://localhost:1317/cosmos/base/tendermint/v1beta1/blocks/latest | jq '.block.header.height'
7. Key management
This chain uses eth_secp256k1 keys.
Create a new key:
# systemd
autheod keys add <key_name> \
--keyring-backend file \
--algo eth_secp256k1 \
--home $HOME/.autheo
# Docker
docker exec -it autheo-node autheod keys add <key_name> \
--keyring-backend file \
--algo eth_secp256k1 \
--home /root/.autheo
Keyring backends:
| Backend | Storage | Use case |
|---|
file | Encrypted file on disk | Recommended for production — passphrase required on each use |
os | OS keychain | macOS Keychain / Linux Secret Service |
test | Plaintext on disk | Development only — never use in production |
Show address:
# systemd
autheod keys show <key_name> -a \
--keyring-backend file \
--home $HOME/.autheo
# Docker
docker exec autheo-node autheod keys show <key_name> -a \
--keyring-backend file \
--home /root/.autheo
List keys:
# systemd
autheod keys list \
--keyring-backend file \
--home $HOME/.autheo
# Docker
docker exec autheo-node autheod keys list \
--keyring-backend file \
--home /root/.autheo
Show validator consensus public key:
# systemd
autheod tendermint show-validator --home $HOME/.autheo
# Docker
docker exec autheo-node autheod tendermint show-validator --home /root/.autheo
8. Create a validator
Requirements:
- Node is fully synced (
catching_up: false)
- Sufficient
aauth balance for self-delegation and fees
- A Sovereign license owned by this account and bound to this validator address in BOUND status
The x/licensedstaking module enforces at the MsgCreateValidator level that a Sovereign license in BOUND status exists on the validator address. The transaction is rejected if this condition is not met.
Step 1 — Verify your Sovereign license is BOUND:
# systemd
autheod query license licenses-by-owner <your_address> \
--node http://localhost:26657 --output json
autheod query license license-by-validator <validator_address> \
--node http://localhost:26657 --output json
# Docker
docker exec autheo-node autheod query license licenses-by-owner <your_address> \
--node http://localhost:26657 --output json
docker exec autheo-node autheod query license license-by-validator <validator_address> \
--node http://localhost:26657 --output json
If your Sovereign license is in ISSUED status (not yet bound), bind it first:
# systemd
autheod tx license bind <license_id> \
--from <key_name> \
--keyring-backend file \
--chain-id autheo_2127-1 \
--gas auto \
--gas-adjustment 1.5 \
--gas-prices 10000000000000aauth \
--home $HOME/.autheo \
--yes
# Docker
docker exec autheo-node autheod tx license bind <license_id> \
--from <key_name> \
--keyring-backend file \
--chain-id autheo_2127-1 \
--gas auto \
--gas-adjustment 1.5 \
--gas-prices 10000000000000aauth \
--home /root/.autheo \
--yes
Confirm the license is now BOUND before proceeding:
# systemd
autheod query license license <license_id> \
--node http://localhost:26657 --output json
# Docker
docker exec autheo-node autheod query license license <license_id> \
--node http://localhost:26657 --output json
Step 2 — Create the validator:
Do not submit create-validator more than once with the same consensus key. Double-signing results in permanent tombstoning — the validator cannot be recovered. Verify you have only one running instance before submitting.
# systemd
VALIDATOR_PUBKEY=$(autheod tendermint show-validator --home $HOME/.autheo)
autheod tx staking create-validator \
--pubkey "$VALIDATOR_PUBKEY" \
--value 500000000000000000000aauth \
--description '{"moniker":"<your_moniker>"}' \
--commission '{"rate":"100000000000000000","max_rate":"200000000000000000","max_change_rate":"10000000000000000"}' \
--min-self-delegation "1" \
--from <key_name> \
--keyring-backend file \
--chain-id autheo_2127-1 \
--home $HOME/.autheo \
--gas auto \
--gas-adjustment 1.5 \
--gas-prices 10000000000000aauth \
--yes
# Docker
VALIDATOR_PUBKEY=$(docker exec autheo-node autheod tendermint show-validator --home /root/.autheo)
docker exec autheo-node autheod tx staking create-validator \
--pubkey "$VALIDATOR_PUBKEY" \
--value 500000000000000000000aauth \
--description '{"moniker":"<your_moniker>"}' \
--commission '{"rate":"100000000000000000","max_rate":"200000000000000000","max_change_rate":"10000000000000000"}' \
--min-self-delegation "1" \
--from <key_name> \
--keyring-backend file \
--chain-id autheo_2127-1 \
--home /root/.autheo \
--gas auto \
--gas-adjustment 1.5 \
--gas-prices 10000000000000aauth \
--yes
The self-delegation inside create-validator triggers the BOUND→ACTIVE license transition automatically.
Step 3 — Verify the validator and license are active:
# systemd
VALIDATOR_ADDR=$(autheod keys show <key_name> --bech val -a \
--keyring-backend file \
--home $HOME/.autheo)
autheod query staking validator $VALIDATOR_ADDR \
--node http://localhost:26657 --output json
# License must now show ACTIVE
autheod query license license-by-validator $VALIDATOR_ADDR \
--node http://localhost:26657 --output json
# Docker
VALIDATOR_ADDR=$(docker exec autheo-node autheod keys show <key_name> --bech val -a \
--keyring-backend file \
--home /root/.autheo)
docker exec autheo-node autheod query staking validator $VALIDATOR_ADDR \
--node http://localhost:26657 --output json
# License must now show ACTIVE
docker exec autheo-node autheod query license license-by-validator $VALIDATOR_ADDR \
--node http://localhost:26657 --output json
9. Troubleshooting
Cannot connect to EVM JSON-RPC
Confirm the JSON-RPC server is enabled and bound correctly in app.toml:
# Both methods — config is on the host-mounted directory
grep -A5 '\[json-rpc\]' $HOME/.autheo/config/app.toml
Node not producing blocks / stuck
systemd:
# Check peer count
curl -s http://localhost:26657/net_info | jq '.result.n_peers'
# Check sync status
autheod status --node http://localhost:26657 | jq '.sync_info.catching_up'
# Check logs
sudo journalctl -u autheod -n 100 --no-pager
Docker:
# Check peer count
curl -s http://localhost:26657/net_info | jq '.result.n_peers'
# Check sync status
docker exec autheo-node autheod status --node http://localhost:26657 | jq '.sync_info.catching_up'
# Check logs
docker logs --tail 100 autheo-node