# Run a node

Install, configure and start an SCL node, then confirm it is in sync with the rest of the network. You do not need a local Bitcoin node.

> Part of the SQRL documentation, section "Protocol".
> Rendered page: https://docs.sqrl.tech/protocol/nodes/run-a-validator

## Install

* Install Rust and Cargo.
* Clone [scl-node](https://github.com/Dark-Fusion-Protocol/scl-node) and build the release binary with `cargo build --release`. The binary lands at `target/release/scl-node`.
* Keep it alongside a writable data directory for state and logs.

You do **not** need a local Bitcoin node: chain data is read from an [Esplora](https://github.com/Blockstream/electrs) endpoint over HTTP.

## Configure

Configuration comes from a `config.toml` next to the binary, from environment variables, or both; environment variables override the file. All fields have working defaults.

Example `config.toml`:

```toml
node_id = "my-node"
rest_address = "0.0.0.0:8080"        # client-facing REST API
bind_address = "0.0.0.0:50051"       # gRPC: peer sync and gossip
url = "http://my-node.example:50051" # public gRPC URL advertised to peers
peers = ["http://node1.example:50051", "http://node2.example:50051"]
esplora = "https://blockstream.info/api"
db_path = "./data/scl-node"
data_dir = "./data"
peer_limit = 10

# Optional: stable Ed25519 identity for signing gossip (64 hex chars).
# Omit for an ephemeral identity.
gossip_private_key = ""

# Optional: bearer token protecting private endpoints
# (confirmed-call log, admin operations). Omit to leave them locked.
api_token = ""
```

The equivalent environment variables:

| Variable | Default | Purpose |
| --- | --- | --- |
| `SCL_NODE_ID` | `scl-node-1` | Node identifier |
| `SCL_REST_ADDRESS` | `0.0.0.0:8080` | REST API bind |
| `SCL_BIND_ADDRESS` | `0.0.0.0:50051` | gRPC bind |
| `SCL_PUBLIC_URL` | `http://localhost:50051` | Public gRPC URL advertised to peers |
| `SCL_PEERS` | empty | Comma-separated peer gRPC URLs |
| `SCL_PEER_LIMIT` | `10` | Max peers for gossip forwarding |
| `SCL_ESPLORA_URL` | `https://blockstream.info/api` | Esplora API base (set a testnet URL for testnet) |
| `SCL_DB_PATH` | `data/scl-node` | Database path |
| `SCL_GOSSIP_PRIVATE_KEY` | empty | Ed25519 seed for a stable gossip identity |
| `SCL_API_TOKEN` | empty | Bearer token for private endpoints |
| `RUST_LOG` | `info` | Log filter |

## Start

```bash
./scl-node
```

There are no subcommands; configuration fully determines behavior. A `docker-compose.yml` in the repository runs a single node with persistent data if you prefer containers.

On startup your node:

* Initializes local storage.
* Fetches the current Bitcoin height from Esplora and anchors its block journal.
* Reloads the contract registry.
* Syncs with peers using Merkle-based diffing.
* Then serves requests, gossips payloads, and watches Bitcoin for new blocks (checking every 60 seconds, with a full peer sync every 5 minutes).

Health check:

```bash
curl -i http://localhost:8080/health
# Expect: HTTP/1.1 200 OK

curl http://localhost:8080/node_status
```

## Verify you're in sync

Compare state roots with another node; matching roots at the same height prove matching state:

```bash
curl http://localhost:8080/v2/state_root
```

For the full REST and gRPC surface, see the [Node API reference](/protocol/nodes/api-reference). Treat the REST surface as current implementation, not a stable public API.

## Validator seats

Anyone can run a node and replay the network. Validator seats on the canonical ledger, which co-sign state roots and earn from the emission pool, are accredited: they are admitted by governance and carry obligations to replay, publish state roots and operate network infrastructure. See [Validators and the canonical ledger](/protocol/network/validators) and [XRB and network economics](/protocol/network/economics).
