Skip to main content

Overview

Securing your SSV Node is critical to protect your validator operations and prevent slashing. This guide covers security best practices, key management, and hardening procedures.

Operator Key Security

Key Generation

SSV Node operators must generate and protect their operator private keys. These keys are used to sign messages within the SSV network.
Never share your operator private key. If compromised, an attacker could impersonate your operator and potentially participate in malicious activities.
For production environments, always use encrypted keystore format:
1

Generate encrypted keystore

# Create a strong password file
echo "your-strong-password-here" > password.txt
chmod 600 password.txt

# Generate encrypted operator keys
docker run --rm -it \
  -v $(pwd):/keys \
  ssvlabs/ssv-node:latest \
  /go/bin/ssvnode generate-operator-keys \
  --password-file=/keys/password.txt
This generates an encrypted encrypted_private_key.json file.
2

Secure the keystore files

# Set restrictive permissions
chmod 600 encrypted_private_key.json
chmod 600 password.txt

# Store in a secure directory
sudo mkdir -p /etc/ssv/secrets
sudo mv encrypted_private_key.json /etc/ssv/secrets/
sudo mv password.txt /etc/ssv/secrets/
sudo chown root:root /etc/ssv/secrets/*
3

Configure SSV Node

Update your config.yaml:
KeyStore:
  PrivateKeyFile: /etc/ssv/secrets/encrypted_private_key.json
  PasswordFile: /etc/ssv/secrets/password.txt
4

Mount secrets in Docker

services:
  ssv-node:
    volumes:
      - /etc/ssv/secrets:/etc/ssv/secrets:ro
The :ro flag mounts the directory as read-only for additional security.

Converting Existing Keys

If you have an existing raw operator key, convert it to encrypted format:
docker run --rm -it \
  -v $(pwd):/keys \
  ssvlabs/ssv-node:latest \
  /go/bin/ssvnode generate-operator-keys \
  --password-file=/keys/password.txt \
  --operator-key-file=/keys/existing_key.txt
After conversion, securely delete the raw key file:
shred -vfz -n 10 existing_key.txt

Key Backup Strategy

1

Create encrypted backup

# Create encrypted archive
tar -czf - /etc/ssv/secrets | \
  gpg --symmetric --cipher-algo AES256 \
  -o ssv-keys-backup-$(date +%Y%m%d).tar.gz.gpg
2

Store in multiple locations

  • Secure offline storage (hardware encrypted USB)
  • Password manager vault
  • Secure cloud storage (encrypted)
  • Physical safe or safety deposit box
3

Document recovery procedure

Create a recovery document with:
  • Backup locations
  • Decryption instructions
  • Configuration file locations
  • Emergency contacts
Never store backup passwords in the same location as the encrypted backups.

Slashing Protection

Understanding Slashing Risks

Ethereum validators can be slashed for:
  1. Double Attestation: Signing two different attestations for the same slot
  2. Surround Voting: Signing attestations that surround or are surrounded by previous attestations
  3. Double Proposal: Proposing two different blocks for the same slot
SSV Node implements built-in slashing protection mechanisms to prevent these scenarios.

Built-in Protections

SSV Node includes automatic slashing protection:
// From source: attestations.md:15
// Slashing protection mechanism kicks in to ensure 
// Operator never signs two contradicting attestations
The node maintains a slashing protection database that tracks:
  • All signed attestations (slot, source epoch, target epoch)
  • All signed proposals (slot, block root)

Additional Protection Measures

1

Never run duplicate validators

Critical: Never run the same validator keys on multiple nodes or clusters simultaneously. This will result in slashing.
2

Proper migration procedure

When migrating validators:
  1. Stop the old node completely
  2. Wait for at least 2 epochs (13 minutes)
  3. Verify the old node is not attesting
  4. Start the new node
  5. Monitor for successful attestations
3

Database backup caution

Be extremely careful when restoring from database backups. Restoring an old database state and signing attestations can lead to slashing.
Best practice: Let the node sync from network events rather than restoring old database backups.
4

Monitor for anomalies

Set up alerts for:
  • Sudden increase in missed attestations
  • Duplicate validator indices in logs
  • Slashing warnings from beacon node

Network Security

Firewall Configuration

Implement defense-in-depth with multiple firewall layers:

UFW (Ubuntu Firewall)

# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH access (change port if using non-standard)
sudo ufw allow 22/tcp

# P2P ports
sudo ufw allow 12001/udp comment 'SSV P2P Discovery'
sudo ufw allow 13001/tcp comment 'SSV P2P Communication'

# Enable firewall
sudo ufw enable

# Verify rules
sudo ufw status verbose
Do not open ports 15000 or 16000 to the internet. These should only be accessible from your monitoring infrastructure.

iptables (Advanced)

# Flush existing rules (careful in production!)
sudo iptables -F

# Default policies
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# Allow loopback
sudo iptables -A INPUT -i lo -j ACCEPT

# Allow established connections
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow SSH from specific IP (replace with your IP)
sudo iptables -A INPUT -p tcp --dport 22 -s YOUR_ADMIN_IP -j ACCEPT

# Allow P2P ports
sudo iptables -A INPUT -p udp --dport 12001 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 13001 -j ACCEPT

# Allow metrics from monitoring server only
sudo iptables -A INPUT -p tcp --dport 15000 -s YOUR_MONITORING_IP -j ACCEPT

# Rate limiting to prevent DDoS
sudo iptables -A INPUT -p tcp --dport 13001 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

# Log dropped packets
sudo iptables -A INPUT -j LOG --log-prefix "iptables-dropped: "

# Save rules
sudo netfilter-persistent save

Cloud Provider Security Groups

For AWS, GCP, Azure deployments:
# Example AWS Security Group rules
Ingress Rules:
  - Protocol: TCP
    Port: 13001
    Source: 0.0.0.0/0
    Description: SSV P2P TCP
  
  - Protocol: UDP
    Port: 12001
    Source: 0.0.0.0/0
    Description: SSV P2P UDP Discovery
  
  - Protocol: TCP
    Port: 22
    Source: YOUR_ADMIN_IP/32
    Description: SSH Admin Access
  
  - Protocol: TCP
    Port: 15000
    Source: YOUR_VPC_CIDR
    Description: Metrics (internal only)

Egress Rules:
  - Protocol: All
    Port: All
    Destination: 0.0.0.0/0

DDoS Protection

1

Rate limiting

Configure connection limits in iptables:
sudo iptables -A INPUT -p tcp --syn --dport 13001 \
  -m connlimit --connlimit-above 50 -j REJECT
2

Fail2ban for SSH

sudo apt-get install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
3

Cloud-level protection

Enable DDoS protection services:
  • AWS Shield
  • Google Cloud Armor
  • Azure DDoS Protection

System Hardening

Operating System Security

1

Keep system updated

# Enable automatic security updates
sudo apt-get install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

# Manually update
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
2

Disable unnecessary services

# List running services
systemctl list-unit-files --state=enabled

# Disable unnecessary services
sudo systemctl disable bluetooth.service
sudo systemctl disable cups.service
3

Configure SSH securely

Edit /etc/ssh/sshd_config:
# Disable root login
PermitRootLogin no

# Use SSH keys only
PasswordAuthentication no
PubkeyAuthentication yes

# Limit users
AllowUsers your-user

# Change default port (optional but recommended)
Port 2222
Restart SSH:
sudo systemctl restart sshd
4

Enable AppArmor/SELinux

# Check AppArmor status
sudo aa-status

# Ensure it's enabled
sudo systemctl enable apparmor
sudo systemctl start apparmor

Docker Security

1

Run as non-root user

The SSV Node Docker image runs processes as non-root by default. Verify:
docker inspect ssvlabs/ssv-node:latest | grep User
2

Use read-only filesystem where possible

services:
  ssv-node:
    read_only: true
    tmpfs:
      - /tmp
      - /var/run
    volumes:
      - ./data:/data  # Only this needs write access
3

Drop unnecessary capabilities

services:
  ssv-node:
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE  # Only if binding to ports < 1024
4

Enable Docker security scanning

# Scan image for vulnerabilities
docker scan ssvlabs/ssv-node:latest

File System Security

# Set secure permissions on configuration
chmod 600 config.yaml
chown root:root config.yaml

# Secure data directory
chmod 700 ./data
chown -R 1000:1000 ./data

# Secure docker-compose file
chmod 600 docker-compose.yaml

Monitoring and Intrusion Detection

Log Monitoring

Set up centralized logging and monitoring:
1

Forward logs to SIEM

services:
  ssv-node:
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://your-siem:514"
        tag: "ssv-node"
2

Monitor for suspicious activity

Alert on:
  • Failed authentication attempts
  • Unexpected configuration changes
  • Abnormal P2P connection patterns
  • Unusual resource usage
  • Unexpected restarts
3

Enable audit logging

# Install auditd
sudo apt-get install auditd

# Monitor config file changes
sudo auditctl -w /path/to/config.yaml -p wa -k ssv-config-change

# Monitor secrets directory
sudo auditctl -w /etc/ssv/secrets -p ra -k ssv-secrets-access

Intrusion Detection

# Install AIDE
sudo apt-get install aide

# Initialize database
sudo aideinit
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Run checks daily
sudo aide --check

# Add to crontab
echo "0 2 * * * /usr/bin/aide --check" | sudo crontab -

Secrets Management

Environment Variables

For sensitive configuration, use environment variables instead of config files:
services:
  ssv-node:
    environment:
      # Don't use this for production - use secrets management
      OPERATOR_PRIVATE_KEY: ${OPERATOR_PRIVATE_KEY}
    env_file:
      - .env.secret
Secure the env file:
chmod 600 .env.secret
echo ".env.secret" >> .gitignore

Docker Secrets (Swarm)

For Docker Swarm deployments:
secrets:
  operator_key:
    external: true
  key_password:
    external: true

services:
  ssv-node:
    secrets:
      - operator_key
      - key_password

HashiCorp Vault Integration

# Store secret in Vault
vault kv put secret/ssv/operator-key \
  private_key=@encrypted_private_key.json \
  password=@password.txt

# Retrieve in startup script
vault kv get -field=private_key secret/ssv/operator-key > /tmp/key.json
vault kv get -field=password secret/ssv/operator-key > /tmp/password.txt

# Start node with retrieved secrets
docker-compose up -d

# Clean up
shred -vfz -n 10 /tmp/key.json /tmp/password.txt

Incident Response

Security Incident Playbook

1

Detection

Identify the security incident through:
  • Monitoring alerts
  • Log analysis
  • Anomaly detection
  • External notification
2

Containment

# Immediately stop the node if compromised
docker-compose down

# Isolate the server
sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT DROP
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT
3

Investigation

  • Preserve logs and system state
  • Analyze attack vectors
  • Determine scope of compromise
  • Check if operator keys were accessed
4

Recovery

If operator keys are compromised:
  1. Generate new operator keys
  2. Update operator registration on SSV network
  3. Rebuild server from clean image
  4. Implement additional security controls
  5. Monitor for follow-up attacks
5

Post-Incident

  • Document the incident
  • Update security procedures
  • Conduct post-mortem
  • Implement preventive measures

Emergency Contacts

Maintain a list of emergency contacts:
  • Security team members
  • Infrastructure team
  • SSV Network support: Discord
  • Beacon chain monitoring services

Security Checklist

Pre-Deployment

  • Operator keys generated using encrypted keystore format
  • Keys backed up in multiple secure locations
  • Passwords stored in password manager
  • Firewall rules configured and tested
  • SSH hardened (key-only auth, non-root, custom port)
  • System fully updated with automatic security updates enabled
  • Time synchronization configured

Deployment

  • Configuration files have restrictive permissions (600)
  • Secrets mounted as read-only in Docker
  • Docker security best practices applied
  • Metrics/API ports not exposed to internet
  • Log monitoring configured
  • Intrusion detection enabled

Ongoing

  • Regular security updates applied
  • Logs reviewed for anomalies
  • Backups tested regularly
  • Security alerts monitored
  • Incident response plan updated
  • Team trained on security procedures

Additional Resources

Next Steps

Build docs developers (and LLMs) love