Skip to content

Run a Validator

Bringing a Zink validator online is mostly standard Agave / Solana operator work with one extra reality: the cluster is currently permissioned. A good new operator should be able to use this page to self-qualify, prepare a host, generate the correct keys, and know exactly which values still need to come from the Zink network team.

Zink-specific

Zink Testnet validator participation currently requires coordination with the network team. Treat this page as both a self-service preparation guide and the runbook to execute once you receive the current cluster bootstrap bundle.

What success looks like

By the end of this guide, you should have:

  • a trusted workstation with the Solana CLI and validator key material
  • a remote Linux host with separated NVMe storage and system tuning applied
  • a systemd-managed agave-validator launch command ready to run
  • a checklist of values to request from the Zink team before first join
  • a verification sequence that proves the node is visible, catching up, and ready to vote

What you prepare vs. what Zink provides

You prepare

  • validator-class hardware that meets System Requirements
  • a publicly reachable host with the intended dynamic port range open
  • validator identity, vote-account, and withdraw-authority keys
  • mounted ledger and accounts volumes
  • the Linux user, startup script, and systemd service you will run in production

The Zink network team provides or confirms

  • current cluster entrypoints
  • current known-validator pubkeys
  • expected genesis hash
  • required Agave / Solana version or release tag
  • vote-account policy for the target cluster (self-create vs. operator-provided)
  • any cluster-specific flags or admission requirements
  • confirmation that your identity and vote account are approved for the validator set

Zink recommendation

If you do not yet have current entrypoints, known validators, expected genesis hash, and version guidance, you are not blocked from preparing the machine — but you are blocked from safely joining the live cluster. Finish host prep first, then request the current bootstrap bundle.

Operator handoff checklist

Before or during onboarding, expect to exchange these values.

Send these to the network team

  • validator identity pubkey
  • vote account pubkey
  • public IP address or hostname
  • cloud/provider region
  • intended --dynamic-port-range
  • whether the host will expose RPC publicly, privately, or not at all
  • an operator contact for incident follow-up

Ask for these back

  • entrypoints for the target cluster
  • known validators for snapshot / gossip trust
  • expected genesis hash
  • recommended validator version
  • whether the vote account should be created by you or pre-provisioned by the team
  • any cluster-specific allowlisting or approval step after the node is online

Preferred bootstrap bundle format

Ask the Zink network team to send the live join parameters in a copy-pasteable bundle, not as prose scattered across chat.

text
cluster_name=Zink Testnet
validator_version=<AGAVE_OR_SOLANA_VERSION>
entrypoints=<HOST:PORT>,<HOST:PORT>
known_validators=<PUBKEY>,<PUBKEY>
expected_genesis_hash=<GENESIS_HASH>
dynamic_port_range=8000-10000
vote_account_policy=self-create | operator-provided
additional_flags=...
approval_contact=<TEAM_OR_PERSON>

That format makes it much harder to misread one value and spend an hour debugging the wrong problem.

1. Prepare a trusted workstation

Do the key-generation and vote-account work on a trusted machine, not on the remote validator host.

Install the CLI

bash
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"

solana --version
agave-validator --version

If the Zink team tells you to match a specific release, pin it explicitly:

bash
solana-install init <VERSION>

Point the CLI at the right cluster

For the currently published public Zink Testnet endpoint:

bash
solana config set --url https://testnet-rpc.z.ink
solana config get

For an unpublished or operator-only environment, use the URL provided during onboarding.

Generate validator keys

bash
mkdir -p ~/zink-validator
chmod 700 ~/zink-validator

solana-keygen new --outfile ~/zink-validator/identity.json
solana-keygen new --outfile ~/zink-validator/vote-account.json
solana-keygen new --outfile ~/zink-validator/withdrawer.json

Record the public keys you will share with the network team:

bash
solana-keygen pubkey ~/zink-validator/identity.json
solana-keygen pubkey ~/zink-validator/vote-account.json
solana-keygen pubkey ~/zink-validator/withdrawer.json

Zink recommendation

Treat the withdrawer key as the most sensitive key in this flow. Keep it under stronger custody than the validator host. Do not leave the withdrawer key on the validator machine.

Create or confirm the vote account

If onboarding expects you to create your own vote account, the standard command shape is:

bash
solana create-vote-account \
  ~/zink-validator/vote-account.json \
  ~/zink-validator/identity.json \
  ~/zink-validator/withdrawer.json

Then verify it:

bash
solana vote-account $(solana-keygen pubkey ~/zink-validator/vote-account.json)

If the vote account is operator-provided instead, do not improvise. Use the exact vote account and authority arrangement supplied during onboarding.

2. Prepare the validator host

Base OS and operator user

Use Ubuntu 22.04 or 24.04. Start with a clean, fully updated host.

bash
sudo apt update
sudo apt upgrade -y
sudo adduser sol

Running the validator as a dedicated non-root user keeps the setup boring in the best possible way.

Create mount points and log paths

bash
sudo mkdir -p /mnt/ledger /mnt/accounts /var/log/zink-validator /home/sol/bin /home/sol/zink-validator
sudo chown -R sol:sol /mnt/ledger /mnt/accounts /var/log/zink-validator /home/sol/bin /home/sol/zink-validator

Mount storage

Use separate high-performance NVMe devices for ledger and accounts. If you are formatting new disks, the shape is typically:

bash
# Example only — replace with your actual device names
sudo mkfs.ext4 /dev/nvme0n1
sudo mkfs.ext4 /dev/nvme1n1

sudo mount /dev/nvme0n1 /mnt/ledger
sudo mount /dev/nvme1n1 /mnt/accounts

Verify the layout:

bash
lsblk
df -h /mnt/ledger /mnt/accounts

