# Secure validator with HW wallet

{% hint style="info" %}

> The steps below show how to do this using the command-line interface (CLI). Alternatively, you can use [validator.x1.wiki](https://validator.x1.wiki/) for a simple web-based way to replace your id.json with a hardware wallet.
> {% endhint %}

## Step 1 — Check your current vote account (server)

On your **server**:

```sh
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`:

```sh
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."
```

***

### 🔒 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)      | Former hot key, no longer used as withdraw authority |

***

## 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.x1.xyz/validating/secure-validator-with-hw-wallet.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
