> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plasma.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Non-Validator Node Setup

> Complete guide for setting up and running non-validator nodes with Docker Compose.

Non-validator nodes provide RPC access to the Plasma network by monitoring consensus clients and serving application requests. This guide covers deployment using the official [non-validator-templates](https://github.com/PlasmaLaboratories/non-validator-templates) repository.

## Prerequisites

<Check>Basic Linux administration skills</Check>
<Check>Docker and Docker Compose installed</Check>
<Check>A server that meets the [hardware requirements](./hardware-requirements)</Check>

## Available Networks

| Network | Chain ID | Consensus Version | Execution Version |
| ------- | -------- | ----------------- | ----------------- |
| mainnet | 9745     | 0.15.0            | Reth v1.8.3       |
| testnet | 9746     | 0.15.0            | Reth v1.8.3       |
| devnet  | 9747     | 0.15.0            | Reth v1.8.3       |

All networks use the public `plasma-consensus-public` image — no GHCR authentication is required.

## Quickstart

<Steps>
  <Step title="Install Docker">
    Connect to your server and ensure that **Docker** and **Docker Compose** are installed.
  </Step>

  <Step title="Clone the templates repository">
    ```bash theme={null}
    git clone https://github.com/PlasmaLaboratories/non-validator-templates.git
    cd non-validator-templates
    ```
  </Step>

  <Step title="Start your node">
    Replace `{network}` with `mainnet`, `testnet`, or `devnet`:

    ```bash theme={null}
    cd {network}/docker-compose
    docker compose up -d
    ```
  </Step>

  <Step title="Verify containers are running">
    ```bash theme={null}
    docker compose ps
    docker compose logs -f plasma-consensus
    ```
  </Step>

  <Step title="Start monitoring (optional)">
    ```bash theme={null}
    docker compose -f monitoring.yml up -d
    ```
  </Step>
</Steps>

## Architecture Overview

Your non-validator node consists of two main components:

<CardGroup cols={2}>
  <Card title="Plasma Execution Client" icon="microchip">
    Based on [Reth](https://github.com/paradigmxyz/reth). Handles transaction execution, state management, and provides JSON-RPC endpoints for applications.
  </Card>

  <Card title="Plasma Observer Client" icon="satellite-dish">
    A lightweight client that monitors the Plasma consensus network without participating in block production or validation.
  </Card>
</CardGroup>

The Docker Compose setup orchestrates these components along with initialisation containers that handle JWT secret generation, key generation, and database setup automatically.

### Directory Structure

Each network directory follows the same layout:

```
{network}/
├── docker-compose/
│   ├── docker-compose.yml        # Service definitions
│   ├── .env                      # Image versions and tags (source of truth)
│   ├── non-validator.toml        # Consensus configuration
│   ├── enodes.txt                # Execution bootstrap nodes
│   ├── monitoring.yml            # Monitoring stack
│   └── monitoring/               # Prometheus & Grafana configs
└── shared/                       # Validator keys & identities (read-only)
    ├── keys/                     # BLS12-381 validator public keys
    └── identities/               # Validator identity files
```

## Setup Process Explained

The Docker Compose file defines four services that run in sequence:

<Steps>
  <Step title="OpenSSL Initialisation">
    Generates the JWT secret for secure Engine API communication and creates secp256k1 keys for your node's network identity. These are only generated once and persist across restarts.
  </Step>

  <Step title="Consensus Database Initialisation">
    Initialises the consensus database with the genesis configuration for your chosen network and generates a peer ID for your node.
  </Step>

  <Step title="Execution Database Initialisation">
    Initialises the Reth execution database with the genesis state.
  </Step>

  <Step title="Container Deployment">
    Once initialisation completes, the execution and consensus clients start. **Execution Client (Reth)** starts first and exposes the JSON-RPC API and Engine API. **Consensus Observer Client** starts after the execution client is healthy and connects to the consensus network.
  </Step>
</Steps>

## Configuration

All version numbers and image tags are defined in each network's `.env` file — this is the single source of truth for software versions. The consensus client is configured via `non-validator.toml`.

<Accordion title="Consensus Configuration Reference (non-validator.toml)">
  | Section                       | Fields                                                                                       | Description                       |
  | ----------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------- |
  | *(top-level)*                 | `engine_api_url`, `consensus_api_host`, `authrpc_jwtsecret`                                  | Execution engine connection       |
  | `[persistence]`               | `data_dir`                                                                                   | Consensus data storage path       |
  | `[network]`                   | `p2p_port`, `interval`, `timeout`, `identity_file_path`, `trusted_only`, `discovery.enabled` | P2P networking and peer discovery |
  | `[api]`                       | `enabled`, `host`, `port`                                                                    | Consensus API endpoint            |
  | `[validators.*]`              | `validator_keystore_pk_file_path`, `identity_file_path`                                      | Validator committee               |
  | `[network.bootstrap_nodes.*]` | `api_host`, `p2p_port`, `peer_id`                                                            | Consensus bootstrap peers         |
</Accordion>

### NAT / External Address

For nodes behind NAT, configure an external address so that peers can discover and connect to your node:

<CodeGroup>
  ```toml non-validator.toml theme={null}
  [network]
  external_address = "node.example.com:34070"
  ```

  ```bash CLI theme={null}
  --p2p.external-address node.example.com:34070
  ```
</CodeGroup>

### Port Configuration

| Port    | Service        | Protocol | Description                   |
| ------- | -------------- | -------- | ----------------------------- |
| `8545`  | Execution RPC  | HTTP     | JSON-RPC API endpoint         |
| `8551`  | Execution Auth | HTTP     | Engine API (internal)         |
| `30303` | Execution P2P  | TCP/UDP  | Peer-to-peer networking       |
| `34070` | Consensus P2P  | TCP      | Consensus networking          |
| `35070` | Consensus API  | HTTP     | Consensus health/API endpoint |
| `9001`  | Metrics        | HTTP     | Prometheus metrics            |

<Warning>
  **Firewall requirements**: Ensure inbound/outbound on port `30303` (TCP/UDP) for execution P2P, inbound on port `34070` (TCP) for consensus P2P, and internal communication on port `8551` for the Engine API. The JSON-RPC interface on port `8545` is exposed by default — consider restricting access in production.
</Warning>

## Common Operations

```bash theme={null}
cd {network}/docker-compose

docker compose up -d                              # Start
docker compose -f monitoring.yml up -d            # Start monitoring
docker compose logs -f                            # Logs
docker compose down                               # Stop
docker compose -f monitoring.yml down             # Stop monitoring
docker compose down -v && docker compose up -d    # Clean restart
```

## Monitoring Your Node

Once your node is operational, you can monitor its health and synchronisation status. For comprehensive monitoring setup and best practices, see the [monitoring guide](../maintenance/monitoring).

<Tabs>
  <Tab title="Status Checks">
    ```bash theme={null}
    # Check container status
    docker compose ps

    # View execution client logs
    docker compose logs -f plasma-execution

    # View consensus observer client logs
    docker compose logs -f plasma-consensus
    ```
  </Tab>

  <Tab title="Sync Status">
    ```bash theme={null}
    # Check execution client sync status
    curl -s -X POST -H "Content-Type: application/json" \
      --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' \
      http://localhost:8545
    ```
  </Tab>

  <Tab title="Endpoints">
    | Endpoint      | URL                             |
    | ------------- | ------------------------------- |
    | Execution RPC | `http://localhost:8545`         |
    | Consensus API | `http://localhost:35070`        |
    | Metrics       | `http://localhost:9001/metrics` |
  </Tab>
</Tabs>

Your node will begin synchronising immediately. Initial sync may take several minutes depending on network conditions and your hardware specifications.

## Database Snapshots

Plasma publishes daily database snapshots for **mainnet** and **testnet**. Snapshots let you bootstrap a new node in hours instead of syncing from genesis, which can take significantly longer.

Each snapshot contains two files — the consensus-layer database and the execution-layer database — uploaded to a requester-pays S3 bucket. You need an AWS account; standard S3 data-transfer rates apply.

### Snapshot Prerequisites

| Requirement | Details                                                             |
| ----------- | ------------------------------------------------------------------- |
| AWS account | Credentials configured via `aws configure` or environment variables |
| AWS CLI     | v2 recommended (`aws --version`)                                    |
| Disk space  | **Mainnet:** \~400 GB free • **Testnet:** \~100 GB free             |

<Info>
  Data transfer out from `us-east-2` is \~\$0.09/GB for the first 10 TB/month. Transferring from an EC2 instance **in the same region** is free — running your node in `us-east-2` is the most cost-effective option.
</Info>

### Snapshot Buckets

| Property           | Mainnet                                       | Testnet                     |
| ------------------ | --------------------------------------------- | --------------------------- |
| **Bucket**         | `plasma-mainnet-db-backups`                   | `plasma-testnet-db-backups` |
| **Region**         | `us-east-2` (Ohio)                            | `us-east-2` (Ohio)          |
| **Access model**   | Requester-pays                                | Requester-pays              |
| **Backup cadence** | Daily                                         | Daily at 02:00 UTC          |
| **Retention**      | Rolling (older backups removed automatically) | 3 days                      |

Backups are organized into date-stamped folders (`MM-DD-YY`). Each folder contains two files:

| File                                                         | Description                                         |
| ------------------------------------------------------------ | --------------------------------------------------- |
| **Consensus database** (`.db` on mainnet, `.mdb` on testnet) | Full consensus-layer state                          |
| **Execution database** (`.tar.gz`)                           | Tar archive of the Reth execution `data/` directory |

### Download a Snapshot

```bash theme={null}
# Set your target network's bucket
BUCKET="plasma-mainnet-db-backups"   # or "plasma-testnet-db-backups"

# List available snapshots
aws s3 ls "s3://${BUCKET}/" \
  --region us-east-2 \
  --request-payer requester

# Download the most recent snapshot
DATE="MM-DD-YY"   # replace with the latest date folder (e.g. 03-23-26)

aws s3 cp \
  "s3://${BUCKET}/${DATE}/" \
  ./backups/ \
  --recursive \
  --region us-east-2 \
  --request-payer requester
```

### Restore from Snapshot

<Steps>
  <Step title="Stop your node">
    ```bash theme={null}
    cd {network}/docker-compose
    docker compose down
    ```
  </Step>

  <Step title="Restore the consensus database">
    Copy the snapshot into the consensus data directory:

    ```bash theme={null}
    # Mainnet (.db)
    cp backups/consensus-backup-*.db /path/to/plasma-data-dir/

    # Testnet (.mdb)
    cp backups/consensus-backup-*.mdb /path/to/plasma-data-dir/
    ```
  </Step>

  <Step title="Restore the execution database">
    Extract the archive into the execution data directory:

    ```bash theme={null}
    tar -xzf backups/execution-backup-*.tar.gz -C /path/to/execution-data-dir/
    ```
  </Step>

  <Step title="Restart your node">
    ```bash theme={null}
    docker compose up -d
    ```
  </Step>
</Steps>

### Snapshot Troubleshooting

| Issue                | Cause / Fix                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `Access Denied`      | You must include `--request-payer requester` on every command. The bucket rejects requests without it.                         |
| `403 Forbidden`      | AWS credentials not configured. Run `aws sts get-caller-identity` to verify you have a valid session.                          |
| Empty bucket listing | Older backups are automatically cleaned up. If the bucket appears empty, a backup cycle may be in progress — check back later. |
| Wrong file extension | Mainnet uses `.db`; testnet uses `.mdb`. Ensure you copy the correct file for your network.                                    |
