Skip to main content

Overview

The start-node command starts an SSV operator node instance. This is the main command for running an SSV operator that participates in distributed validator duties.

Usage

ssvnode start-node [flags]

Required Configuration

The node requires a configuration file specified via the --config flag. At minimum, you must configure:
  • Operator private key (via OperatorPrivateKey or KeyStore)
  • SSV network (ssv.Network)
  • Beacon node endpoint (eth2.BeaconNodeAddr)
  • Execution client endpoint (eth1.ETH1Addr)

Flags

--config
string
default:"./config/config.yaml"
required
Path to the main configuration file (YAML format).
ssvnode start-node --config=/path/to/config.yaml
--share-config
string
default:""
Path to an additional share configuration file that will override values from the main config.Useful for separating operator-specific settings from general configuration.
ssvnode start-node --config=./config.yaml --share-config=./share.yaml

Configuration Options

All configuration is done via YAML files or environment variables. Below are the key configuration sections:

Operator Identity

OperatorPrivateKey
string
Base64-encoded operator private key for contract event decryption.
Using raw private keys is not recommended for production. Use encrypted keystores instead.
OperatorPrivateKey: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ...
KeyStore
object
Recommended: Use encrypted keystore for operator private key.
KeyStore:
  PrivateKeyFile: ./encrypted_private_key.json
  PasswordFile: ./password.txt

SSV Network

ssv.Network
string
default:"mainnet"
The SSV network to join.Valid values:
  • mainnet - Production network
  • holesky - Holesky testnet
ssv:
  Network: mainnet

Consensus Layer (Beacon Node)

eth2.BeaconNodeAddr
string
required
HTTP URL of the beacon node to connect to.
eth2:
  BeaconNodeAddr: http://localhost:5052
eth2.WithWeightedAttestationData
boolean
default:"false"
Enable weighted attestation data from multiple beacon nodes for increased reliability.
eth2.WithParallelSubmissions
boolean
default:"false"
Enable parallel duty submissions to multiple beacon nodes.

Execution Layer

eth1.ETH1Addr
string
required
WebSocket URL of the execution client to connect to.Used for syncing SSV contract events (validator registrations, operator changes, etc.).
eth1:
  ETH1Addr: ws://localhost:8546/ws

P2P Network

p2p.HostAddress
string
External IP address of the node (auto-detected if not specified).
p2p:
  HostAddress: 192.168.1.100
p2p.TcpPort
int
default:"13001"
TCP port for P2P communication.
p2p.UdpPort
int
default:"12001"
UDP port for P2P discovery.
p2p.Discovery
string
default:"discv5"
P2P discovery mechanism.
  • discv5 - Standard discovery (production)
  • mdns - Local network discovery (development only)
NetworkPrivateKey
string
Private key for P2P network identity. Auto-generated if not provided.

Database

db.Path
string
default:"./data/db"
Path to persistent directory for node database storage.
db:
  Path: ./data/db

MEV Configuration

ProposerDelay
duration
default:"0s"
Duration to wait before requesting a block proposal if this operator is the proposer-duty leader.Allows extracting higher MEV by waiting for better bids. Recommended starting value: 300ms.
Values above 1s significantly increase the risk of missing block proposals!
ProposerDelay: 300ms
See Production Deployment for detailed MEV guidance.
AllowDangerousProposerDelay
boolean
default:"false"
Safety flag to allow ProposerDelay values higher than 1s.
Only enable if you understand the risks of missed proposals.
Graffiti
string
default:"ssv.network"
Custom graffiti string for block proposals.
Graffiti: "My SSV Operator"

API Servers

MetricsAPIPort
int
default:"0"
Port for Prometheus metrics endpoint. Set to 0 to disable.
MetricsAPIPort: 15000
Access metrics at http://localhost:15000/metrics
SSVAPIPort
int
default:"0"
Port for SSV REST API. Set to 0 to disable.
Keep this port private to prevent resource-intensive attacks.
SSVAPIPort: 16000
WsAPIPort
int
default:"0"
Port for WebSocket API server.
WithPing
boolean
default:"false"
Enable WebSocket ping messages.

Logging

LogLevel
string
default:"info"
Logger verbosity level.Valid values: debug, info, warn, error, fatal, panic
global:
  LogLevel: debug
