Running the node
There are two supported ways to run a Demos node:- Track 1 — Docker Compose (recommended). Single-command bring-up of the full stack: node + Postgres + TLSNotary + monitoring. Pick this unless you have a specific reason not to.
- Track 2 — bare metal
./run(advanced). Node binary runs natively on the host via Bun; only Postgres lives in a sidecar container managed by./run. Pick this for core development, kernel-level debugging, or TUI-driven operation.
git clone https://github.com/kynesyslabs/node.git) and the same .env file (cp .env.example .env). They differ only in where the node binary and its dependencies live. For the full install walkthrough see INSTALL.md; for variable-by-variable settings see Node configuration.
Track 1: Docker Compose (recommended)
Prerequisites
- Docker 20.10+
- The
docker composev2 plugin (with a space — the legacy hyphenateddocker-composePython script is not supported) git
Start the node
From the repo root:- Node RPC:
http://localhost:53550(trycurl http://localhost:53550/info) - Grafana:
http://localhost:3000(defaultadmin/demos) - Prometheus:
http://localhost:9091
First boot: identity generation
On the very first start the node entrypoint:- Generates a fresh ed25519 keypair if
.demos_identitydoes not exist in thedemos_node_statevolume. - Writes the private key into the volume at
.demos_identity. - Writes the public key to a
publickey_<timestamp>file alongside it and prints it in the container logs.
docker compose down / up cycles. It is destroyed by docker compose down -v — back it up first (see Backing up and restoring a node).
Common operations
demos_:
The
demos_ prefix is set explicitly in docker-compose.yml, so volume names are stable regardless of the directory you ran compose from.
Compose profiles
COMPOSE_PROFILES in .env controls the optional services. The defaults are tuned for local development.
Going public
Before joining a real Demos network from a machine that other peers should reach:- Set
EXPOSED_URLin.envto your reachable address (public IP or DNS), notlocalhost. - Open inbound TCP for
RPC_PORT(53550),OMNI_PORT(53551), and7047(TLSNotary, if enabled) on your firewall before advertising the public URL. - Seed
demos_peerlist.jsonwith bootstrap peers from the team — see Joining the testnet using a custom genesis.
Track 2: Bare metal ./run (advanced)
In Track 2 the node binary runs natively under Bun, and only Postgres lives in Docker (as a sidecar managed by ./run).
Prerequisites
- Docker (still needed for the Postgres sidecar)
- Bun (via Mise or the direct installer)
-
Rust (required by
./scripts/install-deps.shto buildwstcp) -
A
.envwith the bare-metal overrides:
Start the node
5332), runs the node natively, and opens the TUI. Stopping the node with Ctrl+C (or Q in the TUI) shuts the sidecar down too.
./run at the repo root is a thin wrapper that forwards to scripts/run (the actual implementation). Always invoke ./run from the repo root — never call scripts/run directly. The wrapper exists so the legacy command path keeps working.First boot: identity generation
The very first./run:
- Generates a fresh ed25519 keypair if
.demos_identitydoes not exist. - Writes the private key to
.demos_identityin the repo root. - Writes the public key to
publickey_<timestamp>and prints it on the console.
Ctrl+C (or Q in the TUI) to stop, then edit .env / demos_peerlist.json before restarting. Set tight permissions on the identity file:
./run flags
Examples:
TUI controls
By default./run launches a terminal UI with tabs for Core, Network, Chain, Consensus, and others.
Disable the TUI with
./run -t or ./run --no-tui if you prefer plain log output (useful in tmux, CI, or when piping to a file).
Verify the node is running
In a separate terminal:Stop the node
PressCtrl+C (or Q in the TUI) in the ./run terminal. To stop the Postgres sidecar manually: