Skip to content

Environment Variable Reference

Docs-site note (rewritten 2026-07-11): This page is grounded directly in source — the binary's own baked-default table and the per-flag getenv call sites that consume each variable — not in intent or naming. Where a flag's default changed since this page was first written (2026-06-25), that's because the binary itself changed: most of what used to be a manual deploy-script flag list is now filled in automatically. For the build-time (-D) side of the picture, see the Build-Flag Reference; for how these runtime variables reach the validator process during a deploy, see Deploying Vexor.


The short version

Vexor now bakes its own production defaults. The very first thing the binary does at startup — before any subsystem reads an environment variable — is fill in 23 VEX_* variables to their proven values, but only if you haven't already set them. An explicit value on your deploy command line always wins over the bake.

That means the honest, current operator surface is small: a handful of machine-specific variables (which binary, which cores, whether AF_XDP is available on this NIC) plus your keys and network address. Everything that used to be a long "remember all these flags" recipe is now a property of the binary itself. See the minimal recipe on the Build-Flag Reference page.

Two guards keep the bake safe:

  1. Production-only. The bake is skipped entirely when the binary detects an offline-replay or golden-gate context (VEX_LEDGER_REPLAY or VEX_SNAPSHOT_OFFLINE set). Those runs deliberately want the ledger write path, the watchdog's restart authority, and leader broadcast to stay off — baking them on would be actively wrong for a read-only replay.
  2. Machine facts are never baked. A fixed set of variables — which binary to run, hardware/NIC capability, core lists, snapshot freshness policy — legitimately differ from host to host and are deliberately left for the operator to set. See the minimal operator surface below.

Value-parse semantics

Most of the flags on this page follow one contract: unset means "let the binary decide" (baked default if there is one, otherwise off); an explicit 0 or false means "off, and this overrides the bake"; any other value — including the conventional 1 — means "on."

A few flags parse more strictly and only accept an exact "1" (or, on one flag, an exact "0") to arm or disarm; "true" / "yes" will not arm them. If you want a value that's guaranteed to work everywhere on this page, use 1 to turn something on and 0 to turn it off — both are accepted by every flag here, strict or not.


The baked necessity set

These 23 variables are set to the value below automatically at startup if you don't set them yourself. You do not need to put any of these in a deploy command for a standard testnet voting deploy — they're listed here so you know what a "default" boot is actually doing, and so you can force one off (=0) for a specific diagnostic session without a rebuild.

