Skip to main content

Node configuration

A Demos node is configured almost entirely from a single .env file. The repo ships .env.example as the canonical template:
cp .env.example .env
# edit .env to override anything you need
The defaults are tuned for the Track 1 (Docker Compose, recommended) flow. If you are running Track 2 (bare metal ./run, advanced), two settings differ — see Track-specific overrides below.
Old docs referenced RPC_FEE=5 and SERVER_PORT. Both are wrong. The current names are RPC_PORT for the listen port and RPC_FEE (default 1, paired with NETWORK_FEE=1 and BURN_FEE=1 for a per-tx total of 3).

Track-specific overrides

VariableTrack 1 (Docker Compose)Track 2 (bare metal ./run)
PG_HOSTpostgres (in-network service name)localhost
PG_PORT5432 (container-internal)5332 (host-mapped from the sidecar)
TLSNOTARY_HOSTtlsnotary (in-network service name)localhost
Everything else in .env is shared between the two tracks.

Consensus and governance

VariableDefaultNotes
CONSENSUS_TIME10Block production interval in seconds. Lower = faster blocks, higher CPU.
RPC_FEE1Per-tx fee component.
NETWORK_FEE1Per-tx fee component.
BURN_FEE1Per-tx fee component (burned). Total per-tx flat fee = RPC_FEE + NETWORK_FEE + BURN_FEE.
MIN_VALIDATOR_STAKE1000000000000000000Minimum stake to become a validator (raw bigint as string, must fit Postgres int64 ≤ 9.2e18).
These values are the chain’s bootstrap defaults at genesis. Governance proposals can override them at runtime — see Network Governance.

Network and ports

VariableDefaultNotes
RPC_PORT53550Main HTTP RPC listen port.
EXPOSED_URLhttp://localhost:53550Public URL advertised to peers and SDK clients. Loopback default is fine for local dev — set to your reachable address before joining a real network.
OMNI_ENABLEDtrueToggle the OmniProtocol binary RPC server.
OMNI_PORT53551OmniProtocol TCP server port (auto-derived as RPC_PORT + 1 if unset).
OMNI_MODEOMNI_PREFERREDOne of HTTP_ONLY, OMNI_PREFERRED, OMNI_ONLY.
RPC_SIGNALING_PORT3005WebRTC signaling server port (peer discovery handshake for legacy MessagingPeer).
RPC_MCP_PORT3001MCP (Model Context Protocol) server port for AI agent integrations.
If you set EXPOSED_URL to a public IP or DNS name, also open inbound TCP for RPC_PORT (53550), OMNI_PORT (53551), and 7047 (TLSNotary, if enabled) on your firewall before peers start trying to reach you. Do not expose 5432 / 5332 (Postgres), 9090 (node metrics), 9091 (Prometheus), or 3000 (Grafana) to the public internet.

Database (PostgreSQL)

VariableDefaultNotes
PG_HOSTpostgresTrack 1: in-network service name. Track 2: set to localhost.
PG_PORT5432Track 1: container-internal. Track 2: set to 5332 (the host-mapped port the ./run sidecar uses).
PG_USERdemosuser
PG_PASSWORDdemospasswordChange before sharing the host.
PG_DATABASEdemos
See Browsing the Postgres DB via psql for connection commands per track.

Identity and peers

VariableDefaultNotes
IDENTITY_FILE.demos_identityPath to the node’s ed25519 identity keypair. Auto-generated on first boot. Under Track 1 the entrypoint persists this into demos_node_state so it survives container recreation.
PEER_LIST_FILEdemos_peerlist.jsonCached peer list. Same persistence treatment as the identity file.
See Backing up and restoring a node.demos_identity is the single most important file to back up.

TLSNotary

