How to deploy a Solana RPC Node

Antematter
8 min readNov 2, 2022

--

There are two ways to become a citizen of the Solana network.

  • Spin up a Validator
  • Spin up an RPC Node

If you’re the nerdy type and know the difference already, skip ahead 🙂. But for others, let’s dive a bit deeper.

Validator vs. RPC Node

If thou must vote, thou must be a Validator.

Validators are the workhorses of the network, maintaining the chain’s state, validating the submitted transactions and producing blocks when their turn arrives.

In essence, they get to vote i.e. participate in the consensus process. A validator’s voting share depends on the amount of tokens staked to it. When chosen as a leader, it also furnishes blocks for the network and it’s stakeholders are rewarded for it. Handsomely, might I add 😉.

An RPC Node executes the same program as a Validator but it does NOT participate in the consensus process. Instead, developers and applications use it to access and interact with the chain.

Technically, one could spin up a validator which also functions as an RPC Node, but this is strongly discouraged due to performance reasons. Greed never works.

How to run an RPC Node

While this tutorial expounds upon the process of deploying an RPC Node, deploying a Validator is almost similar. I will drop cues along the way if you want to run a Validator instead.

Prerequisites

You should be wealthy enough to have access to the following.

  • CPU
    - 12 Cores / 32 Threads or more, with each core being 2.8GHz+
    - AVX2 instruction support (unless you’re compiling solana from source)
  • RAM
    - 128GB or more
    - 256GB or more if you want to enable account indices for a fully performant RPC API
  • Disk
    -
    2x 1TB NVMe SSD or better
    - One to store the accounts data
    - One to store the ledger data
    - 1x 256GB NVMe SSD or better (to host the OS)
    - Technically, 1x 2TB NVMe SSD can work but highly discouraged
  • Networking
    -
    Access to at least 300Mbit/s symmetric but 1Gbit/s+ is preferred
  • Operating System
    -
    Ubuntu 20.04
    - You may use any other linux based OS too and modify the instructions accordingly

For a comprehensive list, you may give this a read. Otherwise, let’s just yolo it.

1. Understanding the disks

First off, let’s SSH as root into the machine that’s going to run the node. Or if it’s your local desktop, then just power up a bash session and sudo su.

Let’s run lsblk and understand the output. Here’s a sample.

NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 63.2M 1 loop /snap/core20/1623
loop1 7:1 0 67.8M 1 loop /snap/lxd/22753
loop2 7:2 0 48M 1 loop /snap/snapd/17336
loop3 7:3 0 48M 1 loop /snap/snapd/16778
nvme2n1 259:0 0 3.5T 0 disk
└─nvme2n1p1 259:3 0 3.5T 0 part
nvme1n1 259:1 0 3.5T 0 disk
└─nvme1n1p1 259:4 0 3.5T 0 part
nvme0n1 259:2 0 238.5G 0 disk
├─nvme0n1p1 259:5 0 1M 0 part
└─nvme0n1p2 259:6 0 238.5G 0 part /
  • nvme0n1 hosts the Operating System. We don’t care about it. It’s not worth our attention.
  • nvme1n1 will be used to store the ledger data. It has one partition nvme1n1p1.
  • nvme2n1 will be used to store the accounts data. It also has one partition nvme2n1p1 spanning the entire disk.

You may use the parted tool to create partitions on your disks if they’re not already present.

💡 Both nvme1n1p1 and nvme2n1p1 have been formatted using xfs. You may also use ext4.

Oh and while we’re at this step, do yourself a favor and run apt update -y && apt upgrade -y.

2. Mounting the disks

We need to create the appropriate data directories and mount the two disks mentioned above.

As alluded to earlier, we will use /var/solana/data for the ledger and /var/solana/accounts for the accounts data.

root@antematter:~# mkdir /var/solana
root@antematter:~# mkdir /var/solana/data /var/solana/accounts
root@antematter:~# mount /dev/nvme1n1p1 /var/solana/data
root@antematter:~# mount /dev/nvme2n1p1 /var/solana/accounts

You may also edit the /etc/fstab file to always mount the disks on startup.

3. Creating a user

