Slv Validator
by @poppin-fumi
Deploys and manages Solana validators on mainnet and testnet using Ansible playbooks and Jinja2 templates for multiple validator types including jito, agave,...
clawhub install slv-validatorπ About This Skill
SLV Validator Skill
Ansible playbooks and Jinja2 templates for deploying and managing Solana validators (mainnet and testnet).
Supported Validator Types
| Type | Description |
|---|---|
| jito | Jito MEV client (default for mainnet) |
| jito-bam | Jito with Block Awareness Module |
| agave | Standard Agave validator |
| firedancer-agave | Firedancer with Agave consensus |
| firedancer-jito | Firedancer with Jito consensus |
Directory Structure
ansible/
mainnet-validator/ β Mainnet validator playbooks
testnet-validator/ β Testnet validator playbooks
cmn/ β Shared common playbooks
jinja/
mainnet-validator/ β Mainnet Jinja2 templates
testnet-validator/ β Testnet Jinja2 templates
cmn/ β Shared templates
CLI Command β Playbook Mapping
The slv v CLI commands map directly to these playbooks. {net} = mainnet-validator or testnet-validator.
| CLI Command | Playbook | Description |
|---|---|---|
| slv v deploy | {net}/init.yml | Full node initialization and deployment |
| slv v start | {net}/start_node.yml | Start validator |
| slv v stop | {net}/stop_node.yml | Stop validator |
| slv v restart | {net}/restart_node.yml | Restart validator |
| slv v build:solana | {net}/install_solana.yml | Build Solana from source |
| slv v install:solana | cmn/install_solana.yml | Install Solana binary (deprecated, prefer build) |
| slv v setup:firedancer | {net}/setup_firedancer.yml | Setup/update Firedancer |
| slv v update:firedancer | {net}/update_firedancer.yml | Update Firedancer binary |
| slv v update:script | {net}/update_startup_config.yml | Update start-validator.sh from template |
| slv v set:identity | {net}/set_identity_key.yml | Set validator identity key |
| slv v set:unstaked | {net}/set_unstaked_key.yml | Switch to unstaked identity |
| slv v get:snapshot | {net}/wget_snapshot.yml | Download snapshot via aria2c |
| slv v cleanup | cmn/rm_ledger.yml | Remove ledger/snapshot files |
| slv v switch | {net}/nodowntime_migrate.yml | Zero-downtime identity migration |
| slv v list | *(no playbook)* | List validators (CLI only) |
| slv v gen:vote-account | *(no playbook)* | Create vote account (solana CLI) |
All Playbooks
Mainnet Validator (mainnet-validator/)
| Playbook | Description |
|---|---|
| init.yml | Full node initialization (Agave/Jito) |
| init-jito.yml | Jito-specific initialization |
| init-firedancer.yml | Firedancer initialization |
| restart_node.yml | Restart validator |
| start_node.yml | Start validator |
| stop_node.yml | Stop validator |
| install_solana.yml | Build Solana from source |
| install_agave.yml | Build Agave from source |
| install_jito.yml | Build Jito from source |
| install_rust.yml | Install Rust toolchain |
| setup_firedancer.yml | Setup Firedancer binary and config |
| update_firedancer.yml | Update Firedancer binary |
| update_startup_config.yml | Update start-validator.sh from Jinja template |
| deploy-start-validator-sh.yml | Deploy start script to remote |
| create-start-validator-sh.yml | Generate start script from template |
| nodowntime_migrate.yml | Zero-downtime identity migration between nodes |
| set_identity_key.yml | Set validator identity key |
| set_identity_to_active.yml | Activate identity key |
| set_unstaked_key.yml | Switch to unstaked identity |
| switch_on_identity.yml | Enable identity (tower copy + key deploy) |
| switch_off_identity.yml | Disable identity (tower backup) |
| switch_on_firedancer_identity.yml | Enable Firedancer identity |
| switch_off_firedancer_identity.yml | Disable Firedancer identity |
| copy_keys.yml | Copy validator keys to node |
| copy_restart_sh.yml | Copy restarter script |
| create_overrides.yml | Generate overrides.yml from template |
| setup_solv_service.yml | Setup systemd service |
| start-solv-service.yml | Start systemd service |
| setup_ufw.yml | Configure UFW firewall |
| setup_fb_ufw.yml | Configure Firedancer-specific UFW rules |
| setup_logrotate.yml | Setup log rotation |
| configure_hugetlbfs.yml | Configure hugepages for Firedancer |
| fail2ban_solana_rate_limit.yml | Setup fail2ban rate limiting |
| run_snapshot_finder.yml | Find and download best snapshot |
Testnet Validator (testnet-validator/)
| Playbook | Description |
|---|---|
| init.yml | Full initialization (Jito) |
| init-agave.yml | Agave-specific initialization |
| init-firedancer.yml | Firedancer initialization |
| restart_node.yml | Restart validator |
| start_node.yml | Start validator |
| stop_node.yml | Stop validator |
| install_solana.yml | Build Solana from source |
| install_agave.yml | Build Agave from source |
| install_jito.yml | Build Jito from source |
| install_firedancer.yml | Build Firedancer from source |
| setup_firedancer.yml | Setup Firedancer |
| setup_firedancer_agave.yml | Setup Firedancer with Agave |
| setup_firedancer_jito.yml | Setup Firedancer with Jito |
| update_firedancer.yml | Update Firedancer binary |
| update_startup_config.yml | Update start script from template |
| deploy-start-validator-sh.yml | Deploy start script |
| create-start-validator-sh-agave.yml | Generate Agave start script |
| create-start-validator-sh-jito.yml | Generate Jito start script |
| nodowntime_migrate.yml | Zero-downtime identity migration |
| set_identity_key.yml | Set identity key |
| set_identity_to_active.yml | Activate identity |
| set_unstaked_key.yml | Switch to unstaked identity |
| switch_on_identity.yml / switch_off_identity.yml | Toggle identity |
| switch_on_firedancer_identity.yml / switch_off_firedancer_identity.yml | Toggle Firedancer identity |
| change_identity_and_restart.yml | Change identity and restart in one step |
| copy_keys.yml | Copy keys to node |
| rm_ledger.yml | Remove ledger data |
| restart_agave_with_rm_ledger.yml | Restart with ledger removal |
| restart_firedancer.yml | Restart Firedancer |
| restart_firedancer_with_rm_ledger.yml | Restart Firedancer with ledger removal |
| restart_solv.yml | Restart solv service |
| setup_agave.yml | Setup Agave |
| setup_agave_ufw.yml | Agave UFW rules |
| setup_solv_service.yml | Setup systemd service |
| setup_solv_service_init.yml | Initialize systemd service |
| setup_snapshot_finder.yml | Setup snapshot finder |
| add_solv.yml | Add solv user |
Shared Common (cmn/)
| Playbook | Description |
|---|---|
| build_solana.yml | Build Solana from source (dispatches to build_agave/build_jito) |
| build_agave.yml | Build Agave from GitHub source |
| build_jito.yml | Build Jito from GitHub source |
| install_solana.yml | Install Solana binary (deprecated) |
| install_package.yml | Install system packages |
| install_rust.yml | Install Rust toolchain |
| mount_disks.yml | Mount and format disks |
| optimize_system.yml | Optimize system settings (sysctl, limits) |
| disable_swap.yml | Disable swap |
| setup_logrotate.yml | Configure log rotation |
| setup_node_exporter.yml | Setup Prometheus node exporter |
| setup_norestart.yml | Disable auto-restart |
| setup_ufw.yml | Configure UFW firewall |
| setup_unstaked_identity.yml | Setup unstaked identity keypair |
| restart_solv.yml | Restart solv service |
| copy_restart_sh.yml | Copy restarter script |
| update_ubuntu.yml | Update Ubuntu packages |
| wget_snapshot.yml | Download snapshot |
| add_solv.yml | Add solv user |
| rm_ledger.yml | Remove ledger data |
| fix_permissions.yml | Fix file permissions |
Key Variables (extra_vars)
| Variable | Description | Default |
|---|---|---|
| validator_type | Validator type (jito, jito-bam, agave, firedancer-agave, firedancer-jito) | jito |
| solana_version | Solana/Agave version to build | β |
| jito_version | Jito version to build | β |
| firedancer_version | Firedancer version | β |
| snapshot_url | Snapshot download URL | β |
| identity_account | Validator identity pubkey | β |
| vote_account | Vote account pubkey | β |
| block_engine_url | Jito block engine URL | https://frankfurt.mainnet.block-engine.jito.wtf |
| shred_receiver_address | Jito shred receiver address | 64.130.50.14:1002 |
| commission_bps | Commission in basis points | 0 |
| dynamic_port_range | Validator port range | 8000-8025 |
| limit_ledger_size | Ledger size limit | 200000000 |
| expected_shred_version | Expected shred version (testnet, epoch-dependent) | β |
| expected_bank_hash | Expected bank hash (testnet, optional) | β |
| wait_for_supermajority | Wait for supermajority slot (testnet, optional) | β |
| source_host | Source host for nodowntime migration | β |
| target_host | Target host for nodowntime migration | β |
Usage
All playbooks are designed to be run via ansible-playbook with extra_vars:
ansible-playbook -i inventory mainnet-validator/init.yml \
-e '{"validator_type":"jito","solana_version":"3.1.8","snapshot_url":"https://..."}'
No versions.yml required β all variables can be passed via extra_vars.
Interactive Deployment Flow
When deploying a new validator, the agent should guide the user through variable collection
in this order. See AGENT.md for the full step-by-step flow and examples/inventory.yml
for the generated output format.
Required Variables (must collect)
| Variable | Prompt | Validation |
|---|---|---|
| server_ip | "Target server IP?" | Valid IPv4 |
| network | "Mainnet or testnet?" | mainnet or testnet |
| region | "Server region? (amsterdam, frankfurt, tokyo, ny, ...)" | String |
| validator_type | "Which validator type?" | jito, jito-bam, agave, firedancer-agave, firedancer-jito |
| solana_version | "Solana version? (default: 3.1.8)" | Semver |
| jito_version | "Jito version?" (if jito/jito-bam) | Semver |
| firedancer_version | "Firedancer version?" (if firedancer) | String |
| identity_account | "Validator identity pubkey? (or generate)" | Base58 pubkey or generate |
| vote_account | "Vote account pubkey? (or generate)" | Base58 pubkey or generate |
| snapshot_url | "Snapshot URL? (auto-detected for ERPC nodes)" | URL (cannot be empty for init) |
Optional Variables (show defaults, confirm)
| Variable | Default | When Required |
|---|---|---|
| ssh_user | solv (ubuntu for fresh servers) | Always |
| commission_bps | 0 | Always |
| dynamic_port_range | 8000-8025 | Always |
| limit_ledger_size | 200000000 | Always |
| allowed_ssh_ips | β | Strongly recommended (UFW) |
| allowed_ips | β | Optional (UFW) |
| block_engine_url | Auto by region | Jito types only |
| shred_receiver_address | Auto by region | Jito types only |
| expected_shred_version | Epoch-dependent | Testnet only |
| expected_bank_hash | Epoch-dependent | Testnet (optional) |
| wait_for_supermajority | Epoch-dependent | Testnet (optional) |
Optional: Reference RPC
| Variable | Description | Default |
|---|---|---|
| reference_rpc_url | Reference RPC endpoint for slot sync comparison (e.g., ERPC) | β |
ERPC API keys are free at https://erpc.global β enables full slot sync monitoring during deployment and updates.
Pre-flight: Fresh Server Setup
If the target is a new server without a solv user:
ansible-playbook -i inventory.yml cmn/add_solv.yml \
-e '{"ansible_user":"ubuntu"}' --become
Deployment Command
All paths relative to skill's ansible/ directory:
cd /path/to/slv-validator/ansible/
ansible-playbook -i inventory.yml {network}-validator/init.yml \
-e '{"validator_type":"","solana_version":"","snapshot_url":""}'
Dry-Run First
Always offer --check mode before actual deployment:
ansible-playbook -i inventory.yml {network}-validator/init.yml \
-e '{"validator_type":"jito","solana_version":"3.1.8"}' --check
π‘ Examples
All playbooks are designed to be run via ansible-playbook with extra_vars:
ansible-playbook -i inventory mainnet-validator/init.yml \
-e '{"validator_type":"jito","solana_version":"3.1.8","snapshot_url":"https://..."}'
No versions.yml required β all variables can be passed via extra_vars.