How to Run a Solana Node? | Step-by-Step
Solana is a high-performance blockchain designed for speed and scale, processing thousands of transactions per second with low fees. Validators are the backbone of the network. They process transactions, participate in consensus, and help keep the network secure and decentralized.
This guide walks you through setting up and running a Solana validator node on testnet, from provisioning a server and generating keypairs to configuring the validator software and running it as a system service. By the end, your validator will be live on the network and actively participating in consensus.
#What is a Solana node?
A Solana node is a computer that validates transactions and blocks against the consensus rules implemented by the Solana protocol. A Solana node participates in the Solana blockchain network by storing a copy of the blockchain ledger.
#Solana validator vs. RPC nodes
There are two main types of nodes on the Solana network:
-
Validator nodes: participate in consensus by voting on blocks, processing transactions, and earning staking rewards. This guide covers this setup.
-
RPC nodes: act as API endpoints for applications and wallets to query blockchain data. They do not vote or earn rewards, but they support developers and dApps.
The hardware and configuration requirements differ. This guide focuses on setting up a validator node on testnet.
#How to become a Solana validator?
To become a Solana validator, you'll need powerful computing resources, fast processors, significant RAM, and SSD storage. Keep reading to see what exactly is required and the step-by-step process on how to run a Solana node.
#Solana node requirements & tools
This guide includes some hands-on demonstrations. Below are the key hardware and software requirements for running a Solana node:
Server Hardware Specification
-
CPU: 12 cores/24 threads or more, with a base clock speed of 2.8GHz or faster. It should support SHA extensions and AVX2 instructions (AVX512f support is helpful). Recommended processors include AMD Gen 3 or newer and Intel Ice Lake or newer.
-
RAM: 256GB or more. ECC memory is suggested, and a motherboard with 512GB capacity is recommended for future scalability.
-
Disk:
-
OS (Optional): 500GB or larger NVMe SSD (SATA OK).
-
Accounts: 500GB or larger PCIe Gen3 x4 NVMe SSD (or better) with high TBW.
-
Ledger: 1TB or larger PCIe Gen3 x4 NVMe SSD (or better) with high TBW.
-
Storing accounts and ledger on separate disks is recommended for better performance due to high IOPS. Popular choices include Samsung 970 and 980 Pro series SSDs.
-
-
Network: A stable internet connection with at least 1 Gbps upload and download speed and unmetered bandwidth.
Software Requirements
-
Operating System: Ubuntu 22.04 or 24.04 (24.04 recommended)
-
Solana Software: Ensure the latest version of the official Solana software is installed. Check the documentation for the latest version.
-
Firewall: Configure your firewall to allow incoming and outgoing connections on ports 8000-10000 TCP/UDP (P2P communication).
For this demonstration, an AMD Blockchain server from Cherry Servers was used. For other cloud platforms, select server types with similar specs as mentioned in the server hardware specification section above.
Set up your Solana server in minutes
Optimize cost and performance with a pre-configured or custom dedicated bare metal server for blockchain workloads. High uptime, instant 24/7 support, pay in crypto.
#How to run a Solana node: Step-by-step process
The following steps will walk you through setting up a Solana validator node, making the process straightforward and easy to follow. These are written instructions; alternatively, a video guide is available below.
#Step 1: Open the terminal program
To begin, you will be running commands on your local computer, not on the remote machine you plan to use for validator operations. First, open the terminal on your system. On Ubuntu, press CTRL + Alt + T to launch it.
#Step 2: Install Solana CLI locally
To create your validator vote account, you need to install the Solana command-line interface on your local computer.
There are multiple ways to install the Solana command-line interface, as documented, but for this installation, you will use the install tool. Check the Agave GitHub releases page for the latest version and substitute it in the command below if it differs:
sh -c "$(curl -sSfL https://release.anza.xyz/v3.1.12/install)"
You should get a similar output if the installation was successful:
Outputdownloading v3.1.12 installer
✨ 3.1.12 initialized
Adding
export PATH="/home/user/.local/share/solana/install/active_release/bin:$PATH" to /home/user/.profile
Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:
export PATH="/home/user/.local/share/solana/install/active_release/bin:$PATH"
Run the following command to apply the PATH changes to your current session:
export PATH="/home/user/.local/share/solana/install/active_release/bin:$PATH"
Confirm the installation:
solana --version
Outputsolana-cli 3.1.12 (src:6c1ba346; feat:4140108451, client:Agave)
Once you have successfully installed the CLI, the next step is to change the Solana CLI configuration so that it is making requests to the testnet cluster:
solana config set --url https://api.testnet.solana.com
OutputConfig File: /home/user/.config/solana/cli/config.yml
RPC URL: https://api.testnet.solana.com
WebSocket URL: wss://api.testnet.solana.com/ (computed)
Keypair Path: ./validator-keypair.json
Commitment: confirmed
#Step 3: Create keys
Validators require three keypairs to operate. Before creating them, it's important to understand what each one is for:
-
Validator identity keypair: identifies your node on the network and is used to sign transactions.
-
Vote account keypair: used to participate in consensus and collect rewards.
-
Authorized withdrawer keypair: controls the ability to withdraw funds from the vote account.
Run the following commands to generate the three keypairs:
solana-keygen new -o validator-keypair.json
solana-keygen new -o vote-account-keypair.json
solana-keygen new -o authorized-withdrawer-keypair.json
Each command will prompt you for an optional BIP39 passphrase and then generate a keypair saved to the corresponding JSON file. The output will look similar to this:
OutputGenerating a new keypair
For added security, enter a BIP39 passphrase
NOTE! This passphrase improves security of the recovery seed phrase NOT the
keypair file itself, which is stored as insecure plain text
BIP39 Passphrase (empty for none):
Wrote new keypair to validator-keypair.json
=============================================================================
pubkey: HXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1
=============================================================================
Save this seed phrase and your BIP39 passphrase to recover your new keypair:
laptop slush book system retreat cause impulse prepare put boil vessel unique
=============================================================================
Some operators choose to make vanity keypairs for their identity and their vote account using the solana-keygen grind subcommand.
#Step 4: Create a vote account
Before you can create your vote account, you need to configure the Solana command line tool to use the validator keypair. The command below sets the validator keypair you just created as the default in the Solana configuration, allowing subsequent commands to use it for signing and authentication.
solana config set --keypair ./validator-keypair.json
OutputConfig File: /home/user/.config/solana/cli/config.yml
RPC URL: https://api.testnet.solana.com
WebSocket URL: wss://api.testnet.solana.com/ (computed)
Keypair Path: ./validator-keypair.json
Commitment: confirmed
Verify your account balance, which should be 0 at this point:
solana balance
Output0 SOL
You need SOL in your validator identity account to pay for the transaction that creates your vote account. Request an airdrop:
solana airdrop 1
If you hit the rate limit:
OutputError: airdrop request failed. This can happen when the rate limit is reached.
You can request SOL manually from the Solana faucet. Get your wallet address by running:
solana address
OutputHXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1
Enter your address on the faucet, select Testnet, enter the amount you need, and click Confirm Airdrop. Note that you will need a GitHub account to use the faucet.
Once your account is funded, create your vote account:
solana create-vote-account -ut \
--fee-payer ./validator-keypair.json \
./vote-account-keypair.json \
./validator-keypair.json \
./authorized-withdrawer-keypair.json
OutputSignature: 1yzT28WcGXHVF8nWd8YQV9JQkoy4rFrhvYoRtk2dsDGRCm57QPsKgcLGzYZ4bosdoHs6Xc1V8wCViJd6BU39NXF
This confirms that your vote account has been successfully created on the testnet cluster.
#Step 5: Create a server
Next, you need to set up your server on your preferred cloud platform with the required hardware specifications mentioned in the guide. As mentioned earlier, a Solana Testnet server from Cherry Servers was used here. You also need to partition the data storage into two distinct areas:
-
Ledger Partition: The ledger stores blockchain data, including transaction history and blocks. This partition handles sequential write operations.
-
Account Partition: The account partition stores user balances and program data, representing the current network state.
Separating these partitions optimizes validator performance.
#Step 6: SSH to your validator
Next, SSH into your server using the appropriate command for your server provider. This will allow you to access and configure the validator remotely. The command should be in this format:
ssh user@<server.hostname>
OutputThe authenticity of host '5.199.172.207 (5.199.172.207)' can't be established.
ED25519 key fingerprint is SHA256:YxR2cQD6C/68LVbuiJdK/RUYQe1F+JR0z0O2t/ajwss.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '5.199.172.207' (ED25519) to the list of known hosts.
root@5.199.172.207's password:
Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.14.0-37-generic x86_64)
127 updates can be applied immediately.
#Step 7: Update your Ubuntu packages
Now that you have access to the server, run the following command to update the system packages:
sudo apt update && sudo apt upgrade -y
OutputHit:1 http://repo.cherryservers.com/ubuntu noble InRelease
Hit:2 http://repo.cherryservers.com/ubuntu noble-updates InRelease
Hit:3 http://repo.cherryservers.com/ubuntu noble-backports InRelease
Hit:4 http://repo.cherryservers.com/ubuntu noble-security InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
120 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
120 upgraded, 7 newly installed, 0 to remove and 0 not upgraded.
83 standard LTS security updates
Need to get 876 MB of archives.
After this operation, 326 MB of additional disk space will be used.
Fetched 876 MB in 4s (213 MB/s)
Extracting templates from packages: 100%
Preconfiguring packages ...
...
Setting up systemd (255.4-1ubuntu8.14) ...
Setting up openssh-server (1:9.6p1-3ubuntu13.15) ...
Setting up linux-image-6.8.0-106-generic ...
...
Processing triggers for libc-bin ...
#Step 8: Enable firewall
Next, create and enable a firewall on your server to allow traffic on the required ports. These rules are based on the minimum necessary to operate a validator on testnet. Update the port ranges if you are running on a different cluster.
sudo ufw allow "OpenSSH"
sudo ufw allow 8000:10000/udp
sudo ufw allow 8000:10000/tcp
sudo ufw enable
When prompted, type y and press Enter. You should see output similar to this:
OutputFirewall is active and enabled on system startup
Confirm your firewall rules using:
sudo ufw status
OutputStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
8000:10000/udp ALLOW Anywhere
8000:10000/tcp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
8000:10000/udp (v6) ALLOW Anywhere (v6)
8000:10000/tcp (v6) ALLOW Anywhere (v6)
#Step 9: Add a new user
Now, create a dedicated user account on your server that will run the validator service:
sudo adduser sol
sudo usermod -aG sudo sol
You will be prompted to set a password and fill in optional user information. Press Enter to skip the optional fields. You should see a confirmation at the end:
Outputinfo: Adding user sol' ...
info: Selecting UID/GID from range 1000 to 59999 ...
info: Adding new group sol' (1001) ...
info: Adding new user sol' (1001) with group sol (1001)' ...
info: Creating home directory /home/sol' ...
info: Copying files from /etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for sol
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] Y
info: Adding new user sol' to supplemental / extra groups users' ...
info: Adding user sol' to group users' ...
#Step 10: Format and mount storage drives for ledger and accounts
Next, make sure you have at least 2TB of disk space available. Check your current disk space:
df -h
OutputFilesystem Size Used Avail Use% Mounted on
tmpfs 38G 18M 38G 1% /run
efivarfs 256K 114K 138K 46% /sys/firmware/efi/efivars
/dev/md0 879G 12G 823G 2% /
tmpfs 189G 0 189G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/nvme0n1p1 488M 6.2M 481M 2% /boot/efi
/dev/nvme1n1p1 488M 6.2M 481M 2% /boot/efi/ubuntu2
tmpfs 38G 12K 38G 1% /run/user/
To see all available block devices and their format status:
lsblk -f
OutputNAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
nvme2n1
nvme3n1
nvme0n1
├─nvme0n1p1 vfat FAT32 uefi-boot 22D9-DAC7 480.9M 1% /boot/efi
└─nvme0n1p2 linux_raid_member 1.2 8172:0 a8ba5b4b-e3d8-9802-1cf0-379f8cecdf4c
└─md0 ext4 1.0 881e3a42-dc5a-4d0a-8227-8b38981b0981 822.3G 1% /
nvme1n1
├─nvme1n1p1 vfat FAT32 22DE-659D 480.9M 1% /boot/efi/ubuntu2
└─nvme1n1p2 linux_raid_member 1.2 8172:0 a8ba5b4b-e3d8-9802-1cf0-379f8cecdf4c
└─md0 ext4 1.0 881e3a42-dc5a-4d0a-8227-8b38981b0981 822.3G 1% /
Any device listed without a Universally Unique Identifier (UUID) or filesystem is usually unformatted and needs to be set up before use.
Format the drives:
Format the drives that will be used for the ledger and accounts partitions. Your device names may differ, so carefully verify device names before proceeding. Selecting the wrong disk can result in permanent data loss. In this demonstration, nvme2n1 is used for the ledger and nvme3n1 for accounts:
sudo mkfs -t ext4 /dev/nvme2n1
sudo mkfs -t ext4 /dev/nvme3n1
Formatting a disk will permanently erase all data on the device.
Outputmke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 937684566 4k blocks and 234422272 inodes
Filesystem UUID: 6fd9ef9b-7945-4212-94ff-40f312805445
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
After formatting, confirm both drives now have UUIDs and filesystems:
lsblk -f
OutputNAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
nvme2n1 ext4 1.0 6fd9ef9b-7945-4212-94ff-40f312805445
nvme3n1 ext4 1.0 d1caf75c-c684-4a4a-ac09-a203dd5ad449
nvme0n1
├─nvme0n1p1 vfat FAT32 uefi-boot 22D9-DAC7 480.9M 1% /boot/efi
└─nvme0n1p2 linux_raid_member 1.2 8172:0 a8ba5b4b-e3d8-9802-1cf0-379f8cecdf4c
└─md0 ext4 1.0 881e3a42-dc5a-4d0a-8227-8b38981b0981 822.3G 1% /
nvme1n1
├─nvme1n1p1 vfat FAT32 22DE-659D 480.9M 1% /boot/efi/ubuntu2
└─nvme1n1p2 linux_raid_member 1.2 8172:0 a8ba5b4b-e3d8-9802-1cf0-379f8cecdf4c
└─md0 ext4 1.0 881e3a42-dc5a-4d0a-8227-8b38981b0981 822.3G 1% /
Now that the drives are formatted, create the mount point directories:
sudo mkdir -p /mnt/ledger
sudo mkdir -p /mnt/accounts
Mount the drives:
sudo mount /dev/nvme2n1 /mnt/ledger
sudo mount /dev/nvme3n1 /mnt/accounts
Then assign ownership of the mounted directories to the sol user:
sudo chown -R sol:sol /mnt/ledger
sudo chown -R sol:sol /mnt/accounts
These mounts will not survive a server reboot unless added to /etc/fstab. First, note the UUIDs from the lsblk -f output above, then open the fstab file:
sudo nano /etc/fstab
Add the following lines at the end, replacing the UUIDs with your own:
UUID=6fd9ef9b-7945-4212-94ff-40f312805445 /mnt/ledger ext4 defaults 0 2
UUID=d1caf75c-c684-4a4a-ac09-a203dd5ad449 /mnt/accounts ext4 defaults 0 2
Be careful when editing /etc/fstab. Incorrect entries can prevent your system from booting.
Verify the configuration:
sudo mount -a
If no errors are returned, the configuration is correct.
#Step 11: System tuning
To ensure proper validator performance, you need to optimize the system by adjusting kernel parameters and increasing file descriptor limits.
Optimize sysctl knobs:
sudo bash -c "cat >/etc/sysctl.d/21-agave-validator.conf <<EOF
# Increase max UDP buffer sizes
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
# Increase memory mapped files limit
vm.max_map_count = 1000000
# Increase number of allowed open file descriptors
fs.nr_open = 1000000
EOF"
Apply the changes:
sudo sysctl -p /etc/sysctl.d/21-agave-validator.conf
Outputnet.core.rmem_max = 134217728
net.core.wmem_max = 134217728
vm.max_map_count = 1000000
fs.nr_open = 1000000
Increase systemd file limits:
Open the systemd configuration file with the Nano text editor:
sudo nano /etc/systemd/system.conf
Find the [Manager] section and add or update the following parameters, then save and exit:
DefaultLimitNOFILE=1000000
DefaultLimitMEMLOCK=2000000000
Reload systemd to apply the change using:
sudo systemctl daemon-reload
Set session file limits:
sudo bash -c "cat >/etc/security/limits.d/90-solana-nofiles.conf <<EOF
# Increase process file descriptor count limit
* - nofile 1000000
# Increase memory locked limit (kB)
* - memlock 2000000
EOF"
Once all changes are applied, log out and back in for the session limits to take effect:
exit
#Step 12: Copy keypairs
Now, from your local computer, navigate to the directory where your keypairs are stored and copy them to the server using scp:
scp -C vote-account-keypair.json user@<server.hostname>:/home/sol
scp -C validator-keypair.json user@<server.hostname>:/home/sol
Replace user@<server.hostname> with sol and your server's hostname or IP address.
authorized-withdrawer-keypair.json to the server. This keypair should be kept offline in a secure location and only used when withdrawing funds from the vote account.After copying the keypairs, run these commands on the remote server to change their ownership to the sol user:
sudo chown sol:sol /home/sol/validator-keypair.json
sudo chown sol:sol /home/sol/vote-account-keypair.json
#Step 13: Switch to the sol user
On the validator server, switch to the sol user using:
su - sol
#Step 14: Install Solana CLI/Agave-validator on the remote machine
You will need to install the Solana CLI on the remote server to run the validator software. You will be building the Solana CLI from source on the remote server. Start by installing Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
When prompted, press Enter to proceed with the standard installation. Once complete, you should see:
Outputinfo: downloading installer
warn: It looks like you have an existing rustup settings file at:
warn: /home/sol/.rustup/settings.toml
Welcome to Rust!
1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>1
info: default toolchain set to stable-x86_64-unknown-linux-gnu
stable-x86_64-unknown-linux-gnu installed - rustc 1.94.1
Rust is installed now. Great!
To use Rust in the current shell, run:
. "$HOME/.cargo/env"
warn: no default linker (`cc`) was found in your PATH
After Rust installs successfully, run the following to update your current shell session:
. "$HOME/.cargo/env"
Then install build dependencies:
sudo apt-get update && sudo apt-get install build-essential pkg-config libudev-dev llvm libclang-dev protobuf-compiler
OutputHit:1 http://repo.cherryservers.com/ubuntu noble InRelease
Hit:2 http://repo.cherryservers.com/ubuntu noble-updates InRelease
Hit:3 http://repo.cherryservers.com/ubuntu noble-backports InRelease
Hit:4 http://repo.cherryservers.com/ubuntu noble-security InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
build-essential gcc g++ make
0 upgraded, 83 newly installed, 0 to remove and 0 not upgraded.
Need to get 201 MB of archives.
After this operation, 1,158 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Fetched 201 MB in 7s (28.3 MB/s)
Selecting previously unselected package build-essential.
Preparing to unpack .../build-essential_12.10ubuntu1_amd64.deb ...
Unpacking build-essential (12.10ubuntu1) ...
Setting up make (4.3-4.1build2) ...
Setting up gcc (4:13.2.0-7ubuntu1) ...
Setting up g++ (4:13.2.0-7ubuntu1) ...
Setting up build-essential (12.10ubuntu1) ...
Next, download and extract the source code. Check the Agave GitHub releases page for the latest version and substitute it in the commands below if it differs:
curl -L https://github.com/anza-xyz/agave/archive/refs/tags/v3.1.12.tar.gz -o agave-v3.1.12.tar.gz
tar -xzvf agave-v3.1.12.tar.gz
cd agave-3.1.12
Build the binaries:
./scripts/cargo-install-all.sh .
OutputOSTYPE IS: linux-gnu Install location: /home/sol/agave-3.1.12 (release) Building binaries for all platforms: cargo-build-sbf cargo-test-sbf solana-test-validator agave-install solana solana-keygen solana-stake-accounts solana-tokens agave-install-init Building binaries for linux and osx only: agave-validator agave-watchtower solana-gossip solana-genesis solana-faucet agave-ledger-tool
info: syncing channel updates for 1.86.0-x86_64-unknown-linux-gnu
info: latest update on 2025-04-03 for version 1.86.0
info: downloading 6 components
Updating git repository https://github.com/anza-xyz/crossbeam
Updating crates.io index
Downloaded 809 crates (79.8 MB) in 3.49s (largest was openssl-src at 9.8 MB)
Compiling proc-macro2 v1.0.101
Compiling quote v1.0.41
Compiling unicode-ident v1.0.14
Compiling libc v0.2.177
...
Compiling solana-sanitize v3.0.1
Compiling semver v1.0.27
Compiling memchr v2.6.3
Compiling solana-define-syscall v3.0.0
This will take some time to complete. Once finished, make the binaries permanently available in your PATH:
echo 'export PATH="/home/sol/agave-3.1.12/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Confirm the installation:
solana --version
Outputsolana-cli 3.1.12 (src:a78b7a97; feat:4140108451, client:Agave)
agave-validator --version
Outputagave-validator 3.1.12 (src:fdf791c5; feat:4140108451, client:Agave)
Then configure the Solana CLI to connect to testnet:
solana config set --url https://api.testnet.solana.com
OutputConfig File: /home/sol/.config/solana/cli/config.yml
RPC URL: https://api.testnet.solana.com
WebSocket URL: wss://api.testnet.solana.com/ (computed)
Keypair Path: /home/sol/.config/solana/id.json
Commitment: confirmed
#Step 15: Create a validator startup script
Now create a startup script for your validator in the sol user's bin directory:
mkdir -p /home/sol/bin
touch /home/sol/bin/validator.sh
chmod +x /home/sol/bin/validator.sh
The commands above will create a validator.sh file in the bin directory and also make it executable.
Next, using the nano editor, open the validator.sh file:
nano /home/sol/bin/validator.sh
Paste in the following contents, then save and exit:
#!/bin/bash
exec agave-validator \
--identity /home/sol/validator-keypair.json \
--vote-account /home/sol/vote-account-keypair.json \
--known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on \
--known-validator 7XSY3MrYnK8vq693Rju17bbPkCN3Z7KvvfvJx4kdrsSY \
--known-validator Ft5fbkqNa76vnsjYNwjDZUXoTWpP7VYm3mtsaQckQADN \
--known-validator 9QxCLckBiJc783jnMvXZubK4wH86Eqqvashtrwvcsgkv \
--only-known-rpc \
--log /home/sol/agave-validator.log \
--ledger /mnt/ledger \
--accounts /mnt/accounts \
--rpc-port 8899 \
--dynamic-port-range 8000-8025 \
--entrypoint entrypoint.testnet.solana.com:8001 \
--entrypoint entrypoint2.testnet.solana.com:8001 \
--entrypoint entrypoint3.testnet.solana.com:8001 \
--expected-genesis-hash 4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY \
--wal-recovery-mode skip_any_corrupted_record \
--limit-ledger-size
You can run the agave-validator --help command for more information on what each flag is doing in this script. You can also refer to the section on best practices for operating a validator in the official Solana documentation.
#Step 16: Verifying your validator is working
Now run the startup script to start the validator:
/home/sol/bin/validator.sh
Outputlog file: /home/sol/agave-validator.log
In a separate terminal window, SSH into the remote server as the sol user and confirm the validator process is running:
ps aux | grep agave-validator
You should see a line showing agave-validator running under the sol user with all the flags from your startup script. The high CPU usage and Sl+ status code at this stage are normal; they indicate the validator is actively initializing.
Outputsol 188544 75.5 0.1 2131232 494836 pts/0 Sl+ 02:25 2:10 agave-validator --identity /home/sol/validator-keypair.json --vote-account /home/sol/vote-account-keypair.json --known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on --known-validator 7XSY3MrYnK8vq693Rju17bbPkCN3Z7KvvfvJx4kdrsSY --known-validator Ft5fbkqNa76vnsjYNwjDZUXoTWpP7VYm3mtsaQckQADN --known-validator 9QxCLckBiJc783jnMvXZubK4wH86Eqqvashtrwvcsgkv --only-known-rpc --log /home/sol/agave-validator.log --ledger /mnt/ledger --accounts /mnt/accounts --rpc-port 8899 --dynamic-port-range 8000-8025 --entrypoint entrypoint.testnet.solana.com:8001 --entrypoint entrypoint2.testnet.solana.com:8001 --entrypoint entrypoint3.testnet.solana.com:8001 --expected-genesis-hash 4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY --wal-recovery-mode skip_any_corrupted_record --limit-ledger-size
sol 188972 0.0 0.0 6676 2460 pts/1 S+ 02:28 0:00 grep --color=auto agave-validator
Monitor the logs to check for errors:
tail -f agave-validator.log
Watch for any lines containing ERROR. If none appear after a few minutes, the validator is starting up cleanly.
Output[2026-04-09T02:31:58.605597364Z INFO solana_file_download] downloaded 4579090432 bytes 90.4% 15609672.0 bytes/s
[2026-04-09T02:32:04.848557683Z INFO solana_file_download] downloaded 4674658304 bytes 92.3% 15308103.0 bytes/s
[2026-04-09T02:32:11.091361571Z INFO solana_file_download] downloaded 4770913760 bytes 94.2% 15418631.0 bytes/s
[2026-04-09T02:32:17.319114276Z INFO solana_file_download] downloaded 4866867200 bytes 96.1% 15407392.0 bytes/s
[2026-04-09T02:32:23.547087983Z INFO solana_file_download] downloaded 4962500608 bytes 97.9% 15355466.0 bytes/s
[2026-04-09T02:32:29.775206797Z INFO solana_file_download] downloaded 5057912832 bytes 99.8% 15319588.0 bytes/s
[2026-04-09T02:32:30.297258749Z INFO solana_file_download] ✨ Downloaded http://109.94.99.177:8899/snapshot-400531073-HVDGQT985AnBEnnY7Q3rSmnPcjxjSuR1gTp8uqfWvUWt.tar.zst (5066949798 bytes) in 331.268475855s
[2026-04-09T02:32:30.299058484Z INFO solana_runtime::snapshot_utils] Purging old full snapshot archives in /mnt/ledger, retaining up to 2 full snapshots
[2026-04-09T02:32:30.299182159Z INFO solana_runtime::snapshot_utils] Purging old incremental snapshot archives in /mnt/ledger, retaining up to 4 incremental snapshots
[2026-04-09T02:32:30.822735760Z INFO solana_download_utils]
.....
RPC Address |Age(ms)| Node identifier | Version | RPC |PubSub|ShredVer
------------------+-------+----------------------------------------------+---------+------+------+--------
173.231.16.186 | 328 | kormosBFDEYL9z5S59aXW3tdWG54912QiniP98G1Vad |4.0.0-beta.4| 8899 | 8900 | 27350
38.92.24.102 | 328 | chopdD4fCw5cjsn9mfavcEY8T6D3m4ML8bzZHhRgF1L |4.0.0-beta.4| 8899 | 8900 | 27350
207.188.7.155 | 833 | CJWCVTRhnvCX8u4tP8cfnD3Hb9VmPUNeQ7obizTQ9N5g |4.0.0-beta.4| 8899 | 8900 | 27350
185.155.17.90 | 2004 |
......
Next, verify that your validator is running correctly by checking if it has registered itself with the Gossip network. First, get your validator's public key:
solana-keygen pubkey ~/validator-keypair.json
OutputHXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1
Then confirm it has registered on the gossip network:
solana gossip | grep <your-validator-identity-pubkey>
Replace <your-validator-identity-pubkey> with the public key of the validator node extracted earlier. If the validator has been registered on the Gossip network, you should get an output similar to the one below:
Output5.199.172.207 | HXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1 | 8000 | none | 8009 | 5.199.172.207:8899 | 3.1.12 | 4140108451
With the validator in the Gossip network, you can also confirm that the validator has joined the network using the following command:
solana validators | grep <your-validator-identity-pubkey>
You should get an output as the one below if it has joined the network:
OutputHXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1 AQukXXqRR7umYXunLdx6zn9cb5h2vZGu79MLd9ucRqri 100% 400543073 (-61) 400543042 (-57) - 3319 3.1.12 0.000000000 SOL (0.00%)
You can also see how quickly your validator is processing blocks using the solana catchup command:
solana catchup <your-validator-identity-pubkey>
OutputHXTSNm9Wq933VCjVRB563uffDgASw7Ny5JhwZfad5Mh1 has caught up (us:400543609 them:400543609)
#Step 17: Create a system service
Running the validator as a systemd service ensures it runs in the background and automatically restarts if it crashes or if the server reboots.
Before setting up the system service, stop the manually running validator:
kill $(pgrep agave-validator)
Next, create the systemd unit file:
sudo nano /etc/systemd/system/sol.service
Paste in the following:
[Unit]
Description=Solana Validator
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=sol
LimitNOFILE=1000000
LimitMEMLOCK=2000000000
LogRateLimitIntervalSec=0
Environment="PATH=/home/sol/agave-3.1.12/bin:/usr/bin:/bin"
ExecStart=/home/sol/bin/validator.sh
[Install]
WantedBy=multi-user.target
If you installed a different version, update the version number in the PATH accordingly. For example, replace agave-3.1.12 with your installed version.
Then enable and start the service:
sudo systemctl enable --now sol
OutputCreated symlink /etc/systemd/system/multi-user.target.wants/sol.service → /etc/systemd/system/sol.service.
Verify the validator is running by tailing the logs:
tail -f /home/sol/agave-validator.log
Then confirm it is visible on the network:
solana gossip | grep <your-validator-identity-pubkey>
solana validators | grep <your-validator-identity-pubkey>
#Step 18: Configure log rotation
Validator log files grow very quickly and will fill up your disk without log rotation. Run the following to set it up:
cat > logrotate.sol <<EOF
/home/sol/agave-validator.log {
rotate 7
daily
missingok
postrotate
systemctl kill -s USR1 sol.service
endscript
}
EOF
sudo cp logrotate.sol /etc/logrotate.d/sol
sudo systemctl restart logrotate.service
This will rotate the log file daily and keep the last 7 days of logs.
#Conclusion
In this guide, you set up a Solana validator node on testnet from scratch. Provisioning a server, configuring storage, installing the validator software, and running it as a production systemd service. Your validator is now live on the network, participating in consensus and processing transactions.
From here, you can explore staking, monitor your validator's performance, and work toward running on mainnet. The Solana documentation and validator community are good resources as you continue operating and optimizing your node.
High egress costs and lost transactions?
Switch to blockchain-optimized dedicated bare metal—save up to 60% on your cloud bill and double the performance compared to hyperscale cloud.