It is recommended to create another user to run the RPC node as. Shouldn’t be much hassle.

root@antematter:~# adduser solana
root@antematter:~# chown solana:solana /var/solana/data
root@antematter:~# chown solana:solana /var/solana/accounts

We’re also making solana the owner of both the data directories.

4. Installing the Solana binaries

Let’s make sure to switch to the newly created solana user first.

root@antematter:~# su - solana

And now let’s just curl the script which sets up the binaries. Easy peasy.

solana@antematter:~# sh -c "$(curl -sSfL <https://release.solana.com/stable/install>)"

Make sure to append the following to your .profile for solana if it’s not already there.

export PATH="/home/solana/.local/share/solana/install/active_release/bin:$PATH"

To verify if the CLI tools have been installed, run solana --version. For me, it is

solana@antematter:~# solana --version
solana-cli 1.13.5 (src:9382e90c; feat:4011803773)

5. Creating the Validator Keypair

Each Validator (or an RPC Node) is identified on the network with a keypair. So let’s create one for our own RPC Node.

solana@antematter:~# solana-keygen new -o /var/solana/data/config/validator-keypair.json

We do not need to deposit any SOL to this account since we’re not running a validator. If you were, however, trying to run a validator, not only will you need to fund this account, you will need two more keypairs and initialize a vote account. Refer here.

6. Running the system tuner

Solana is a wild beast and as such your system needs to be tuned for it to function performantly.

There are two ways to do this: manual & automatic. Let’s opt for the manual one, create config files with thousands of overwhelming entries using vi and committing them using sysctl.

NO! That’s torture. Let’s just run the automatic tuner.

solana@antematter:~# sudo $(command -v solana-sys-tuner) --user sol > sys-tuner.log 2>&1

You will obviously need solana to be a sudoer. Switch to root and run adduser solana sudo.

7. Creating a startup script

Just about there! Let’s create a startup script so we can easily craft a systemd service around it.

Switch back to the solana user and cd into the home directory. Then let’s run the following commands

solana@antematter:~# mkdir /home/solana/bin && cd /home/solana/bin
solana@antematter:~/bin# touch validator.sh

Now we just need to put the following script inside the validator.sh file we just created.

#!/bin/bashset -e
set -u
export RUST_LOG=errorsolana-validator \
--ledger /var/solana/data/ledger \
--accounts /var/solana/accounts \
--identity /var/solana/data/config/validator-keypair.json \
--known-validator 7Np41oeYqPefeNQEHSv1UDhYrehxin3NStELsSKCT4K2 \
--known-validator GdnSyH3YtwcxFvQrVVJMm1JhTS4QVX7MFsX56uJLUfiZ \
--known-validator DE1bawNcRJB9rVm3buyMVfr8mBEoyyu73NBovf2oXJsJ \
--known-validator CakcnaRDHka2gXyfbEd2d3xsvkJkqsLw2akB3zsN1D2S \
--expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint2.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint3.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint4.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint5.mainnet-beta.solana.com:8001 \
--rpc-port 8899 \
--dynamic-port-range 8000-8020 \
--wal-recovery-mode skip_any_corrupted_record \
--init-complete-file /var/solana/data/init-completed \
--limit-ledger-size 50000000 \
--log - \
--only-known-rpc \
--full-rpc-api \
--no-voting \
--enable-rpc-transaction-history \
--enable-cpi-and-log-storage

Here’s a brief explanation of the non self-explanatory and important flags.

  • --known-validator points to a validator on the network you trust. These validators will be used to fetch the network’s snapshot.
  • --rpc-port specifies the port where the RPC server will be listening.
  • --limit-ledger-size specifies the amount of shreds in root slots. This is useful for limiting disk usage.
  • --full-rpc-api exposes RPC methods for querying the chain’s state.
  • --no-voting tells the validator to not participate in the consensus process i.e. spin up as an RPC node.
  • --enable-rpc-transaction-history will enable historical transaction information over the RPC server but will consume more disk.

💡 You may use the --rpc-bind-address flag to bind the RPC server to a specific address such as 127.0.0.1.

