Skip to main content
Tessellation supports two approaches for running nodes: Docker-based (recommended for most users) and SBT-based (for building and running JARs directly). The Docker approach handles environment setup, peer joining, and health checks automatically.

Prerequisites

Java 21

Required at runtime. Enforced at build time — Kryo serialization depends on Java 21 reflection.

SBT

Required to compile and assemble JARs from source.

Docker

Required for the Docker-based approach and the just test environment.

Node types

Tessellation runs four distinct node types in a hierarchical consensus model:
NodeModuleDefault portsRole
Global L0 (gl0)dag-l09000 / 9001 / 9002Global consensus — aggregates all metagraph state channels into global snapshots
DAG L1 (gl1)dag-l19010 / 9011 / 9012Metagraph block creation; sends L1 blocks to Global L0
Currency L0 (ml0)currency-l09020 / 9021 / 9022Currency metagraph L0; aggregates Currency L1 blocks into currency snapshots
Currency L1 (cl1 / dl1)currency-l19030+ / 9031+ / 9032+Currency metagraph L1; handles end-user transactions
Each node exposes three ports: public (HTTP API), p2p (peer-to-peer), and cli (cluster management).
1

Install just

Install the just command runner. On macOS: brew install just. On Linux: see casey/just.
2

Configure your keystore

Each node requires a PKCS12 keystore (key.p12). Generate one using the keytool CLI:
java -jar keytool.jar generate \
  --keystore ./key.p12 \
  --alias alias \
  --password yourpassword
Place the keystore at ./key.p12 (the default mount path) or set CL_KEYSTORE_MOUNT_PATH to a different path.
3

Start the environment

just up
This calls docker/bin/compose-runner.sh --up and starts the configured node containers. To use pre-built JARs from a specific release instead of compiling from source:
just up --hypergraph-release=v3.5.11
4

Verify node health

Each node exposes a health endpoint on its public port:
# Global L0 (port 9000)
curl http://localhost:9000/node/health

# DAG L1 (port 9010)
curl http://localhost:9010/node/health

# Metagraph L0 (port 9020)
curl http://localhost:9020/node/health
A healthy node returns HTTP 200.
5

Run the test suite

just test                  # Full test suite: compile + docker + all E2E tests
just test --skip-assembly  # Skip JAR compilation, reuse existing JARs
Available test scenarios:
just test --list-tests     # List all available test scenarios

# DAG tests (no metagraph required)
just test --test=dag-cluster
just test --test=delegated-staking
just test --test=token-lock-replacement
just test --test=snapshot-streaming

# Metagraph tests (require --use-test-metagraph)
just test --test=currency
just test --test=rewards
just test --test=token-locks
just test --test=allow-spends
6

Stop the environment

just down

SBT-based approach

Build JARs from source and run them directly with java -jar.
1

Compile and assemble JARs

sbt compile          # Compile all modules
sbt dagL0/assembly   # Assemble Global L0 JAR
sbt dagL1/assembly   # Assemble DAG L1 JAR
JARs are written to each module’s target/scala-2.13/ directory.
2

Set environment variables

Each node reads configuration from environment variables:
export CL_KEYSTORE=/path/to/key.p12
export CL_PASSWORD=yourpassword
export CL_PUBLIC_HTTP_PORT=9000
export CL_P2P_HTTP_PORT=9001
export CL_CLI_HTTP_PORT=9002
export CL_EXTERNAL_IP=<your-public-ip>
export CL_COLLATERAL=0
3

Add Java 21 module flags

Kryo serialization requires additional JVM flags for Java 21 module access:
export JAVA_OPTS="\
  --add-opens=java.base/java.lang.invoke=ALL-UNNAMED \
  --add-opens=java.base/java.util=ALL-UNNAMED \
  --add-opens=java.base/java.security=ALL-UNNAMED"
4

Run the node

java $JAVA_OPTS \
  -jar modules/dag-l0/target/scala-2.13/dag-l0-assembly-*.jar \
  run-validator

Environment variables reference

VariableDefaultDescription
CL_KEYSTOREPath to PKCS12 keystore inside the container
CL_PASSWORDKeystore password (sets both store and key password)
CL_PUBLIC_HTTP_PORT9000Public HTTP API port
CL_P2P_HTTP_PORT9001Peer-to-peer HTTP port
CL_CLI_HTTP_PORT9002CLI/cluster management port
CL_EXTERNAL_IPAuto-detectedPublic IP announced to peers
CL_COLLATERALNode collateral amount
CL_L0_PEER_HTTP_HOSTgl0Hostname of the L0 peer to connect to
CL_L0_PEER_HTTP_PORT9000Port of the L0 peer
CL_L0_PEER_IDNode ID of the L0 peer
CL_DOCKER_GENESISfalseBoot in genesis mode
CL_DOCKER_ROLLBACKfalseRollback to a previous snapshot hash
CL_DOCKER_ROLLBACK_HASHHash of the snapshot to roll back to

Health check endpoints

GET /node/health          # Liveness: returns 200 when the process is up
GET /node/info            # Node metadata: version, cluster ID, state
GET /cluster/info         # Current cluster peers
The Docker healthcheck runs internal-health-check.sh which calls GET /node/health on the node’s configured public port.

Build docs developers (and LLMs) love