Environment variables
audience: both
Variables that every binary respects, plus role-specific ones. All
are optional unless marked Required. Values are passed either as
an env var or as the corresponding CLI flag; env beats flag when both
are set (per clap(env = "...")).
Users do not read this page — the SDK takes no env vars. This is an operator reference. When it diverges from what a binary currently parses, the binary is lagging the documented deployment model; align the binary to this page, not the other way around.
Common to every binary
| Variable | CLI flag | Default | Description |
|---|---|---|---|
ZIPNET_INSTANCE | --instance | Required | Instance name for this deployment (e.g. acme.mainnet). Folds into committee GroupId, submit StreamId, broadcasts StoreId. All processes of one deployment must share this value. |
ZIPNET_UNIVERSE | --universe | zipnet::UNIVERSE (mosaik.universe) | Override the shared mosaik universe NetworkId. Set only for isolated federations; leave unset for normal deployments. |
ZIPNET_BOOTSTRAP | --bootstrap | (none) | Comma- or repeat-flag-separated PeerIds on the shared universe to dial on startup. Universe-level, not per-instance. |
ZIPNET_METRICS | --metrics | (none) | Prometheus exporter bind address, e.g. 0.0.0.0:9100. |
ZIPNET_SECRET | --secret | (random) | Seed for this node’s iroh secret. Anything not 64-hex is blake3-hashed. Recommended on committee servers and the aggregator for stable PeerId. |
RUST_LOG | — | info,zipnet_node=debug | Standard tracing_subscriber filter. |
zipnet-server
| Variable | CLI flag | Default | Description |
|---|---|---|---|
ZIPNET_COMMITTEE_SECRET | --committee-secret | Required | Shared committee admission secret. Treated as a root credential — all committee servers of the same instance must share this value; clients and the aggregator must not have it. |
ZIPNET_MIN_PARTICIPANTS | --min-participants | 1 | Minimum registered clients before the leader opens a round. |
ZIPNET_ROUND_PERIOD | --round-period | 2s | How often the leader attempts to open a new round. |
ZIPNET_ROUND_DEADLINE | --round-deadline | 6s | How long a round may stay open before the leader force-advances. |
zipnet-aggregator
| Variable | CLI flag | Default | Description |
|---|---|---|---|
ZIPNET_FOLD_DEADLINE | --fold-deadline | 2s | Time window after a round opens in which the aggregator accepts envelopes. |
zipnet-client
| Variable | CLI flag | Default | Description |
|---|---|---|---|
ZIPNET_MESSAGE | --message | (none) | UTF-8 message to seal each round. Omit to run as cover traffic. |
ZIPNET_CADENCE | --cadence | 1 | Talk every Nth round (1 = every round). |
Duration syntax
The duration parsers accept Nms, Ns, Nm (e.g. 500ms, 2s,
1m). Hours / days are not supported; if you need them, file an
issue.
Secret syntax
All “secret” style inputs (ZIPNET_SECRET, ZIPNET_COMMITTEE_SECRET)
follow the same rule:
- Exactly 64 hex characters → decoded as 32 raw bytes.
- Anything else → blake3-hashed into 32 bytes.
This matches mosaik’s own secret-key handling, so operators can reuse
whatever seed format they already have (e.g. openssl rand -hex 32).
Deployment derivation
Every deployment-local ID descends from a content + intent addressed
root computed from the operator’s ZIPNET_INSTANCE plus the rest of
the fingerprint (shuffle window, init salt, datum schema). The
consumer side computes the same hash from its compiled-in Config
and ShuffleDatum impl:
DEPLOYMENT = blake3("zipnet|" + name + "|type=" + TYPE_TAG +
"|size=" + WIRE_SIZE + "|window=" + window +
"|init=" + init) // UniqueId
SUBMIT = DEPLOYMENT.derive("submit") // StreamId
BROADCASTS = DEPLOYMENT.derive("broadcasts") // StoreId
COMMITTEE = DEPLOYMENT.derive("committee") // GroupKey material
...
A typo in any fingerprint field on either side lands on a GroupId
nobody serves. The failure mode is Error::ConnectTimeout on the
client, not a distinct “not found” error — zipnet has no on-network
registry.
Two deployments with different ZIPNET_INSTANCE values on the same
universe are completely independent committees: disjoint
GroupIds, disjoint streams, no crosstalk. Useful for:
- running dev/staging/prod in one machine pool,
- running per-tenant deployments on shared hardware,
- running a public testnet (
preview.alpha) alongside production (mainnet).
Instance names share a flat namespace per universe — two operators
picking the same name collide in the committee group and neither
works correctly. Namespace defensively
(<org>.<purpose>.<env>, e.g. acme.mixer.mainnet).
Universe override (ZIPNET_UNIVERSE)
Default is the shared mosaik universe (zipnet::UNIVERSE = unique_id!("mosaik.universe")). Override only when running an
isolated federation that intentionally does not share peers with the
rest of the mosaik ecosystem. Every server, aggregator, and client
of one deployment must agree on this value; consumers of the SDK
build against zipnet::UNIVERSE unless their code explicitly passes
a different NetworkId to Network::new.