Secure validator with HW wallet
This guide updates your vote account’s withdraw authority from a local keypair (id.json) to a Ledger hardware wallet address, without plugging the Ledger into the server.
Step 1 — Check your current vote account (server)
On your server:
solana show-vote-account <VOTE_PUBKEY>
Confirm the Withdraw Authority matches the id.json
key you plan to replace.
Verify the pubkey of id.json
:
solana-keygen pubkey ~/.config/solana/id.json
This ensures you’re confirming the correct
id.json
key before updating its withdraw authority.
Step 2 — Get your Ledger’s public key (on your computer)
Plug in your Ledger, open the Solana app, and run:
solana-keygen pubkey "usb://ledger?key=0/0"
Copy the output — this is your Ledger withdraw authority address:
<LEDGER_PUBKEY>
You only need the public key. No Ledger connection is required on the server.
Step 3 — Set your RPC cluster (server)
Example for X1 testnet:
solana config set --url https://rpc.testnet.x1.xyz
Step 4 — Change the withdraw authority (server)
Run this on the server:
solana vote-authorize-withdrawer-checked \
<VOTE_PUBKEY> \
~/.config/solana/id.json \
<LEDGER_PUBKEY> \
--fee-payer ~/.config/solana/id.json \
--url https://rpc.testnet.x1.xyz
Signs with your current withdraw authority (
id.json
)Assigns your Ledger as the new withdraw authority
Pays the transaction fee from the same account
You are changing who can withdraw rewards. Validator operations are unaffected.
Step 5 — Verify on-chain (server or computer)
solana show-vote-account <VOTE_PUBKEY> --url https://rpc.testnet.x1.xyz | grep "Withdraw Authority"
You should see:
Withdraw Authority: <LEDGER_PUBKEY>
Step 6 — Back up and clean up (server)
🔐 Back up id.json
safely
id.json
safelyCreate a structured backup and store it in your password manager or encrypted vault:
mkdir -p ~/X1-backups/keys
cp ~/.config/solana/id.json ~/X1-backups/keys/
PUBKEY=$(solana-keygen pubkey ~/X1-backups/keys/id.json)
SHA256=$(shasum -a 256 ~/X1-backups/keys/id.json | awk '{print $1}')
cat > ~/X1-backups/keys/id_key_metadata.txt <<EOF
--- PRIVATE KEY (id.json) ---
$(cat ~/X1-backups/keys/id.json)
--- PUBLIC KEY ---
$PUBKEY
--- SHA256 (file checksum) ---
$SHA256
EOF
If you’re on macOS:
pbcopy < ~/X1-backups/keys/id_key_metadata.txt
echo "✅ id_key_metadata.txt copied to clipboard — paste it into your password manager."
🧹 Remove old key from server
Once you’ve confirmed your Ledger is the new withdraw authority:
shred -u ~/.config/solana/id.json || rm -f ~/.config/solana/id.json
🔒 Tighten permissions
chmod 700 ~/.config/solana
chmod 600 ~/.config/solana/*.json
This ensures only your current Linux user can access key files — protecting against accidental leaks or unauthorized reads.
Final State
Validator identity
identity.json
Operates the validator node
Vote account
vote.json
Account linked to validator for consensus/rewards
Withdraw authority (new)
Ledger hardware wallet
Securely holds withdraw rights
Withdraw authority (old)
id.json
(backed up & removed from server)
Former hot key, no longer used
Troubleshooting
“insufficient funds for fee”
id.json
has 0 balance. Send a small amount of testnet XNT to it before retrying.“Signature verification failed”
id.json
is not the current withdraw authority for this vote account, or you’re pointed at the wrong cluster.“This account may not be used to pay transaction fees” You tried to use a restricted account (e.g., validator identity) as fee-payer. Use a normal wallet or
id.json
itself.
Last updated