> For the complete documentation index, see [llms.txt](/llms.txt)

# Generate keystore

**Time:** \~5 minutes.

<!-- -->

<!-- -->

## 1. Generate a publisher mnemonic (24 words)

```bash
cast wallet new-mnemonic --words 24
```

Back up the mnemonic NOW, before anything else

**Write it down on paper, or store it on a hardware device. Do this before you continue.**

This 24-word phrase is the **only** way to regenerate your publisher private key if you lose the server. **There is no recovery if you skip this step.** Lose the mnemonic, lose the funds in the publisher account, lose the ability to publish, get slashed for inactivity, lose your stake.

Do **not**:

* Store it on the server running the node.
* Email it to yourself.
* Save it in a password manager that syncs to the cloud without a hardware-key second factor.
* Take a screenshot.

## 2. Derive the publisher private key

```bash
cast wallet derive-key "your 24 word mnemonic phrase here"
```

Copy the returned private key into the **Publisher Private Key** field in the configuration panel.

<!-- -->

## 3. Generate the validator keystore

The configuration panel says you'll register **1** sequencer identit<!-- -->. Adjust the **Sequencer count** field above if that's wrong before running the command.

```bash
aztec validator-keys new \
  --fee-recipient 0x0000000000000000000000000000000000000000000000000000000000000000 \
  --staker-output \
  --gse-address {{GSE_ADDR}} \
  --l1-rpc-urls {{ETH_RPC}} \
  --l1-chain-id {{L1_CHAIN_ID}} \
  --publishers {{PUBLISHER_KEY}} \
  --count {{COUNT}}
```

Provider coinbase is set per delegation, not here

