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.

The steps below show how to do this using the command-line interface (CLI). Alternatively, you can use validator.x1.wiki for a simple web-based way to replace your id.json with a hardware wallet.

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

Create 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

Role
File / Address
Description

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