Fullnode Operations
Run a Talero fullnode
A Talero fullnode is the standard builder and integration node: it syncs the network,
serves JSON-RPC and REST, participates in transaction gossip, and can power private or hardened public infrastructure.
This guide follows the repository's containerized path and stays inside the public-safe boundary.
Fullnode
Mainnet-oriented
Public RPC possible
Privacy hardened
This page does not publish admin CIDRs, trusted proxy ranges, signer secrets, or other deployment-specific controls.
Keep those details in your private operations material.
Requirements
- A persistent Linux host with storage for
/data.
- Docker Engine and Docker Compose plugin.
- The Talero node repository or release bundle on the host.
- Canonical mainnet identity material from the approved release process:
TALERO_EXPECTED_CHAIN_ID,
TALERO_EXPECTED_GENESIS_HASH,
TALERO_GENESIS_TIMESTAMP_SECS,
and the current bootnode list.
- A clear decision about whether the node will stay private or sit behind a hardened public RPC edge.
Install Docker on Ubuntu
If the host is fresh, use Docker's official Ubuntu flow.
For updates or distro-specific changes, verify against the
official Docker Engine install guide for Ubuntu.
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo \"${UBUNTU_CODENAME:-$VERSION_CODENAME}\") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker "$USER"
Log out and back in after changing Docker group membership.
Prepare the deployment files
sudo mkdir -p /opt/talero
sudo chown "$USER":"$USER" /opt/talero
cd /opt/talero
# Place the Talero node release or repository here
# Required files include:
# Dockerfile
# docker-compose.mainnet.yml
# docs/
# tools/
cd /opt/talero/node
docker compose -f docker-compose.mainnet.yml build
The canonical release profile in the repository expects the default feature set, including
hybrid PoW / PoS-BFT, REVM, checkpoint-notary, safe-mode, honeytrap, and network-health.
Mainnet chain identity
On a fresh mainnet datadir, the node refuses to initialize unless the expected genesis hash and matching genesis timestamp are present.
It also checks the expected chain ID against the actual runtime identity.
- Set
TALERO_EXPECTED_CHAIN_ID to the approved mainnet chain ID.
- Set
TALERO_EXPECTED_GENESIS_HASH to the canonical mainnet genesis hash.
- Set
TALERO_GENESIS_TIMESTAMP_SECS to the exact genesis timestamp used by that chain.
- Set
TALERO_BOOTNODES to the current canonical bootnode list.
Do not add consensus-critical override variables such as TALERO_CHAIN_ID,
TALERO_EVM_BLOCK_GAS_LIMIT, or PQ_REQUIRED_FROM_HEIGHT on a normal mainnet fullnode.
The mainnet startup guard rejects that pattern by default.
Choose the RPC exposure model
For a containerized fullnode, the safe default is to let the node listen on container 0.0.0.0:8547,
but publish that port to host loopback only. If you want public RPC, terminate it through a controlled reverse proxy.
Recommended host-loopback override
cd /opt/talero/node
cat > docker-compose.mainnet.private-rpc.yml <<'EOF'
services:
talero-node:
ports:
- "127.0.0.1:8547:8547"
- "30303:30303"
- "30303:30303/udp"
EOF
| Surface |
Recommended exposure |
Why |
| RPC |
Host loopback or reverse proxy |
Lets you harden the public edge without publishing raw node ports. |
| P2P TCP and UDP |
Public |
The fullnode needs normal peer connectivity. |
| /metrics |
Private only |
Operational telemetry should not be internet-facing by default. |
Create the fullnode environment file
cd /opt/talero/node
cat > .env.mainnet.fullnode <<'EOF'
TALERO_NETWORK=mainnet
TALERO_ROLE=fullnode
TALERO_ROLE_STRICT=1
# Canonical chain identity from the approved mainnet release process
TALERO_EXPECTED_CHAIN_ID=REPLACE_WITH_CHAIN_ID
TALERO_EXPECTED_GENESIS_HASH=0xREPLACE_WITH_CANONICAL_GENESIS_HASH
TALERO_GENESIS_TIMESTAMP_SECS=REPLACE_WITH_CANONICAL_GENESIS_TIMESTAMP
# RPC inside the container
TALERO_RPC_LISTEN=0.0.0.0:8547
TALERO_RPC_PUBLIC_MODE=1
TALERO_RPC_READONLY=0
TALERO_RPC_TRUST_X_FORWARDED_FOR=0
# P2P
TALERO_P2P_LISTEN=0.0.0.0:30303
TALERO_P2P_SELF_ADDR=YOUR_PUBLIC_IP:30303
TALERO_BOOTNODES=BOOTNODE_A:30303,BOOTNODE_B:30303
# Fullnode behavior
TALERO_DISABLE_MINING=1
TALERO_EVM_ENABLED=1
TALERO_EVM_REPLAY_ON_STARTUP=1
TALERO_EVM_REPLAY_STRICT_STARTUP=1
# Public RPC hardening
TALERO_PRIVACY_ENABLED=1
TALERO_PRIVACY_PUBLIC_MODE=masked
TALERO_HONEYTRAP_ENABLED=1
TALERO_SAFE_MODE_ENABLED=1
TALERO_SAFE_MODE_MANUAL_OVERRIDE=auto
# Logging
TALERO_LOG=info
TALERO_LOG_FORMAT=json
EOF
This is a public-safe starting point. It deliberately leaves out admin CIDRs, trusted CIDRs,
mining CIDRs, and proxy trust ranges because those are infrastructure-specific and should stay out of public docs.
If the node remains entirely private, you can set TALERO_RPC_PUBLIC_MODE=0.
If it sits behind a public builder edge, keep public mode on and let privacy, honeytrap, and safe-mode do their work.
Start the fullnode
cd /opt/talero/node
TALERO_ENV_FILE=.env.mainnet.fullnode \
docker compose \
-f docker-compose.mainnet.yml \
-f docker-compose.mainnet.private-rpc.yml \
up -d
cd /opt/talero/node
TALERO_ENV_FILE=.env.mainnet.fullnode \
docker compose \
-f docker-compose.mainnet.yml \
-f docker-compose.mainnet.private-rpc.yml \
logs -f talero-node
Verify node health
curl -sS http://127.0.0.1:8547/health | jq '{
ok,
network,
role,
head,
finalized,
sync,
p2p,
rpc
}'
curl -sS -X POST http://127.0.0.1:8547/rpc \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
curl -sS -X POST http://127.0.0.1:8547/rpc \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"talero_getPrivacyConfig","params":{}}'
role should be "fullnode".
sync.hasSeenPeer should turn true after bootstrapping.
p2p.peersTotal should rise above zero.
- If you intend to expose public RPC, confirm the privacy config and safe-mode status through RPC before you put traffic on the node.
Upgrade flow
cd /opt/talero/node
tar -C ./data -czf fullnode-backup-$(date -u +%Y%m%d-%H%M%S).tgz .
docker compose -f docker-compose.mainnet.yml build
TALERO_ENV_FILE=.env.mainnet.fullnode \
docker compose \
-f docker-compose.mainnet.yml \
-f docker-compose.mainnet.private-rpc.yml \
up -d
After restart, repeat the health and RPC checks.
Troubleshooting
| Error shape |
Likely cause |
Fix |
requires TALERO_BOOTNODES |
Mainnet bootnode list is missing. |
Set the canonical mainnet bootnodes. |
requires TALERO_EXPECTED_GENESIS_HASH |
Fresh mainnet datadir without identity guards. |
Set expected chain ID, genesis hash, and genesis timestamp. |
chain_id() is still 1337 |
You are using a devnet-style build or incorrect release material. |
Deploy the approved mainnet build or release bundle. |
| Public RPC looks masked or redacted |
Privacy hardening is active. |
This is expected on public mode. Use a private integration node for unredacted access. |
cd /opt/talero/node
TALERO_ENV_FILE=.env.mainnet.fullnode \
docker compose \
-f docker-compose.mainnet.yml \
-f docker-compose.mainnet.private-rpc.yml \
logs --tail=200 talero-node