A provider's coinbase is **not** a single wallet you choose now. Each time a delegator stakes to you, the protocol creates a **Splits-V2 Split contract** for that delegation and, in the default flow, you update that specific attester's `coinbase` field to point at the new Split contract address, then reload the keystore. (Providers using the [payout-script flow](/operate/operators/provider/configure-environment.md#alternative-eoa-coinbase-with-the-payout-script) point coinbase at an address they control instead.) The procedure for updating coinbase after a delegation arrives lives in [Configure environment](/operate/operators/provider/configure-environment.md#after-delegation-set-coinbase-to-the-split-contract). For now, omit `--coinbase` so it defaults to the attester address, so the keystore is functional and you'll update it per attester later. Failing to update coinbase after a delegation means rewards route to your hot attester key instead of the Split, breaking your commission accounting and the delegator's claim flow.

<!-- -->

This writes two files in `~/.aztec/keystore/`:

* **`key1.json`** is the private keystore. Never share it, never commit it to git.
* **`key1_staker_output.json`** is the public keystore. Safe to share. You'll upload it to the staking dashboard when you [register as sequencer](/operate/operators/provider/register-sequencer.md).

Securing the keystore in production

This command stores private keys inline in `key1.json`. That's the simplest setup, but means anyone with read access to the file gets your keys. At a minimum, restrict file permissions (`chmod 600 ~/.aztec/keystore/key1.json`), use full-disk encryption, and limit who can SSH into the server. For more advanced storage (encrypted JSON V3 keystores, remote signers like Web3Signer), see [Key storage methods](/operate/operators/keystore/storage-methods.md).

Make sure you have the mnemonic saved offline

The mnemonic from step 1 is your **single backup**. Both the publisher ECDSA key and the attester BLS key are derived deterministically from it, so re-running the same `aztec validator-keys new` command with the same mnemonic reproduces `key1.json` byte-for-byte. If the server's disk fails and you have the mnemonic, you can rebuild the node from scratch.

Without the mnemonic and without a copy of `key1.json`, a disk loss means a forced exit and re-registration, including the withdrawal delay of about 10 days.

Optional, for faster recovery: keep an encrypted copy of `key1.json` and `key1_staker_output.json` somewhere off this server. Restoring from a copy is faster than re-deriving from the mnemonic. The command below uses GPG symmetric encryption (most Linux distros ship `gpg`; macOS users can `brew install gnupg`). It prompts for a passphrase, asks you to confirm it, and writes the encrypted archive:

```bash
tar czf - ~/.aztec/keystore/key1.json ~/.aztec/keystore/key1_staker_output.json \
  | gpg --symmetric --cipher-algo AES256 --output aztec-keystore-backup.tar.gz.gpg
```

Move `aztec-keystore-backup.tar.gz.gpg` off this server (hardware drive, encrypted cloud bucket, air-gapped machine). To restore later, on a fresh server, run:

```bash
gpg --decrypt aztec-keystore-backup.tar.gz.gpg | tar xzf - -C /
```

GPG prompts for the same passphrase. The keystore lands back in `~/.aztec/keystore/key1.json`.

## 4. Extract your addresses

<!-- -->

<!-- -->

## 5. Verify the keystore loaded correctly

```bash
cat ~/.aztec/keystore/key1.json | jq .
```

Expected structure:

```json
{
  "schemaVersion": 1,
  "validators": [{
    "attester": { "eth": "0x...", "bls": "0x..." },
    "publisher": ["0x..."],
    "feeRecipient": "0x000...000",
    "coinbase": "0x..."
  }]
}
```

## Before you continue

* **Mnemonic written down on paper or stored on a hardware device.** Not on this server. Not in a synced password manager. Not in a screenshot.
* `key1.json` and `key1_staker_output.json` exist in `~/.aztec/keystore/`.
* Attester address and Publisher address filled in the configuration panel.

If you cannot honestly check off the first item, **stop now and do it**. The next steps fund accounts with real ETH and AZTEC; losing the mnemonic after that point costs money.

***

The keys, the addresses, and who calls what

A sequencer involves a small cast of distinct identities. They can be the same wallet for a casual setup, or fully separated for a production setup.

**Cryptographic keys (live in `key1.json`):**

* **Attester ETH key (ECDSA)** identifies your sequencer on the network. The address derived from this key is what gets registered in the Rollup contract and what other operators see. It can also start an exit of its position (an [attester-initiated exit](/operate/operators/sequencer-management/exiting-a-sequencer.md)). The stake still goes to the withdrawer, but anyone holding this key can take the sequencer out of the active set, so protect it like the node itself.
* **Attester BLS key (BLS12-381)** signs block attestations. BLS signatures aggregate, so when a 32-member committee attests to a block, all 32 signatures combine into one short signature on L1. That saves gas.
* **Publisher key (ECDSA)** is a separate Ethereum account that pays L1 gas when your node submits proofs and attestations. Keeping it separate means you can rotate the funded account without rotating your sequencer identity.

**Operational addresses (passed in at registration time, stored onchain):**

* **Caller** is whoever calls `Rollup.deposit(...)` to register the sequencer. This is the address whose 200K AZTEC gets pulled in as stake (verified against `StakingLib.deposit`: `safeTransferFrom(msg.sender, ...)`). Typically a treasury or operator multisig that holds the AZTEC.
* **Withdrawer** is the address that controls the stake: it can start an exit with `initiateWithdraw`, names the recipient for every exit (including attester-initiated ones), signs governance delegations ([governance docs](/operate/operators/sequencer-management/creating_and_voting_on_proposals.md)), and receives residual stake on slash-driven ejection ([slashing docs](/operate/operators/sequencer-management/slashing_and_offenses.md)). Use a cold wallet or multisig you control. It does **not** need to be the same as the caller.
* **Coinbase** is an L1 Ethereum address that accumulates sequencer rewards on the Rollup contract. You claim them via `claimSequencerRewards(coinbase)`.
* **Fee recipient** is an L2 Aztec address that would collect L2 transaction fees. L2 fees are not enabled today, so this is a placeholder set to `0x000...000`.

**Casual setup** uses one operator wallet for caller + withdrawer + coinbase, plus a hot publisher key on the box, plus the in-keystore attester. **Production setup** keeps caller and withdrawer on a multisig, attester hot on the node, publisher funded separately, and coinbase on a treasury wallet. Four (or five) distinct identities, each rotatable on its own.

`--gse-address` in the keystore-generation command points at the **Governance Staking Escrow** contract that manages validator registration and stake. It is a different address on testnet vs mainnet; the configuration panel handles that for you.

For the deeper schema, advanced patterns (multi-validator, hardware-wallet publisher), and recovery procedures, see the [Keystore Management section](/operate/operators/keystore.md).

Something wrong?

* **"Error: could not connect to RPC"** — Your L1 RPC URL may be wrong or rate-limited. Test with `cast block-number --rpc-url YOUR_URL`.
* **`jq` shows an empty validators array** — Re-run the command. Ensure `--publishers` has a valid private key with the `0x` prefix.

**Stuck?** Ask in [Discord](https://discord.com/invite/aztec).
