# Node Setup

Running a validator means operating a full node that participates in consensus, validates transactions, and runs submission audits. This guide walks through identity generation, staking, configuration, and starting the node.
**Prerequisites:** - A dedicated machine (bare metal or cloud VM) with a public IP or DNS hostname
- Stable network access
- SOMA CLI [installed and configured](https://docs.soma.org/getting-started/install/)

## Hardware Requirements

Validators handle consensus, data validation, and model weight storage. Underprovisioned machines will fall behind on sync and miss proposals.

| Component | Minimum | Recommended |
|-----------|---------|-------------|
| CPU | 14 cores | 16+ cores |
| RAM | 14 GB | 32+ GB |
| Storage | 250 GB NVMe SSD | 500 GB+ NVMe SSD |
| Network | 1 Gbps | 10 Gbps |

**OS**: Linux (Ubuntu 22.04+ recommended).

If you haven't installed SOMA yet, follow the [installation guide](https://docs.soma.org/getting-started/install/).

## Generate Validator Info

Before configuring anything, generate your validator identity. This creates the key files and metadata needed for both the node config and committee registration.

1. Run the following command, replacing `<hostname>` with your machine's public hostname and `<commission_rate>` with your desired rate in basis points (`200` = 2%):

    ```
    soma validator make-validator-info <hostname> <commission_rate>
    ```

    This creates the following files in the current directory:

    | File | Description |
    |------|-------------|
    | `protocol.key` | Protocol signing keypair |
    | `account.key` | Account keypair |
    | `network.key` | Network communication keypair |
    | `worker.key` | Worker keypair |
    | `validator.info` | Signed validator metadata (used later with `join-committee`) |

2. Back up all key files immediately.
**Caution:** Loss of validator keys means permanent loss of validator access. Store copies in a secure, offline location. There is no recovery mechanism.

## Start the Scoring Server

Validators audit submissions by scoring data against model weights on a GPU. If the validator machine has a GPU, set `scoring_device: cuda` in the config and the validator handles scoring internally, no separate process needed. If the GPU lives on a different machine, run a standalone scoring server there and point the validator to it via `scoring_url`.

### GPU requirements

Scoring loads full model weights into GPU memory. You need a dedicated GPU with **at least 24 GB of VRAM** (e.g. RTX 3090, RTX 4090, A10G, L4, A100).
**Caution:** The default device is `wgpu`, which runs on the CPU. This works but is **extremely slow** for audits. Expect scoring to take orders of magnitude longer than on a GPU. For any production validator, use `cuda`.

### Remote scoring server (optional)

If the GPU is on a **separate machine** from the validator, start a standalone scoring server on that machine:

```
soma start scoring --device cuda
```

This binds to `0.0.0.0:9124` by default. Common options:

```
soma start scoring --device cuda --port 9124 --data-dir /data/scoring
```

Make sure port `9124` is reachable from the validator host. You'll point the validator to it via `scoring_url` in the config below.

## Configure the Node

A validator node is started from a YAML config file that tells it where to find keys, genesis state, and data directories.

1. **Download the genesis blob** for the network you're joining. For testnet:

    ```
    curl -fsSL -o genesis.blob https://github.com/soma-org/genesis/raw/refs/heads/main/testnet/genesis.blob
    ```

2. **Create your `validator.yaml`** referencing the key files from the generate step, the genesis blob, and your node's addresses. Here is a minimal example. Replace `validator.example.com` with your hostname and adjust paths as needed:

    ```yaml
    # Keys (from make-validator-info)
    protocol_key_pair:
      path: ./protocol.key
    worker_key_pair:
      path: ./worker.key
    account_key_pair:
      path: ./account.key
    network_key_pair:
      path: ./network.key

    # Genesis
    genesis:
      genesis-file-location: ./genesis.blob

    # Data directories (persistent storage)
    db_path: /data/authorities_db
    consensus_db_path: /data/consensus_db

    # Network addresses
    network_address: "/dns/validator.example.com/tcp/8080/http"
    consensus_config:
      address: "/dns/validator.example.com/tcp/8081/http"
      db-path: /data/consensus_db
    p2p_config:
      listen_address: "0.0.0.0:8084"
      external_address: "/dns/validator.example.com/tcp/8084/http"
      seed_peers:
        - address: "/dns/validator-0.testnet.soma.org/tcp/8084/http"

    rpc_address: "0.0.0.0:9000"

    # Scoring - GPU on this machine:
    scoring_device: cuda
    # Or, point to a remote scoring server instead:
    # scoring_url: "http://gpu-host:9124"

    authority_store_pruning_config:
      num-latest-epoch-dbs-to-retain: 3
      epoch-db-pruning-period-secs: 3600
      num-epochs-to-retain: 0

    end_of_epoch_broadcast_channel_capacity: 128
    ```

## Start the Node

1. Start the validator process with your config file:

    ```
    RUST_LOG=info soma start validator --config validator.yaml
    ```

2. Look for increasing checkpoint height. This means your node is syncing with the network.

3. Wait for the node to fully sync before proceeding to [join the network](https://docs.soma.org/guides/validator/join-network/). A partially synced validator will miss proposals and may be penalized.

## Troubleshooting

<details>
<summary>Common startup issues</summary>

- **Port conflict**: another process is using a required port. Check with `lsof -i :8080` (or the relevant port) and stop the conflicting process or reconfigure.
- **Disk space low**: monitor with `df -h` and plan for expansion. Running out mid-sync corrupts state.
- **Checkpoint height stops advancing**: check your network connection and firewall rules. Ensure consensus and P2P ports are reachable. Restarting usually resolves transient stalls.
- **OOM killed**: check `dmesg | tail` for OOM messages. Ensure at least 14 GB RAM is available.

</details>