Skip to main content

Run the project (macOS)

This guide gets you to a running node on macOS. Track 1 (Docker Compose) is the recommended path; Track 2 (bare metal) is documented at the bottom for advanced setups.

Prerequisites

Verify both are present:
docker --version
docker compose version
Use the docker compose form (with a space). The legacy hyphenated docker-compose is the deprecated Python script and is not supported.

Three-step quickstart

git clone https://github.com/kynesyslabs/node.git && cd node
cp .env.example .env
docker compose up
The first run pulls images and builds the node container, which can take a few minutes. Subsequent starts are near-instant. When the stack is healthy:
  • Node RPC: http://localhost:53550 — try curl http://localhost:53550/info
  • Grafana: http://localhost:3000 (default admin / demos)
  • Prometheus: http://localhost:9091

Tour of .env

.env.example is the canonical template. The defaults work for local development. The variables you are most likely to touch:
VariableDefaultNotes
CONSENSUS_TIME10Block production interval (seconds).
RPC_FEE1Per-tx fee component. Total flat fee = RPC_FEE + NETWORK_FEE + BURN_FEE (default 1+1+1=3).
NETWORK_FEE1Per-tx fee component.
BURN_FEE1Per-tx fee component.
RPC_PORT53550Host-mapped RPC port. Change if 53550 is taken.
EXPOSED_URLhttp://localhost:53550Public URL advertised to peers. Loopback default is fine for local dev — set it to your reachable address before joining a real network.
OMNI_ENABLED / OMNI_PORTtrue / 53551OmniProtocol binary RPC. Modes via OMNI_MODE: HTTP_ONLY, OMNI_PREFERRED, OMNI_ONLY.
TLSNOTARY_ENABLEDtrueSet to false to skip TLSNotary entirely.
TLSNOTARY_SIGNING_KEY(empty)Leave empty in default docker mode — the sidecar manages its own key. Only set when TLSNOTARY_MODE=ffi.
GRAFANA_ADMIN_PASSWORDdemosChange this.
COMPOSE_PROFILESmonitoring,tlsnotaryWhich compose profiles to bring up (see below).
Leave PG_HOST=postgres and TLSNOTARY_HOST=tlsnotary exactly as shipped — those are the in-network service names used by docker compose.
Old docs referenced RPC_FEE=5 and SERVER_PORT. Both are wrong. The current names are RPC_FEE (default 1, plus NETWORK_FEE=1 and BURN_FEE=1) and RPC_PORT.

Compose profiles

COMPOSE_PROFILES in .env controls the optional services:
ProfileAdds
(none)postgres + node — bare minimum
tlsnotaryTLSNotary sidecar (HTTPS attestation)
monitoringPrometheus + Grafana
fullnode-exporter (host CPU/RAM/disk metrics) — pair with monitoring
neo4jNeo4j (only for CGC/KYC features)
# Default — postgres + node + tlsnotary + monitoring (uses .env)
docker compose up

# Minimal — only postgres + node (also set TLSNOTARY_ENABLED=false in .env)
COMPOSE_PROFILES= docker compose up

# Add host-level metrics
COMPOSE_PROFILES=monitoring,tlsnotary,full docker compose up

Common operations

# Follow logs
docker compose logs -f node

# Update to the latest source
git pull
docker compose up -d --build

# Stop containers, KEEP volumes (your identity, chain data, etc.)
docker compose down

# Stop AND DELETE all volumes — nuclear, destroys identity + state
docker compose down -v
State persists in named Docker volumes prefixed demos_ (e.g. demos_node_state holds .demos_identity, demos_pgdata holds chain data, demos_grafana_data holds dashboards). They survive docker compose down but not docker compose down -v.

Going public

Before joining a real Demos network from a Mac that other peers should reach:
  1. Set EXPOSED_URL in .env to your reachable address — public IP or DNS — not localhost.
  2. Open inbound TCP for 53550 (RPC), 53551 (OmniProtocol), and 7047 (TLSNotary, if enabled) on your router/firewall before advertising the public URL.
  3. Seed demos_peerlist.json with bootstrap peers from the team. Do not invent hostnames; use the values the team publishes.
See INSTALL.md for the full peerlist seeding procedure.

Troubleshooting

SymptomFix
docker compose: command not foundYou have the legacy Python docker-compose. Install the v2 plugin via Docker Desktop or the official guide.
Port 53550 already in useSet RPC_PORT (and EXPOSED_URL) to a free port in .env, then docker compose up -d.
EXPOSED_URL warning at startupExpected for local dev. Set EXPOSED_URL to a routable address before joining a network.
Postgres connection refusedPostgres takes a few seconds to become healthy on first boot. The node waits via depends_on. If it persists, check docker compose logs postgres.

Track 2: Bare metal with ./run (advanced)

Track 2 runs the node binary natively via Bun and uses Docker only for a Postgres sidecar managed by the ./run script. Pick this path for core development, kernel-level debugging, or TUI-driven operation. The macOS-specific quirks (source $HOME/.zshrc instead of .bashrc, Docker Desktop instead of apt-installed Docker) are handled by the upstream install scripts. The full walkthrough — prerequisites, ./scripts/install-deps.sh, identity generation, peerlist setup, and ./run flags — lives in the source of truth: For the bare-metal path, override these in your .env:
  • PG_HOST=localhost
  • PG_PORT=5332
  • TLSNOTARY_HOST=localhost