Skip to content
Tenzro
← All tutorials
Tutorial · Operate

Run a validator node

Become a Tenzro validator: what the role is, the requirements, how to apply during the preview, the commands from download to active set, how to operate it, and how to leave.

Advanced60 min

A validator orders transactions and signs finality for Tenzro Network. It runs Tenzro DAG Consensus: every validator proposes in parallel each round, validators talk over channels keyed by X25519 and ML-KEM-768, and every finalized checkpoint carries a finality certificate signed with ML-DSA-65. A validator holds a self-stake that is slashable, and its consensus key lives in hardware.

This page follows one machine from download to the active set and then covers running it. It states what the code enforces and what has not been proven. For every status and transition see Validator lifecycle.

Easy path

  1. Install Tenzro: one command on Linux and macOS (curl -fsSL https://downloads.tenzro.com/install.sh | sh) or in PowerShell on Windows (irm https://downloads.tenzro.com/install.ps1 | iex). See Install and first run.
  2. Run tenzro and choose "Run a validator". The guide checks the machine, shows the exact command before it runs each step and sets up your keys. A validator also needs stake and approval during the preview; see below.

The requirements and the manual steps follow, for operators who install by hand or script the setup.

Requirements

RequirementWhat the code says
Operating system and archiveLinux x86_64 with tenzro-node-linux-x86_64-cpu.tar.gz (glibc 2.39 or newer), Linux aarch64 with the CPU or CUDA archive (glibc 2.39 or newer), macOS with the Apple silicon or Intel archive, or Windows x86_64 with the CUDA zip (which needs an NVIDIA GPU). A validator does not need a GPU. See Supported hardware.
Identity hardwareA TPM 2.0 (Linux, Windows), a Secure Enclave (Mac), or, on Linux and macOS, the TPM of another machine you own reached through a key holder. A genesis validator needs its own TPM 2.0 or Secure Enclave; a validator whose keys are in another machine's TPM joins after genesis through registration. A passkey is not a consensus key; it authorizes you and grants the key holder. A machine with none of these refuses to start.
CPU, memory, diskThe code sets no minimum. The validator preset sizes the store from the machine: a quarter-gigabyte to 4 GiB of store memory (1/32 of the memory pool) and a 64 MiB/s background write limit. The fleet example in deploy/validator-deployment.md uses 4 vCPU, 16 GB RAM and a 100 GB SSD; that is an example, not an enforced requirement.
NetworkOutbound UDP 9001 (the node's QUIC endpoint) and outbound TCP 443 (relays). No inbound port is required; validators exchange consensus messages with every other validator, so forward UDP 9001 (or use UPnP, NAT-PMP or PCP on the router) for direct reachability. Behind a NAT that hole punching cannot cross it works through relays at higher latency. Run tenzro-node doctor to see which case you are in. The RPC (8545), web (8080), MCP (3001) and A2A (3002) listeners bind loopback only; do not open them.
Self-stakestake.validator_tnzo, 10,000 TNZO at genesis, plus gas. Read the value in force with tenzro_getNetworkParams. A raise does not eject a seated validator.
AdmissionDuring the preview validator.admission_approval is 1: you register only from an account that an enacted approve_validators governance proposal named. Governance sets it to 0 to open admission. Any machine can run a node and follow the chain without approval.
UnbondingAfter you exit, the bond stays slashable for staking.validator_unbonding_ms, 7 days at genesis, then it can be withdrawn.
UptimeSee below.

What the code enforces about uptime

  • Inactivity ejection: a validator that signs nothing the chain certifies for staking.inactivity_limit_epochs consecutive epochs (5,000 at genesis, which is 208 days at the hourly epoch of the launch genesis) is moved to exit. An ejection never takes the active set below staking.active_set_floor (4 at genesis).
  • Jail: signing two conflicting checkpoints with one index slashes the bond and jails the validator for slashing.jail_term_epochs (720 at genesis), or until a reinstate_validator proposal passes. It then returns as a candidate. Slashing is also applied for a provable breach of your own signed operator policy. See Slashing.
  • No slash for being offline is defined for a validator in the parameters. Being offline still costs the network margin: at four validators one stop leaves no spare, and the founding design asks for at least seven validators on four independent operators so planned stops fit.

Apply for admission

  1. Send an application through the operator form naming the account that will hold the stake. Admission is a governance decision: an approve_validators proposal naming the account has to be enacted before registration is accepted. See Governance.
  2. Prepare the machine while you wait (steps 1 to 4 below). You can run as a non-voting node first.

Registration from an account that was not approved is refused. There is no other path during the preview.

1. Download and verify

Download the archive for your platform from Downloads together with SHA256SUMS, SHA256SUMS.sig, tenzro-release.pub and the genesis file genesis.toml, then, with cosign 3.x:

bash
cosign verify-blob --key tenzro-release.pub --insecure-ignore-tlog=true --signature SHA256SUMS.sig SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing

Both must pass before you unpack anything; the second also checks genesis.toml, which the signed list names. Check the genesis file against the launch manifest as described in Verify your download. The reasons for the flag and the Windows and macOS forms are in Verify your download. Every validator must run a compatible release: a node on a different build or genesis computes a different state root and its messages are rejected.

bash
tar -xzf tenzro-node-linux-x86_64-cpu.tar.gz
sudo install -m 0755 bin/tenzro-node bin/tenzro /usr/local/bin/
tenzro-node --version
tenzro-node hardware

tenzro-node hardware prints the build, the accelerators and whether the node would start here, and exits non-zero if it would not.

2. Provision the hardware key

On Linux, run this once per machine, as the user that will run the node and that can open /dev/tpmrm0:

bash
ls -l /dev/tpmrm0
tenzro-node tpm provision

It creates the storage root, the machine attestation key and the node identity key in the TPM, and is idempotent. The node only reads these keys and refuses to start until they exist. Because they derive from the chip's endorsement seed, provisioning again after a reinstall gives back the same identity. On Windows run it from an elevated prompt. On a Mac the Secure Enclave needs no provisioning step.

A machine with no TPM can hold the validator role through a key holder: the TPM machine runs tenzro-node tpm serve with a file that enrols this client for derived keys, this machine runs tenzro-node tpm key-holder, and you approve it with a passkey grant (tenzro-node tpm grant-request, then tenzro-node tpm grant-install). The node starts with --tpm-key-holder <socket> --tpm-label <label>. Such a machine cannot be a genesis validator, because the genesis entry (tenzro-node validator-entry) is read only from the machine's own TPM or Secure Enclave; it joins after genesis and registers with tenzro validator register --tpm-key-holder. The key holder runs on Linux and macOS only. Limits: a grant lasts at most the provider's max_grant_hours (720 by default) and a reboot of the key holder needs a new one, without which the validator cannot sign; every signature is a round trip to the provider; and the ML-DSA-87 plus P-384 scheme is not available this way. See Validator lifecycle.

3. Start as a non-voting node

bash
tenzro-node \
  --roles validator \
  --data-dir /var/lib/tenzro \
  --genesis genesis.toml

With no --boot-nodes the node joins the network through its genesis validators. On this release a new node joins by block replay from genesis: it replays the chain from block 0, verifying finality certificates, says so in its log, and is in step when it reports the network's finalized height. Joining from a snapshot arrives in an update; a validator always replays. Until it is admitted it runs as a non-voting node: it verifies and relays but does not propose or vote. On an idle chain the node can sit at block 0 with peers until the next block is minted (the heartbeat default is 10 minutes); that is not a fault.

The guided setup does steps 2 to 5 for you: tenzro setup --path network --mode validate --apply checks the hardware root, offers to provision the keys, writes a unit that boots with --validator-self-stake, starts the service, follows the sync and prints the account to fund and the amount.

4. Fund the validator account

The validator account derives from the same hardware root. Find its address, send it the self-stake plus gas from an account that holds TNZO, and check:

bash
tenzro node status
tenzro wallet balance --address <validator-address>

Sponsored bonds exist (tenzro sponsor check, tenzro sponsor apply, enacted SponsorValidatorBond proposals) but validator.sponsored_bond_max_tnzo is 0 by default, which disables them until governance sets it.

5. Register

Once your account is approved and funded, restart the node with the self-stake in wei (1 TNZO is 10^18 wei). The node signs its own registration transaction with its hardware keys.

bash
tenzro-node \
  --roles validator \
  --data-dir /var/lib/tenzro \
  --validator-self-stake <self-stake-in-wei>

Registration is refused below the on-chain minimum, with a balance that does not cover stake plus gas, or from an account that was not approved. Check it:

bash
tenzro validator get <validator-address>
tenzro validator list --status Candidate

6. Activation

The set changes only at epoch boundaries. Your status moves from Candidate to PendingActive to Active after a short activation delay, subject to the activation churn cap:

bash
tenzro validator list --status PendingActive
tenzro validator list-active

From then on the TPM certifies a session key once per epoch and the node signs its votes with it; the hardware is not on the hot path of each vote.

Check that you are healthy

bash
curl -s http://127.0.0.1:8080/health
curl -s http://127.0.0.1:8080/ready
curl -s http://127.0.0.1:8080/status
tenzro node status
tenzro node syncing
tenzro validator get <validator-address>
curl -s http://127.0.0.1:8545 -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tenzro_getFinalizedBlock","params":[]}'

A healthy validator has peers, is not syncing, reports Active, and sees the finalized height advance. A container or process that is up is not enough: consensus progress is the signal. Prometheus metrics are at http://127.0.0.1:8080/metrics.

Operations

Service management

Run the node as a service that restarts on failure. Example systemd unit for the archive install:

ini
[Unit]
Description=Tenzro validator
After=network-online.target
Wants=network-online.target

[Service]
User=tenzro
ExecStart=/usr/local/bin/tenzro-node --roles validator --data-dir /var/lib/tenzro --genesis /var/lib/tenzro/genesis.toml
ExecStop=/usr/local/bin/tenzro-node graceful-exit
Restart=always
RestartSec=10s
TimeoutStopSec=60
KillSignal=SIGTERM

[Install]
WantedBy=multi-user.target

graceful-exit waits until the node leads none of the next rounds, then starts shutdown (it waits at most 60 seconds). After a crash or reboot the node re-derives the same identity from the same hardware and returns as the same validator, so keep --validator-self-stake out of the unit once you are registered, or leave the one tenzro setup wrote. Never run two nodes from one identity: signing two conflicting checkpoints is provable and is slashed. Give the service user, and no one else, access to /dev/tpmrm0.

Ports, firewall and time

Open nothing inbound unless you want direct reachability (UDP 9001). Keep the four HTTP listeners on loopback; the node refuses to start with one bound elsewhere. If you expose RPC, do it through your own TLS reverse proxy and pass its https URL as --external-rpc-addr; a validator that is not an RPC node carries no admin token. Keep the system clock synchronized; clock skew is one of the listed causes of a validator not signing, but the repository documents no skew tolerance, so none is stated here.

Disk, backups and the data directory

The node prunes to the governed history window and compacts when the data volume passes [storage] prune_watermark_pct (75%). Past refuse_watermark_pct (90%) it refuses non-essential data such as model downloads and uploads; consensus writes are never refused. Alert before the volume is full.

Your keys are not in the data directory and cannot be backed up. What the directory holds that peers cannot return is consensus/ (the record of checkpoints you signed, which stops you signing two for one index after a restart), wallets/, contacts.json, credentials/ and access.toml. tenzro-node backup --dest <dir> copies the newest epoch snapshot while the node runs; the node never sends a backup anywhere. If the TPM or board is lost, the identity is lost with it. Moving to new hardware is a key-rotation transaction signed by the current key, so do it before the old machine is gone. Never delete the data directory to "reset" a validator.

Key custody and grants

With a key holder, the passkey grant must be installed again after every reboot of the key-holder machine and whenever it ends, at most max_grant_hours after it is made. Without an unexpired grant the validator cannot sign. A node restart alone needs no new grant if the key holder keeps running as its own service. tenzro-node tpm session-status shows when the current delegation ends.

Upgrades

An upgrade replaces the binary and keeps the data directory and genesis. On start the node checks the chain on disk against its genesis and refuses to run on a mismatch.

  1. Read headroom first. If live validators are at quorum or one above it, do not stop one; restore a validator first. scripts/validator-prestop-check.sh in the repository judges a planned stop set against the live view.
  2. Stop one validator with tenzro-node graceful-exit (or the unit's stop), swap the binary, start it.
  3. Confirm peers, /ready and an advancing finalized height before touching the next. Roll one validator at a time.

No tested version-compatibility matrix is published: a rolling upgrade across a change in state rules is a coordinated event, and docs/KNOWN-RESIDUALS.md lists changes that must carry an activation height before they can be rolled out on a running network.

Monitoring and alerts

Alert on: finalized height not advancing for 10 minutes; live validators at quorum or one above it (the repository's deploy/monitoring/alerts.yml carries these as ValidatorHeadroomZero, ValidatorHeadroomOne and FinalizedHeightStalled10m); peer count dropping; /ready failing; memory growth; disk past the watermarks; a non-zero tenzro_consensus_equivocation_evidence, which indicates a misconfigured or compromised validator. Read the list with tenzro_listActiveValidators and tenzro_listValidators, which shows jailed_until_epoch for a jailed validator. The node logs to stderr (--log-format json for structured output; RUST_LOG filters). Under systemd read it with journalctl -u tenzro-node. The signing health flag is not a reliable alarm; watch for the refusal line the node logs at start-up and when signing is first refused.

Incidents

  • Corrupt chain database: the node refuses to start with Corruption: block checksum mismatch. Do not wipe the directory. Stop the node, copy consensus/, wallets/, contacts.json, credentials/ and access.toml aside, move the directory away, put back only those, and start again without --state-sync-from and without checkpoint flags. On this release the node rebuilds the chain by block replay from genesis, fetching the blocks from its peers; wait until it reports the network's finalized height. Finalized blocks are on the peers, so the replay restores the state. Restoring from a peer's snapshot arrives in an update.
  • Rejoining after a long absence: the node continues from its own tip by block replay; add --checkpoint-hash and --checkpoint-height of a finalized block you verified out of band to defeat a long-range fork. If you were ejected for inactivity you are no longer in the set and must register again; whether a re-registration needs a new approval while admission approval is on is not documented.
  • Chain halted below quorum: nothing is certified and the set cannot repair itself. Bring the original machines back first; the same hardware returns with the same identity. If machines are gone for good the recovery manifest procedure applies (--recovery-check, --recovery-manifest; see docs/RECOVERY-BELOW-QUORUM.md), agreed among the surviving operators.
  • Jailed: stop every copy of the validator, find the cause, and wait out the term or for a reinstate_validator proposal. The slash is not undone.

Security

Verify every download. Run the node as an unprivileged user on a dedicated host. Do not put an admin token on a validator. Credentials the node stores for model origins are sealed to the machine's TPM or Secure Enclave. No key is ever written to disk, to configuration or to an environment variable.

Capacity facts from the code

Connections: 1,024 overall and 512 in a separate consensus pool, 8 and 4 per peer, idle timeout 30 s. The edge preset applies on a machine with 8 GiB of memory or less; the validator preset otherwise.

Resource management

Every control below is a flag or configuration key of the node; defaults are those of the node reference. Nothing here is a measured efficiency claim.

ControlFlag or keyDefault
Resource preset--tier auto|edge|validator|provider (TENZRO_TIER)auto: provider for roles that run models, edge at 8 GiB of memory or less, validator otherwise
Runtime worker threads--worker-threads N2 (1 on a one-core edge device)
Store memory, write buffer, background jobs, background write rate, open files[storage] memory_mb, write_buffer_mb, background_jobs, background_write_mb_per_sec, max_open_filesedge: 1/16 of the memory pool (32 to 256 MiB), 16 MiB, 1, 16 MiB/s, 256; validator and provider: 1/32 (256 MiB to 4 GiB), 64 MiB, 2, 64 MiB/s, 1000
Data-volume watermarks[storage] prune_watermark_pct, refuse_watermark_pct75 and 90
History retentiona governed network parameternot a node setting
Connection limits[iroh.connection]: max_connections, max_connections_per_peer, max_consensus_connections, max_consensus_connections_per_peer, idle_timeout_secs, stream and window limits1024, 8, 512, 4, 30, 100 streams, 32 MiB window
TPM use[tpm] call_timeout_secs, signs_per_second, quotes_per_second10, 30, 2
Model memory--reserve-gb, --resident-ceiling-gb, --on-demand-ceiling-gb16 GiB held back; 60% of the rest; the remainder
Build variantlight (no model engines; refuses ai, compute, tee), standard, standard plus a GPU backendsee Supported hardware

Not found in the node reference: a network bandwidth cap, a CPU cap, or a GPU selection or GPU memory limit flag. Cap those with the service manager (for example CPUQuota= and MemoryMax= in the systemd unit); the repository documents no such limits for production units, only for its test harness. An idle chain makes no empty blocks; with no transactions the leader mints on a long heartbeat (10 minutes by default), and the cost of idle consensus rounds has not been measured here.

To see utilization, read /metrics on the web port (8080, loopback) and /status. tenzro_livenessStats runs one sweep of identity liveness TTLs and is not a utilization gauge.

A release gate budgets 100 MB stripped binary and 256 MiB idle, 320 MiB loaded resident memory for a --roles light node. Measurements of a light validator are in docs/NODE.md (Measurements) in the repository.

Add stake

bash
tenzro validator increase-stake --additional 500

Leave

Leaving is a signed exit transaction. The validator stays active until the next epoch boundary, then becomes Exited, and the stake unbonds over 7 days. It stays slashable while unbonding, so evidence of a fault committed while active can still be acted on. Do planned maintenance with tenzro-node graceful-exit and check headroom; do not exit to stop a node for a day.

bash
tenzro validator exit
tenzro validator get <validator-address>

Known limits

  • Admission during the preview is by governance approval. There is no other path.
  • Four validators is the arithmetic floor for tolerating one fault; fewer than seven on four operators does not meet the founding requirement.
  • The participation roster at epoch close is a residual state-split risk on a node that does not hold that epoch's set (restored from a snapshot without epoch history). It must be redesigned before a mainnet; see docs/KNOWN-RESIDUALS.md.
  • A restarted validator can stay outside the mesh for minutes under packet loss.
  • A key held through a key holder depends on the provider's reachability and on grants.
  • No rolling-upgrade compatibility matrix, clock-skew tolerance or minimum hardware is documented.
  • Recovery from a halt below quorum has been exercised in tests, not on this network.

Next steps

A close view of a circuit board with a line of light ending at a small chip.
Validate

Run a validator.

The signing key is rooted in the machine's TPM 2.0 or Secure Enclave, or held by a delegated key holder.

ExploreJoin the network