Deploy Monad validators in minutes, not hours. Ansible automation for the entire lifecycle — setup, monitoring, upgrades, and recovery — on testnet and mainnet.
Target server:
| Component | Specification |
|---|---|
| OS | Ubuntu 22.04 / 24.04 |
| CPU | 16+ cores |
| RAM | 32GB minimum |
| Storage | 2TB NVMe (TrieDB) + 500GB (OS/consensus) |
| Network | 1Gbps, static IP |
Your local machine:
- Ansible 2.15+
- Python 3.10+
jq(for Makefile helper scripts)- SSH key access to target server (root or sudo user)
# Clone the repo
git clone https://github.com/pointgroup-labs/mv-manager.git
cd mv-manager
# Install Ansible collections
ansible-galaxy install -r requirements.yml
# Configure secrets
cp group_vars/vault.yml.example group_vars/vault.yml
vim group_vars/vault.yml
ansible-vault encrypt group_vars/vault.yml
# Configure inventory
cp inventory/testnet.yml inventory/local.yml
vim inventory/local.yml # set your server IP
# Test connectivity
make ping
# Deploy
make deploy
# Apply snapshot for fast sync
make snapshot
# Monitor sync progress
make statusCopy from the example and fill in your values:
# IKM (Initial Key Material) - generates your SECP and BLS keys
vault_secp_ikm: "64_hex_chars"
vault_bls_ikm: "64_hex_chars"
# Keystore password (generate with: openssl rand -base64 32)
vault_keystore_password: "your_password"
# Staking (needed for validator registration)
vault_funded_wallet_private_key: "wallet_with_100k_MON"
vault_beneficiary_address: "0x..."
vault_auth_address: "0x..."Always encrypt after editing:
make vault-encryptall:
vars:
env: testnet # or mainnet
children:
monad:
children:
validators:
hosts:
my-validator:
ansible_host: "1.2.3.4"
type: validator
setup_triedb: true
register_validator: false
fullnodes:
hosts: {}Multiple validators — add more hosts under validators:
validators:
hosts:
validator-01:
ansible_host: "1.2.3.4"
type: validator
setup_triedb: true
validator-02:
ansible_host: "5.6.7.8"
type: validator
setup_triedb: trueTarget a specific node with NODE=:
make status NODE=validator-01
make restart NODE=validator-02make deploy runs the full deployment pipeline through these Ansible roles:
common → Preflight checks, firewall (UFW), fail2ban, sudoers
prepare_server → System packages, kernel tuning, hugepages, TrieDB disk
monad-node → Download binaries, node.toml config, systemd service
validator → Staking CLI, key generation, registration scripts
monitoring → Health check scripts, alert thresholds
backup → Automated backup scripts (daily, 7-day retention)
Each role can run independently using tags:
ansible-playbook -i inventory/local.yml playbooks/deploy-validator.yml --tags monadRun make help to see all available commands. All commands support NODE=<name> to target a specific host.
make deploy # Full deployment pipeline
make snapshot # Download and apply snapshot for fast sync
make execution # Setup execution layer (statesync socket)
make register # Register as validator (requires synced node + 100k MON)
make upgrade # Upgrade monad packages to latest versionmake health # Run health checks
make status # Show validator status (keys, sync, peers)
make logs # Tail consensus logs (LINES=100)
make watch # Stream logs in real-time with colormake restart # Restart consensus + execution services
make stop # Stop all monad services
make start # Start execution, then consensus
make backup # Backup keys and configmake recovery # Run full recovery playbook
make diagnose # Show diagnostic info (disk, memory, services)make ping # Test SSH connectivity
make hardware # Show server hardware specs (CPU, RAM, storage)
make speedtest # Run bandwidth speedtest
make ssh # SSH into first validator
make check # Syntax check all playbooksmake vault-edit # Edit vault secrets (decrypt → edit → re-encrypt)
make vault-encrypt # Encrypt vault file
make vault-decrypt # Decrypt vault fileNew nodes should sync from a snapshot rather than from genesis:
make deploy # Deploy node first
make snapshot # Download and apply latest snapshot
make status # Monitor block heightThe snapshot is downloaded from Monad's official CDN. Depending on your bandwidth, this can take 30–60 minutes. After applying, the node will catch up the remaining blocks automatically.
After your node is fully synced:
make registerRequirements:
- Node must be synced (
eth_syncingreturnsfalse) - Wallet funded with 100,000+ MON for self-stake
register_validator: trueset in inventory- Vault configured with
vault_funded_wallet_private_keyand addresses
The registration script stakes MON, submits your validator keys on-chain, and begins participating in consensus once the stake activates.
| Port | Protocol | Direction | Purpose |
|---|---|---|---|
| 8000 | TCP/UDP | Public | P2P consensus |
| 8001 | UDP | Public | Auth |
| 8002 | TCP | Localhost only | JSON-RPC |
| 4317 | TCP | Localhost only | OTEL gRPC (if enabled) |
| 8889 | TCP | Localhost only | Prometheus metrics (if enabled) |
Only P2P ports (8000, 8001) are exposed publicly. RPC and metrics are bound to localhost by default.
Node won't start
make diagnose # Check disk, memory, service status
journalctl -u monad-consensus -n 50 # View service logs on the serverSync is stuck or slow
make status # Check current block height
make logs LINES=200 # Look for errors in recent logs
make snapshot # Re-apply snapshot if neededConnection refused / can't reach node
make ping # Test SSH connectivity
make hardware # Verify server specs
# Check firewall: ports 8000 (TCP/UDP) and 8001 (UDP) must be openTrieDB mount issues
make diagnose # Check disk partitions
# Verify NVMe device path matches triedb_config.drive in all.yml
# Default: /dev/nvme0n1Recovery from crash
make recovery # Full recovery: check services, repair data, restartContributions are welcome. Please:
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-change) - Follow Conventional Commits for commit messages
- Submit a pull request