Variable Baked value What it actually does
VEX_LEDGER 1 Initializes the persistent VexLedger blockstore and spawns its write tile. See VexLedger.
VEX_DAG_DISPATCH 1 Enables the single-threaded conflict-DAG dispatcher on the replay path — the live transaction-ordering mechanism.
VEX_PARALLEL_EXEC 1 Arms wave-barrier parallel transaction execution inside the DAG dispatcher (requires VEX_DAG_DISPATCH, also baked on).
VEXOR_ED25519_FEC_DEDUP 1 Arms the Ed25519 FEC-set signature-dedup cache in the verify tile.
VEX_DISABLE_NETHASH 1 Despite the name, this value turns a liveness band-aid off: the node votes its own locally computed bank hash rather than falling back to a cluster-reported one.
VEX_LEADER_BROADCAST 1 Enables real leader-slot block broadcast instead of loopback-only. On its own this only ever produces empty, cluster-accepted blocks — it cannot make a block transaction-bearing by itself (see experimental flags below).
VEX_TURBINE_REAL_STAKES 1 Builds the turbine broadcast/retransmit tree from real epoch stake weights instead of a uniform stub (falls back to uniform, with a warning, if epoch stakes aren't populated yet).
VEX_STAKE_BPF 1 Routes stake-program instructions through the on-chain SBPF VM path instead of a native Zig implementation — the canonical path for testnet.
VEX_FORK_ISOLATION 1 Enables per-fork account-state isolation during replay. Strict parse: only an exact "1" arms it.
VEX_REPAIR_INFLIGHT 1 Arms in-flight repair-request tracking, so the same shred isn't re-requested while a request is already outstanding.
VEX_CATCHUP_ADAPTIVE_REFIRE 1 Arms adaptive repair re-fire behavior during catch-up.
VEX_VOTE_REFRESH 1 Re-sends the byte-identical last vote on a fresh blockhash if the node stalls without casting a new one — never a new vote, so it can't be a slashing risk by construction.
VEX_SWITCH_PROOF 1 Arms (not shadow-only) the cross-fork switch-threshold proof that authorizes voting a different fork than the node's current one, on top of — never instead of — the lockout check.
VEX_PROP_GATE 1 Refuses to vote a fork whose propagation hasn't been confirmed, when armed.
VEX_PROP_LATCH 1 Selects canonical leader-window propagation-latch target selection for vote targeting.
VEX_CANONICAL_VOTE 1 Arms canonical heaviest/canonical-leaf vote selection, the counterpart to VEX_SWITCH_PROOF above — the two are designed to run together and are baked on together.
VEX_VOTE_PREWARM 1 Arms targeted QUIC connect-ahead for validators the node expects to need shortly, in the vote poller.
VEX_DISABLE_CURL_VOTES 1 Forces the legacy curl/UDP vote-relay path off. Belt-and-suspenders: that path is already opt-in, so this mostly guards against it being turned on by accident.
VEX_REPAIR_SKIP_ABANDONED 1 Only takes effect when a cluster oracle also confirms a slot is genuinely abandoned — it is not a blind repair skip.
VEX_WATCHDOG_RESTART 1 Lets the liveness watchdog restart the process on a sustained wedge, instead of alert-only.
VEX_LEDGER_MAX_BYTES 107374182400 (100 GiB) Bounds on-disk ledger size; prunes the oldest whole segments once the cap is hit.
VEX_LEDGER_KEEP_SLOTS 216000 Alternate ledger-prune policy (keep the last N slots); the byte cap above takes precedence if both are set.
VEX_VOTE_FANOUT_ROTATIONS 3 Number of fanout rotations used when broadcasting a vote.

The minimal operator surface

These are the variables that legitimately vary per host and are never filled in automatically. Everything else that's genuinely load-bearing for a standard deploy is above.

Variable Purpose
VEX_BINARY Which pre-built binary to run.
VEX_ALLOW_NO_BN254 Required (=1) on every deploy. The BN254 boot guard is designed around a linked Firedancer Ballet BN254 library and refuses to boot without either that library or this explicit flag; Vexor's production binary has no such library by design (BN254/Poseidon run through Vexor's own vex_crypto instead), so this variable tells the guard that is expected. See Building Vexor.
VEX_ENABLE_AFXDP Enables AF_XDP zero-copy networking on NICs that support it. Note: the transport switch itself comes from the corresponding CLI flags your deploy wrapper derives from this variable; the variable's own direct effect in the binary is narrower — a dedicated allocator arena for the receive thread and occupancy instrumentation. Set it wherever your deploy tooling expects it.
VEX_FRESH_SNAPSHOT 1 (recommended default) re-extracts the snapshot every boot and, if the local tarball is more than VEX_SNAP_MAX_AGE_SLOTS behind the live tip, downloads a fresh near-tip base+incremental pair. Working account cache, ledger, and tower state are wiped either way — this is the production-correct path, since it never inherits possibly-corrupt local state.
VEX_SNAP_MAX_AGE_SLOTS Freshness threshold for the check above, in slots. 0 forces a refetch on every boot; a very large value effectively preserves whatever local snapshot is already there.
VEX_REUSE_SNAPSHOT 1 boots from the existing local extracted-* snapshot without deleting or re-downloading it — the safe way to reproduce a specific slot for carrier diagnosis or regression repro. Working account cache, ledger, and tower are still wiped and rebuilt from that snapshot. Default 0 (off; use VEX_FRESH_SNAPSHOT behavior instead).
VEX_PARALLEL_EXEC_CORES Which CPU cores host the parallel-execution worker pool. Hardware-specific — see Hardware.
VEX_TASKSET_CORES The process-wide CPU affinity mask. Hardware-specific.
VEX_SIGVERIFY_CORES Which CPU cores run the whole-slot parallel replay-sigverify pre-pass (see Consensus). Default 4,25,26,28,29,30 (6 workers). Two of those cores are deliberately shared with VEX_PARALLEL_EXEC_CORES — sigverify is a Phase-1 whole-slot pre-pass and parallel-exec is a Phase-2 per-entry pass, so they never contend in time. Hardware-specific — see Hardware.
VEX_UMEM_RESERVE AF_XDP UMEM frame reservation count.

Identity keypair, vote keypair, public IP, ports, cluster entrypoints, and data-directory paths are CLI arguments, not environment variables — see the Build-Flag Reference minimal recipe for an example and your deploy tooling's own flags for the full argument list.


Experimental, keep-gated flags (not production)

These compile in and ship in the binary, but are deliberately left off by default and off in the baked-default list — they're real, working code paths that haven't earned a place in the standard deploy yet.

Variable What it does Status
VEX_TPU_INGEST Enables transaction ingest into an in-memory mempool, independent of block broadcast. Not production. Safe on its own (loopback only), but see the interlock below.
VEX_TXBEARING_BROADCAST The interlock that lets a broadcast block actually carry transactions, instead of an empty but cluster-accepted block. Not production. Earlier guidance here stated flatly that transaction-bearing blocks diverge from consensus and get skipped. As of v0.9.3-j, production executes every packing candidate through the same instruction-dispatch ladder replay uses and refuses a candidate up front via a pre-admission oracle, so the architectural gap that let production and replay disagree is closed. That closes the defect class this note used to warn about, but the containment has not yet been proven against a live cluster in this release, so the flag stays off: leave it unset.
VEX_FORCE_INLINE_PRODUCE Runs block production inline on the replay thread rather than deferring it. One of the four variables the produce path requires; see Arming block production below. Not production.
VEX_PRODUCE_EXEC Selects the executor used to pack candidates during production. Named values only — the default is off, which produces empty blocks. vote_only packs vote transactions. Not production.
VEX_PACK_BUDGET_MS Wall-clock budget, in milliseconds, for collecting candidates during one leader slot. Default 60. The budget is checked after each batch is absorbed, so a slot always makes progress even if the value is set very low. Most of a slot's wall clock is fixed hashing cost, which is where this default comes from — raising it does not buy proportionally more packing. Optional; the default is correct for a standard deploy.
VEX_PACK_MAX_SCAN Hard cap on candidates examined in one slot, independent of the clock. Default 100000, matching Agave's per-scheduling-pass scan cap. Bounds the work even if the wall clock misbehaves. Optional; the default is correct for a standard deploy.
VEX_GOSSIP_PROP Gated, working code path. Not production. Confirm the exact effect in source before relying on it — not covered in operator-facing deploy guidance.
VEX_BLOCK_DAG Gated, working code path. Not production. Confirm the exact effect in source before relying on it — not covered in operator-facing deploy guidance.