To run a Validator instead of an RPC Node, you can remove the following flags

  • --no-voting
  • --full-rpc-api
  • --enable-rpc-transaction-history
  • --enable-cpi-and-log-storage
  • Lastly, provide the voting keypair using the --vote-account flag.

Oh and we should not forget this little thing.

solana@antematter:~bin# chmod +x validator.sh

8. Creating a system service

solana@antematter:~bin# sudo su - root
root@antematter:~# touch /etc/systemd/system/solana-validator.service

And then dump the following blob of text inside the file we just willed into existence.

[Unit]
Description=Solana RPC Node
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
User=solana
LimitNOFILE=1000000
LogRateLimitIntervalSec=0
Environment=PATH=/bin:/usr/bin:/home/solana/.local/share/solana/install/active_release/bin
ExecStart=/home/solana/bin/validator.sh

[Install]
WantedBy=multi-user.target

9. Running the RPC Node

Before running the systemd service, you can try and make sure everything works seamlessly by switching to the solana user, cding into the ~/bin directory and running ./validator.sh.

To view complete logs, make sure to remove the line export RUST_LOG=error from the bash script and redirect logging to a specific file by modifying the --log flag.

The RPC Node takes some time to boot up and download a recent network snapshot. But once you’ve verified that everything works correctly, kill the process and run the systemd service.

solana@antematter:~# sudo systemctl daemon-reload
solana@antematter:~# sudo systemctl enable solana-validator
solana@antematter:~# sudo systemctl start solana-validator

Voila! We our now knee-deep into the Solana-land.

10. So…is it really up?

I don’t know. But I can help you know.

System Service

solana@antematter:~# sudo systemctl status solana-validator
● solana-validator.service - Solana RPC Node
Loaded: loaded (/etc/systemd/system/solana-validator.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2022-10-31 10:17:55 UTC; 21h ago
Main PID: 69314 (validator.sh)
Tasks: 836 (limit: 618684)
Memory: 479.8G
CGroup: /system.slice/solana-validator.service
├─69314 /bin/bash /home/solana/bin/validator.sh
└─69328 solana-validator --ledger /var/solana/data/ledger ...

Your output should be similar to mine.

Solana Gossip

Let’s find out our public key which identifies our validator on the network.

solana@antematter:~# solana-keygen pubkey /var/data/data/config/validator-keypair.json

Then run the following and verify our public key is indeed present in the output.

solana@antematter:~# solana gossip | grep <pubkey>

11. Catching up

Once your RPC Node joins the network for the first time, it must download a snapshot from one of the known validators. By the time it downloads the snapshot, the network usually already has progressed further. So our node has to work faster than the network to catch up.

Use the following command to see how much behind the network our node is.

solana@antematter:~# solana catchup <pubkey>

If the above command fails, it may be that your validator is still downloading the snapshot and has not fully joined the network. Give it some time, it deserves your patience.

Oh and once the node is fully up and initialized, you should add --no-snapshot-fetch to your validator.sh to avoid slow restarts in the future.

12. Enabling account indices

Story time!

I provisioned my RPC Node and set up an nginx proxy to secure access to the node. I was elated. I provided the RPC URL to my team working on a project.

But lo and behold, calls to getTokenAccountsByOwner were getting stuck. Initially, I thought it was a problem with ports or the node itself. But then I found out that the calls would eventually succeed, they were just taking a LOT of time.

The answer lies here. We need to enable in-memory indices to make account-data RPC requests performant. There are three indices you can enable by providing the --account-index <type> flag to the node.

  • program-id
  • spl-token-mint
  • spl-token-owner

💡 Enabling all three indices will hog all the available RAM, eventually killing the process.

My machine had access to 500GB of RAM but the three indices combined just gulped it down in an instant. Eventually, I just settled with the spl-token-owner index.

TL;DR

There is no TL;DR for this post. You’ve got to read everything or the RPC node won’t work.

Want us to help?

If you’d like us to help you set up an RPC Node or a Validator, drop us a line at our website: antematter.io

Further Reading

--

--

Antematter

The world moves fast, your software should move faster. We develop and improve cutting-edge solutions using Blockchain & AI with maximum performance