This guide will help you set up a validator node for the Vana Proof-of-Stake (PoS) network using Docker.
- Docker: Install Docker
- Docker Compose: Install Docker Compose
- OpenSSL: Install via your package manager:
sudo apt-get install openssl # Debian-based systems brew install openssl # macOS
- Hardware: Ensure your system meets the minimum hardware requirements for running a Vana Propagator (Validator)
-
Clone the repository:
git clone https://github.com/vana-com/vana.git cd vana
-
Configure your environment:
# For Moksha testnet cp .env.moksha.example .env # OR for Mainnet cp .env.mainnet.example .env # Edit .env with your preferred text editor
-
Start your node:
docker compose --profile init --profile node up -d
-
Verify your node is running:
# View logs for key services docker compose logs -f geth # Execution client docker compose logs -f beacon # Consensus client
đź’ˇ Tip: Check out the Fast Syncing section below to significantly speed up your initial node sync!
Note: If services fail to start, check the configuration validation logs:
docker compose logs check-config-node
Once your node is fully synced, follow these steps to set up and run a validator.
⚠️ IMPORTANT: Running a validator on the Vana network requires whitelisting. Please join our Discord to request validator permissions before proceeding with setup.
-
Configure validator settings in
.env
:# Configure validator settings WITHDRAWAL_ADDRESS=<your_withdrawal_address> DEPOSIT_RPC_URL=<your_rpc_url> DEPOSIT_CONTRACT_ADDRESS=<contract_address>
-
Set up validator keys:
If you have existing keys:
- Place keystore files in
./secrets
- Create
wallet_password.txt
andaccount_password.txt
in./secrets
# Import existing keys docker compose --profile manual run --rm validator-import
If you need new keys:
# Generate new keys docker compose --profile manual run --rm validator-keygen # Import generated keys docker compose --profile manual run --rm validator-import
- Place keystore files in
-
Submit deposits (if not done already):
# Add deposit private key echo "your_private_key" > ./secrets/deposit_private_key.txt # Submit deposits docker compose --profile manual run --rm submit-deposits
-
Configure validator statistics reporting:
# Set stats configuration in .env STATS_SERVER_URL=http://stats.vana.org INSTANCE_NAME="Your Validator Name" VALIDATOR_PUBLIC_KEY=0x... # Your validator's public key
Get your validator's public key using either method:
# Method 1: From deposit data cat ./secrets/deposit_data-*.json | jq -r '.[0].pubkey' # Method 2: List validator accounts docker compose --profile init run --rm validator accounts list --wallet-dir=/vana/wallet
View your node's statistics at stats.vana.org. Your node will appear under the name specified in
INSTANCE_NAME
. -
Start the validator:
docker compose --profile validator up -d
Note: If the validator fails to start, check the configuration validation logs:
docker compose logs check-config-validator
To voluntarily exit your validator, ensure your beacon node is fully synced and run:
docker compose --profile init --profile manual run --rm validator-exit
This service requires account_password.txt
and wallet_password.txt
in the secrets
folder.
Important: Exiting your validator is permanent and cannot be reversed. This only signals your intent to exit - it does not withdraw funds. For withdrawal functionality, see the withdrawal documentation.
Before proceeding with setup, you must get your validator whitelisted:
-
Join the Vana Discord and request validator permissions
-
Generate your validator keys following the Validator Setup section
-
Submit your validator's public key for whitelisting through Discord
-
Wait for confirmation before proceeding with deposits and starting your validator
There are two recommended methods to speed up your initial node sync:
Checkpoint sync is the recommended way to quickly sync your node. You will need:
- A trusted beacon node that serves checkpoint syncing (checkpoint sync URL)
- A specific block root and epoch number that you wish to sync to (weak subjectivity checkpoint)
Configure them in your .env
file:
# Use appropriate URL for your network
TRUSTED_BEACON_NODE_URL=http://archive.vana.org:3500
# Replace with actual checkpoint from a trusted source
WEAK_SUBJECTIVITY_CHECKPOINT=0x0000...0000:0 # block root:epoch number
Then uncomment these lines in docker-compose.yml
under the beacon
service:
- --weak-subjectivity-checkpoint=${WEAK_SUBJECTIVITY_CHECKPOINT}
- --checkpoint-sync-url=${TRUSTED_BEACON_NODE_URL}
- --genesis-beacon-api-url=${TRUSTED_BEACON_NODE_URL}
For a fast initial sync, you can also restore a recent publicly available backup. See the Backup and Restore section for detailed instructions on downloading and restoring snapshots.
Edit the .env
file to configure your node. Key variables include:
NETWORK
: Choose betweenmoksha
(testnet) ormainnet
CHAIN_ID
: Network chain IDEXTERNAL_IP
: Your node's external IP address- Various port configurations for different services
Ensure all required variables are set correctly before proceeding.
After starting your services, you can check the logs to ensure everything is running correctly:
-
View logs for all services:
docker compose logs
-
View logs for specific key services:
docker compose --profile=init --profile=node logs -f geth docker compose --profile=init --profile=node logs -f beacon docker compose --profile=init --profile=node logs -f validator
-
To follow logs in real-time and filter for specific patterns:
docker compose --profile=init --profile=node logs -f geth 2>&1 | grep 'Looking for peers' docker compose --profile=init --profile=node logs -f beacon 2>&1 | grep 'Synced new block' docker compose --profile=init --profile=node logs -f validator 2>&1 | grep 'Submitted new'
When reviewing logs, look for:
- Geth (execution layer): Messages about peer connections and syncing progress
- Beacon Chain: Indications of connection to the network and slot processing
- Validator: Messages about duties being performed and contributions submitted
If you see error messages or unexpected behavior in the logs, refer to the troubleshooting section or seek support.
If you encounter issues:
- Ensure all configuration files are present and correctly formatted.
- Check individual service logs for specific error messages.
- Verify that your
.env
file contains all necessary variables. - Run the configuration check:
docker compose run --rm check-config
- For connection issues, check your firewall settings and ensure the necessary ports are open.
- If services fail to start, try restarting them individually:
docker compose restart <service_name>
- Securely store your validator keys and never share them.
- Regularly update your node software to the latest version.
- Monitor your validator's performance and status regularly.
For additional help or to report issues, please open an issue in the GitHub repository or contact the Vana support team.
The docker-compose.yml
file provides several additional capabilities for managing your Vana PoS validator node. Here are some useful commands and their purposes:
Different profiles are available for various operations:
init
: Initialize clients, generate secretsnode
: Run the main node servicesvalidator
: Run validator-specific servicesmanual
: For manual operations like key generationdelete
: Delete data, e.g. to reset the chain so you can re-syncpublic
: Expose APIs securely via Caddy reverse proxy (ports 80/443)
You can combine profiles as needed. Whenever a service depends on another service, you must include the dependent profile.
For example, to start the node, you must include the init
and node
profiles:
docker compose --profile init --profile node up -d
For example, to run the node with public API access:
docker compose --profile init --profile node --profile public up -d
Or to start/stop just the API gateway:
docker compose --profile init --profile node --profile public up -d caddy
docker compose --profile init --profile node --profile public down caddy
Generate validator keys (interactive process):
docker compose --profile init --profile manual run --rm validator-keygen
Import validator keys:
docker compose run --profile manual --rm validator-import
To delete all data/ (does not remove generated secrets/):
docker compose --profile delete run --rm delete-all
To delete execution or consensus layer data:
docker compose --profile delete run --rm delete-geth
docker compose --profile delete run --rm delete-beacon
Run a configuration check:
docker compose --profile=init --profile=node run --rm check-config
You can start, stop, or restart individual services:
docker compose --profile=init --profile=node up -d geth
docker compose --profile=init --profile=node stop beacon
docker compose --profile=init --profile=node restart validator
View logs for specific services:
docker compose --profile=init --profile=node logs geth
docker compose --profile=init --profile=node logs beacon
docker compose --profile=init --profile=node logs validator
Add -f
to follow the logs in real-time:
docker compose --profile=init --profile=node logs -f geth
Use grep to filter for specific events:
docker compose --profile=init --profile=node logs -f geth 2>&1 | grep 'Looking for peers'
docker compose --profile=init --profile=node logs -f beacon 2>&1 | grep 'Synced new block'
docker compose --profile=init --profile=node logs -f validator 2>&1 | grep 'Submitted new'
Remember that many settings are controlled via environment variables in the .env
file. You can modify these to adjust your node's configuration.
For more detailed information on Docker Compose commands and options, refer to the official Docker Compose documentation.
After generating validator keys and before starting your validator, you need to submit deposits for each validator. This process stakes your ETH and registers your validator(s) with the network.
-
Ensure you have the following environment variables set in your
.env
file:DEPOSIT_RPC_URL
: The RPC URL for the network on which you're submitting depositsDEPOSIT_CONTRACT_ADDRESS
: The address of the deposit contract
-
Create a file named
deposit_private_key.txt
in the./secrets
directory containing the private key of the account funding the deposits:echo "your_private_key_here" > ./secrets/deposit_private_key.txt
Replace
your_private_key_here
with the actual private key. -
Run the deposit submission process:
docker compose --profile manual run --rm submit-deposits
This command will iterate through all generated validator keys and submit the required deposits.
-
Wait for the transactions to be confirmed on the network before proceeding to start your validator.
For more detailed information on Docker Compose commands and options, refer to the official Docker Compose documentation.
The validator node exposes its APIs through a Caddy reverse proxy for secure HTTPS access. By default, it uses localhost
but you can configure a custom domain in your .env
file. The provided Caddyfile configuration is a basic starting point and may need additional security headers and hardening for production use.
If using a custom domain:
- Point your domain's DNS to your server's IP address
- Ensure ports 80 and 443 are open on your firewall
- Set your domain and email (for Let's Encrypt) in the
.env
file
The API gateway implements the following access controls:
- Public endpoints:
- Execution layer: All JSON-RPC endpoints (POST /)
- Consensus layer: Limited set of beacon endpoints including genesis, headers, validator info, and node status
- Private endpoints (localhost and trusted IPs only):
- All other consensus layer endpoints under /eth/*
- Configure trusted IPs via RPC_TRUSTED_IP_RANGES in .env
For local testing, you can access the APIs using curl with the -k
flag to skip certificate verification:
# Query beacon node identity (public endpoint)
curl -k -X GET 'https://localhost/eth/v1/node/identity' -H 'accept: application/json'
# Query execution node info (public endpoint)
curl -k -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_nodeInfo","params":[],"id":1}' \
https://localhost
You can also install Caddy's root CA certificate on your host machine:
Linux:
docker compose cp \
caddy:/data/caddy/pki/authorities/local/root.crt \
/usr/local/share/ca-certificates/root.crt \
&& sudo update-ca-certificates
macOS:
docker compose cp \
caddy:/data/caddy/pki/authorities/local/root.crt \
/tmp/root.crt \
&& sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain /tmp/root.crt
Windows:
docker compose cp \
caddy:/data/caddy/pki/authorities/local/root.crt \
%TEMP%/root.crt \
&& certutil -addstore -f "ROOT" %TEMP%/root.crt
Note: Many modern browsers maintain their own certificate trust stores. You may need to manually import the root.crt file in your browser's security settings.
If you encounter SSL-related issues:
- Check Caddy logs:
docker compose logs caddy
- Verify your domain points to your server's IP address
- Confirm ports 80 and 443 aren't used by other services
- Check your firewall allows traffic on ports 80 and 443
The setup includes services for backing up and restoring your node data. You can also use provided snapshots for faster sync.
To quickly sync your node using provided snapshots:
-
Download and verify snapshots:
# Download snapshot files (replace DATE with actual date, e.g., 20241104) wget https://storage.googleapis.com/vana-snapshots/DATE/geth-chaindata-DATE.tar.zst{,.md5} wget https://storage.googleapis.com/vana-snapshots/DATE/beacon-chaindata-DATE.tar.zst{,.md5} # Verify checksums md5sum -c *.md5
-
Extract snapshots to the backups directory:
zstd -d geth-chaindata-DATE.tar.zst -o "backups/geth_backup_DATE.dat" zstd -d beacon-chaindata-DATE.tar.zst -o "backups/beaconchain_DATE.db"
-
Restore the snapshots:
# For Geth (requires interactive terminal) docker compose run -it --rm geth-restore # For Beacon chain (requires interactive terminal) docker compose run -it --rm beacon-restore
Note: make sure you trust the snapshot provider and verify the checksums before restoring!
To create and restore manual backups of your node data:
To perform a backup of your Geth data, ensure that the geth service is stopped, then run:
docker compose --profile backup run --rm geth-backup
This will create a timestamped backup file in the ./backups directory.
To perform a backup of your Beacon Chain data, ensure that the beacon service is stopped, then run:
docker compose --profile backup run --rm beacon-backup
This creates a timestamped copy of the Beacon Chain database in the ./backups directory.
The validator backup can be triggered while the validator service is running:
docker compose --profile backup run --rm validator-backup
This sends a request to the validator service to create a backup, which will be stored in the ./backups directory.
Before performing any restore operations, ensure that the respective services are stopped.
To restore Geth data:
docker compose --profile restore run --rm geth-restore
You'll be prompted to select a backup file to restore from.
To restore Beacon Chain data:
docker compose --profile restore run --rm beacon-restore
You'll be prompted to select a backup file to restore from.
To restore Validator data:
docker compose --profile restore run --rm validator-restore
You'll be prompted to select a backup file to restore from.
- Remember your password and separately backup your keystore(s)!
- Performing backups while services are running risks corrupting the backup, with the exception of the validator backup.
- After restoring data, you may need to resync your node to catch up with the latest state of the network.
The API gateway includes CORS (Cross-Origin Resource Sharing) headers to control which domains can access the API. By default, it allows all origins (*
) but this can be restricted:
- Set allowed origins in your
.env
file:
# Allow specific origins (comma-separated)
CORS_ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
# Or allow all origins (default)
CORS_ALLOWED_ORIGINS=*
- When setting specific origins:
- Credentials will be allowed (
Access-Control-Allow-Credentials: true
) - Preflight requests are automatically handled
- Methods are limited to GET, POST, OPTIONS
- Only Content-Type header is allowed
- Preflight responses are cached for 24 hours
- Credentials will be allowed (
Security Note: Using
*
for CORS_ALLOWED_ORIGINS is acceptable for public RPC nodes but not recommended for nodes handling sensitive operations. Always restrict origins in production environments.