Arming block production

Block production requires four variables together. Set three of the four and the node boots, runs, reports healthy, and produces empty blocks — the arming state defaults to off, and nothing in the normal logs distinguishes "disarmed" from "nothing to pack":

VEX_TPU_INGEST=1 VEX_FORCE_INLINE_PRODUCE=1 VEXOR_STATUS_CACHE=1 VEX_PRODUCE_EXEC=vote_only

VEX_PRODUCE_EXEC is the arming state itself and is the one most easily lost, because it is the newest of the four — a deploy recipe copied forward from before it existed will carry the other three and look complete. Confirm all four reached the process rather than trusting the command line:

tr '\0' '\n' < /proc/<pid>/environ | grep -E 'VEX_TPU_INGEST|VEX_FORCE_INLINE_PRODUCE|VEXOR_STATUS_CACHE|VEX_PRODUCE_EXEC'

VEXOR_STATUS_CACHE additionally needs the binary built with -Dprod, since the corresponding compile-time setting is baked in rather than read at runtime.


Diagnostic and forensic flags

Everything in this category defaults off, is intended for parity investigations or crash forensics, and has no place in a normal deploy. Rather than list every individual name, here's the shape of what exists, grouped:

Category What it's for Examples
Account read/write recorder Per-slot account access tap for parity investigations VEX_RECORD_READS, VEX_RECORD_WRITES, VEX_RECORD_SLOTS
State/field dumps Dump bank or account state at a given point VEX_FREEZE_DUMP_SLOT, VEX_ACCT_DUMP, VEX_DUMP_ENTRY
Lt-hash verification Verify or trace the accounts lt-hash VEX_VERIFY_LTHASH_SLOT, VEX_VERIFY_LTHASH_WRITES, VEX_LT_DELTA
Vote / gossip probes Byte-level vote and gossip transport diagnostics VEX_VOTE_PROBE, VEX_PROBE_SYSVAR_BYTES, VEX_PROBE_IDENTITY
SBPF VM debug BPF interpreter tracing VEX_CALLX_DEBUG, VEX_VMFAULT_DEBUG, VEX_BPF_DBG_PROBES
KAT / fixture replay Known-answer-test harness inputs VEX_KAT_HASH, VEX_FIXTURE_ONLY
Allocator debug Swap in Zig's checked debug allocator to catch use-after-free with a real stack trace VEX_DEBUG_ALLOC — slow, boot only to hunt a crash, never for production

If you're chasing a specific consensus or performance question and think one of these is relevant, it's worth confirming the exact call site in source before relying on it — some historical variable names in older deploy notes turn out to have no live effect in the current binary.


Metrics — SOLANA_METRICS_CONFIG

Vexor reports metrics using the standard environment variable and format:

SOLANA_METRICS_CONFIG="host=<url>,db=<database>,u=<user>,p=<password>"

If the variable is unset or fails to parse, the metrics reporter logs that it's disabled and the validator runs normally — there's no metrics-config requirement to vote. For the public testnet metrics write endpoint and credentials, see Anza's cluster documentation rather than copying a value from anywhere else — those are the canonical, current values for the cluster you're joining.


VEX_MODE (planned)

A single VEX_MODE switch is planned to select the validator's role in one step, replacing the current mix of individual flags for the same decision:

Value Role
full (planned default) Vote and produce blocks — today's behavior.
vote Vote only; never produce or broadcast blocks.
rpc Follow the cluster only — no voting, no block production.

This has not shipped yet. It's designed as a thin macro over the existing VEX_LEADER_BROADCAST flag plus one new voting-enable gate, specifically so that full mode remains byte-identical to current behavior. Once it lands, this page will be updated with the shipped specifics; until then, the baked necessity set above reflects the only mode that exists today (full: vote + produce empty, cluster-accepted blocks).


Status

This page reflects the binary's own baked-default table and the source getenv sites that consume each variable, audited directly against source rather than inferred from deploy-script history or variable names. If a flag you're relying on isn't listed here, treat it as unproven for production use until you've confirmed its effect in source. See Deploying Vexor for the ordered contract these variables are consumed by, and Building Vexor for the -D build flags a handful of them arm at runtime.