Skip to content

Node Management

merobox runs Calimero (merod) nodes for you and gives every node the same set of lifecycle commands regardless of how it is running. There are two backends:

Backend Selected by Implementation Best for
Docker (default) no flag DockerManager (merobox/commands/manager.py) isolated, reproducible multi-node runs; the auth/Traefik stack
Binary --no-docker BinaryManager (merobox/commands/binary_manager.py) running a locally-built merod, embedded auth, lower overhead

Almost every command (run, stop, list, logs) takes --no-docker to target the binary backend; without it they operate on Docker containers.

Terminal window
# One Docker node (name defaults to calimero-node-1)
merobox run
# A cluster of three
merobox run --count 3
# Custom base ports and name prefix
merobox run --count 2 --base-port 2428 --base-rpc-port 2528 --prefix my-node
# A specific image
merobox run --image ghcr.io/calimero-network/merod:prerelease

Each node opens two listeners, matching merod’s own defaults:

Listener Purpose Base port
libp2p swarm peer-to-peer networking 2428 (--base-port)
HTTP server / RPC admin API, JSON-RPC, WebSocket, SSE 2528 (--base-rpc-port)

When you start more than one node, ports are allocated per node starting from the base (or auto-detected free ports if you omit the base flags).

Flag Effect
--count, -c Number of nodes to start (default 1).
--base-port, -p / --base-rpc-port, -r Base swarm / RPC port (auto-detected if unset).
--prefix Node name prefix (default calimero-node).
--image Custom Docker image (Docker mode).
--force-pull Force-pull the image even if present locally (Docker mode).
--log-level RUST_LOG value; default debug. Supports patterns like info,module::path=debug.
--rust-backtrace RUST_BACKTRACE value (default 0).
--no-docker Run merod as a native process (binary mode).
--binary-path Path to the merod binary (binary mode); otherwise PATH and common locations are searched.
--foreground Attach to merod’s interactive UI (binary mode, single node only).
--auth-service Enable the Traefik + auth stack (Docker mode).
--auth-mode embedded or proxy (default proxy).

Once nodes are up, the same commands inspect and tear them down. Add --no-docker to any of these to target binary-mode nodes.

Terminal window
merobox list # running Docker nodes
merobox list --no-docker

In Docker mode each node’s home directory is bind-mounted from the host at ./data/<node-name> to /app/data inside the container (the container sets CALIMERO_HOME=/app/data). That directory holds the node’s identity, datastore, and blob store, so it survives container replacement.

With --no-docker, merobox spawns merod as a native subprocess instead of a container. It writes each node’s files under ./data/<node-name>/, captures stdout/stderr to ./data/<node-name>/logs/<node-name>.log, and tracks the process so stop/list/logs work the same way.

Terminal window
# Single binary node using a locally built merod
merobox run --no-docker --binary-path ./target/release/merod
# Attach to merod's interactive UI (single node only)
merobox run --no-docker --binary-path ./merod --foreground

Two independent auth models, one per backend.

Docker: Traefik + mero-auth stack (--auth-service)

Section titled “Docker: Traefik + mero-auth stack (--auth-service)”

Passing --auth-service (CLI) or auth_service: true (workflow YAML) brings up a reverse-proxy stack alongside the node containers:

  • A Traefik proxy (proxy container) and a mero-auth service (auth container, default image ghcr.io/calimero-network/mero-auth:edge, override with --auth-image).
  • Two Docker networks: calimero_web (external-facing, connects Traefik to the nodes) and calimero_internal (an internal bridge that isolates the auth service).
  • Traefik routes on a single HTTP entrypoint (web, port 80) using per-node nip.io hostnames of the form http://<node>.127.0.0.1.nip.io.

Route protection applied by the proxy:

Routes Protection
/jsonrpc, /admin-api/, /ws, /sse require auth (auth middleware)
/admin-dashboard public
Terminal window
merobox run --auth-service
merobox run --count 2 --auth-service --auth-image ghcr.io/calimero-network/mero-auth:edge
merobox stop --auth-service # tear the stack down

By default the auth and WebUI frontends are fetched fresh (CALIMERO_AUTH_FRONTEND_FETCH / CALIMERO_WEBUI_FETCH); pass --auth-use-cached / --webui-use-cached to use the cached bundles.

Binary: embedded auth (--auth-mode embedded)

Section titled “Binary: embedded auth (--auth-mode embedded)”

In binary mode, --auth-mode embedded runs merod’s own built-in JWT auth on /jsonrpc, /admin-api/, /ws, with the auth service served under /auth/* and credentials persisted in the node home. Workflows can drive this path declaratively with login / refresh / ws_connect steps (see workflow YAML).

Terminal window
merobox run --no-docker --binary-path ./merod --auth-mode embedded

--auth-mode also accepts proxy (the default — no embedded auth). The embedded auth stack is not available with the Docker backend.

merobox does not hand-write a config.toml from scratch. In Docker/binary mode it runs merod init for each node and then applies E2E-oriented adjustments via the helpers in merobox/commands/config_utils.py:

  • apply_bootstrap_nodes — inject bootstrap peer multiaddrs so nodes discover each other.
  • apply_mdns_setting — toggle mDNS local discovery.
  • apply_e2e_defaults — clear inherited public bootstrap nodes and bind for isolated, deterministic test runs.

To reuse an existing configuration instead, point a workflow at a config.toml with a config_path (shared across nodes, or per-node). Supplying a custom config skips merod init for that node. This is not supported with count mode — see workflow YAML.

--log-level sets each node’s RUST_LOG (default debug). It accepts the full tracing filter syntax, so you can scope verbosity to a subsystem:

Terminal window
merobox run --log-level "info,calimero_node::sync=trace"

In a workflow, set log_level: at the top level instead.