LogFormat
string
default:"console"
Logger encoding format.
  • console - Human-readable (default)
  • json - Machine-readable JSON
LogLevelFormat
string
default:"capitalColor"
Log level formatting style.
  • capitalColor - Colored output (default for console)
  • capital - Capitalized without color
  • lowercase - Lowercase level names
LogFilePath
string
default:"./data/debug.log"
File path for log output.
LogFileSize
int
default:"500"
Maximum log file size in megabytes before rotation.
LogFileBackups
int
default:"3"
Number of rotated log files to keep.

Advanced Options

EnableTraces
boolean
default:"false"
Enable OpenTelemetry distributed traces.
EnableProfile
boolean
default:"false"
Enable Go profiling tools (pprof).
EnableDoppelgangerProtection
boolean
default:"false"
Enable doppelganger protection to prevent running duplicate validators.
LocalEventsPath
string
Path to local events file for testing/development.
LocalEventsPath: ./config/events.yaml

Examples

Basic Configuration

config.yaml
global:
  LogLevel: info
  LogFilePath: ./data/debug.log

db:
  Path: ./data/db

ssv:
  Network: mainnet

eth2:
  BeaconNodeAddr: http://localhost:5052

eth1:
  ETH1Addr: ws://localhost:8546/ws

p2p:
  TcpPort: 13001
  UdpPort: 12001

KeyStore:
  PrivateKeyFile: ./encrypted_private_key.json
  PasswordFile: ./password.txt

MetricsAPIPort: 15000
./bin/ssvnode start-node --config=./config.yaml

Configuration with MEV

config.yaml
ssv:
  Network: mainnet

eth2:
  BeaconNodeAddr: http://localhost:5052

eth1:
  ETH1Addr: ws://localhost:8546/ws

KeyStore:
  PrivateKeyFile: ./encrypted_private_key.json
  PasswordFile: ./password.txt

# MEV Configuration
ProposerDelay: 300ms
Graffiti: "My MEV Operator"

MetricsAPIPort: 15000

Multi-Beacon Node Setup

config.yaml
eth2:
  BeaconNodeAddr: http://localhost:5052,http://backup:5052
  WithWeightedAttestationData: true
  WithParallelSubmissions: true

eth1:
  ETH1Addr: ws://localhost:8546/ws

KeyStore:
  PrivateKeyFile: ./encrypted_private_key.json
  PasswordFile: ./password.txt

Environment Variables

export LOG_LEVEL=debug
export SSV_NETWORK=mainnet
export BEACON_NODE_ADDR=http://localhost:5052
export ETH1_ADDR=ws://localhost:8546/ws
export PRIVATE_KEY_FILE=./encrypted_private_key.json
export PASSWORD_FILE=./password.txt
export METRICS_API_PORT=15000

./bin/ssvnode start-node

Output

When the node starts successfully, you’ll see:
2026-03-04T12:00:00.000Z	INFO	starting SSV-Node-v1.4.0-abc123def
2026-03-04T12:00:00.100Z	INFO	connecting CL(s)	{"Address": "http://localhost:5052"}
2026-03-04T12:00:00.200Z	INFO	beacon client ready	{"version": "Lighthouse/v4.5.0"}
2026-03-04T12:00:00.300Z	INFO	starting P2P network	{"tcp": 13001, "udp": 12001}
2026-03-04T12:00:00.400Z	INFO	node started successfully

Common Issues

could not read config: open ./config/config.yaml: no such file or directory
Solution: Specify the correct path to your config file:
./bin/ssvnode start-node --config=/full/path/to/config.yaml
Failed to decrypt private key
Solution: Ensure your password file contains the correct password:
cat password.txt  # Verify password is correct
failed to create beacon client: context deadline exceeded
Solution: Verify beacon node is running and accessible:
curl http://localhost:5052/eth/v1/node/version
failed to connect to execution client
Solution: Check WebSocket connection:
# Test WebSocket connectivity
wscat -c ws://localhost:8546/ws
bind: address already in use
Solution: Change the port in your config or stop the conflicting process:
p2p:
  TcpPort: 13002  # Use different port
  UdpPort: 12002

See Also

Build docs developers (and LLMs) love