Apply Linux tuning

Apply the tuning from System Requirements before first boot. At minimum, ensure:

  • vm.max_map_count = 1000000
  • fs.nr_open = 1000000
  • net.core.rmem_max = 134217728
  • net.core.wmem_max = 134217728
  • systemd LimitNOFILE and LimitMEMLOCK are raised

3. Copy only the keys the host actually needs

The validator host needs the identity key. It does not need the withdrawer key.

If you created the vote account already, the launch command can use the vote-account pubkey instead of storing the vote-account keypair on the host.

Example copy step:

bash
scp ~/zink-validator/identity.json sol@<server>:/home/sol/zink-validator/

If you still need the vote-account keypair on-box for your own workflow, copy it intentionally and remove it later once no longer needed.

4. Install Agave on the validator host

As the sol user:

bash
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"

solana --version
agave-validator --version

If Zink operator guidance specifies a particular release, pin that exact version here too.

5. Open ports and confirm reachability

At minimum, your validator needs its dynamic port range reachable.

Example UFW rules

bash
sudo ufw allow 8000:10000/tcp
sudo ufw allow 8000:10000/udp

If you intentionally expose RPC:

bash
sudo ufw allow 8899/tcp
sudo ufw allow 8900/tcp

Zink-specific

A node that starts cleanly but is not reachable on the configured dynamic port range will often fail the real goal: appearing in gossip and catching up. Port reachability is not a cosmetic check.

6. Create the validator launch script

Create /home/sol/bin/validator.sh:

bash
cat >/home/sol/bin/validator.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

exec /home/sol/.local/share/solana/install/active_release/bin/agave-validator \
  --identity /home/sol/zink-validator/identity.json \
  --vote-account <VOTE_ACCOUNT_PUBKEY> \
  --ledger /mnt/ledger \
  --accounts /mnt/accounts \
  --log /var/log/zink-validator/validator.log \
  --entrypoint <ZINK_ENTRYPOINT_1> \
  --entrypoint <ZINK_ENTRYPOINT_2> \
  --known-validator <KNOWN_VALIDATOR_PUBKEY_1> \
  --known-validator <KNOWN_VALIDATOR_PUBKEY_2> \
  --only-known-rpc \
  --expected-genesis-hash <ZINK_GENESIS_HASH> \
  --dynamic-port-range 8000-10000 \
  --wal-recovery-mode skip_any_corrupted_record \
  --limit-ledger-size
EOF

chmod +x /home/sol/bin/validator.sh

Important notes:

  • --vote-account can be the vote-account pubkey; it does not need to be a keypair file once the account exists.
  • Keep the real cluster values in this script or a sourced env file, not in a chat message or a scratchpad.
  • Add any extra cluster-specific flags supplied by the network team exactly as provided.
  • Do not reach for --no-port-check unless you have a very specific networking reason and understand the tradeoff.

Optional RPC flags

If the validator will also answer RPC for internal use, you may add:

bash
--rpc-port 8899 \
--private-rpc

For a pure consensus validator, keep RPC exposure minimal.

7. Run it once in the foreground

Before you daemonize it, do one clean foreground boot.

bash
sudo -iu sol /home/sol/bin/validator.sh

Look for the good early signs:

  • the process stays up
  • a snapshot begins loading or replay advances
  • there is no immediate genesis-hash or key mismatch failure
  • logs do not show repeated bind failures or panic loops

Stop the foreground run with Ctrl+C once you are satisfied it is basically healthy.

8. Create a systemd service

Create /etc/systemd/system/zink-validator.service:

ini
[Unit]
Description=Zink Validator
After=network-online.target
Wants=network-online.target

[Service]
User=sol
LimitNOFILE=1000000
LimitMEMLOCK=2000000000
Restart=always
RestartSec=3
ExecStart=/home/sol/bin/validator.sh

[Install]
WantedBy=multi-user.target

Then enable and start it:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now zink-validator

9. Verify the node after first boot

Process and logs

bash
pgrep -af agave-validator
journalctl -u zink-validator -f

Gossip visibility

bash
solana gossip | grep <IDENTITY_PUBKEY>

Validator-set visibility

bash
solana validators | grep <IDENTITY_PUBKEY>
solana validators | grep <VOTE_ACCOUNT_PUBKEY>

Catchup progress

bash
solana catchup <IDENTITY_PUBKEY>

Vote-account health

bash
solana vote-account <VOTE_ACCOUNT_PUBKEY>

Healthy early signs:

  • the node appears in gossip
  • solana catchup shows progress toward cluster head
  • the vote account resolves correctly
  • logs show snapshot load and replay rather than repeated crash loops

10. Final activation checklist for Zink Testnet

Before calling the node ready, confirm all of these are true:

  • the host is visible in solana gossip
  • catchup is converging instead of drifting away
  • the vote account is the expected one
  • the validator version matches the cluster guidance
  • the network team has confirmed the identity / vote account are admitted to the permissioned set
  • firewall rules match the actual --dynamic-port-range

If the node is healthy but not yet voting, the remaining blocker is usually onboarding state, not host prep.

Common first-join failures

  • Wrong cluster bundle — stale entrypoints, stale genesis hash, or wrong software version
  • Closed UDP/TCP ports — process is running, but the rest of the cluster cannot really talk to it
  • Underpowered storage — replay never catches up because ledger/accounts I/O is saturated
  • Vote-account mismatch — correct host, wrong vote account or wrong authorities
  • Key custody mistakes — identity missing on host, withdrawer accidentally copied to host, wrong file permissions
  • Clock drift — host time is bad, causing weird network behavior and misleading symptoms

Zink is a general-purpose SVM network for programs, operators, and bridge integrations.