TLSNotary provides cryptographic attestation of HTTPS responses.
VariableDefaultNotes
TLSNOTARY_ENABLEDtrueSet to false to skip TLSNotary entirely.
TLSNOTARY_HOSTtlsnotaryTrack 1: in-network service name. Track 2: set to localhost.
TLSNOTARY_PORT7047Attestation server port.
TLSNOTARY_MODEdockerdocker (sidecar container) or ffi (in-process Rust binding).
TLSNOTARY_FATALfalseIf true, TLSNotary failures crash the node. Keep false for graceful degradation.
TLSNOTARY_SIGNING_KEY(empty)Leave empty in default Docker mode — the sidecar manages its own key. Only set when TLSNOTARY_MODE=ffi (64-char hex secp256k1 key, or empty to auto-generate into .tlsnotary-key).
Under Track 1, keep TLSNOTARY_ENABLED aligned with the tlsnotary profile in COMPOSE_PROFILES — enabling one without the other produces noisy warnings.

Monitoring

VariableDefaultNotes
METRICS_ENABLEDtrueExposes Prometheus metrics at http://<node>:<METRICS_PORT>/metrics.
METRICS_PORT9090Container-internal port. Pinned to 9090 in compose to match the static scrape target in monitoring/prometheus/prometheus.yml. Override only on bare metal.
METRICS_HOST0.0.0.0Bind address.
METRICS_HOST_PORT9090Host-mapped port for the metrics endpoint (Track 1 only). Set this if 9090 is already taken on the host.
GRAFANA_PORT3000Dashboard UI port.
GRAFANA_ADMIN_USERadmin
GRAFANA_ADMIN_PASSWORDdemosChange this before opening Grafana to anything outside your machine.
PROMETHEUS_PORT9091Prometheus server external (host-mapped) port. Internal stays 9090.

Logging and runtime

VariableDefaultNotes
LOG_LEVELinfoOne of debug, info, warning, error, critical. debug produces a wall of per-block consensus JSON — only enable when actually debugging.
PRODfalseSet true in production (enables DTR production relay and prod-only safety checks).
L2PS_ZK_ENABLEDfalseAdvanced: enable ZK proofs in the L2PS layer. Experimental.

Docker Compose only

These variables are consumed by docker-compose.yml and not by the node binary itself, so they only matter on Track 1.
VariableDefaultNotes
COMPOSE_PROFILESmonitoring,tlsnotaryComma-separated list of profiles to bring up. Empty = bare minimum (postgres + node). Other profiles: full (adds node-exporter for host metrics), neo4j (only for CGC/KYC features).
IMAGE_NAMEdemos-nodeImage name. Override to pull a pre-built image (e.g. ghcr.io/kynesyslabs/node).
IMAGE_TAGlocalImage tag.

Optional external API keys

.env.example ships with these commented out. Uncomment only the ones you need; each unlocks a specific feature:
VariableUsed by
SOLANA_RPCSolana RPC endpoint override (default: public mainnet RPC)
ETHERSCAN_API_KEYEVM block explorer queries
HELIUS_API_KEYSolana enhanced RPC (NFTs, DAS API)
NOMIS_API_KEY / NOMIS_CLIENT_IDOn-chain reputation scoring
RAPID_API_KEYVarious enrichment routes
GITHUB_TOKENGitHub-based identity attestations
DISCORD_BOT_TOKENDiscord-based identity attestations
HUMAN_PASSPORT_API_KEYSybil resistance scoring (Gitcoin Passport)

Generating your identity

You do not configure the node’s keypair manually. On first boot the node:
  1. Generates a fresh ed25519 keypair.
  2. Writes the private key to IDENTITY_FILE (default .demos_identity).
  3. Writes the public key to a file named publickey_<timestamp> in the same directory and prints it to the console.
For the exact first-boot procedure on each track, see Running the node.

Configuring the peerlist

demos_peerlist.json lists known peers as { "<publicKey>": "<url>" }. Copy the example and edit it:
cp demos_peerlist.json.example demos_peerlist.json
{
  "0xd0b2be2cb6d...": "https://node2.example.network"
}
For solo / local dev, the file can stay empty (or contain only your own entry). To join an existing network, seed it with at least one known bootstrap peer — see Joining the testnet using a custom genesis for the full procedure.