Step-by-Step Guide to Setting Up Stellar Validator Node In

RMAG news

Note:

The tutorial will guide you to set up three validation nodes.
The tutorial is brief and should help you set up a node within 20 minutes (excluding time for synchronization).
I will not explain in detail the reasons for each step here, please refer to the detailed documentation provided by SDF for more information.
You need to have a basic understanding of Stellar.
You need to have a basic understanding of Linux.
Some community members requested a simpler setup guide, so I wrote this tutorial hoping it helps. If you have any questions, feel free to ask in the Discord.

Prerequisites:

Three servers with Ubuntu 22.04 installed. You can find the hardware requirements here.
A domain name; we assume your domain is example.com.
Three Stellar accounts for the nodes. We assume the account for node A is GA, for node B is GB, and for node C is GC. Their corresponding private keys are SA, SB, and SC. You need to activate these three accounts on the network and set their home domain to example.com.

Let’s get started

Setup domain

Point core-live-a.example.com, core-live-b.example.com, and core-live-c.example.com to the IP addresses of nodes A, B, and C, respectively.
Point history.core-live-a.example.com, history.core-live-b.example.com, and history.core-live-c.example.com to the IP addresses of nodes A, B, and C, respectively.

Setup Stellar Core

Add the Stellar repository

sudo curl -fsSL https://apt.stellar.org/SDF.asc -o /etc/apt/keyrings/SDF.asc
sudo chmod a+r /etc/apt/keyrings/SDF.asc
echo “deb [signed-by=/etc/apt/keyrings/SDF.asc] https://apt.stellar.org $(lsb_release -cs) stable” | sudo tee -a /etc/apt/sources.list.d/SDF.list
sudo apt update

Install PosttgreSQL and Stellar Core

sudo apt install postgresql postgresql-contrib stellar-core

Setup PostgreSQL

Let’s create a new database user and database.

sudo -u postgres psql
CREATE ROLE stellar WITH LOGIN;
CREATE DATABASE stellar OWNER stellar;
q

Configure Stellar Core

sudo -u stellar nano /etc/stellar/stellar-core.cfg
# Add the following configuration
# save the file

You need to talk care of the EDIT ME in the configuration file.

# complete example config: https://github.com/stellar/stellar-core/blob/master/docs/stellar-core_example.cfg

# Path to the file you want stellar-core to write its log to.
# You can set to “” for no log file.
LOG_FILE_PATH=“/var/log/stellar/stellar-core.log”

# BUCKET_DIR_PATH (string) default “buckets”
# Specifies the directory where stellar-core should store the bucket list.
# This will get written to a lot and will grow as the size of the ledger grows.
BUCKET_DIR_PATH=“/var/lib/stellar/buckets”

# Sets the DB connection string for SOCI.
# DATABASE=”postgresql://user=stellar password=passw&rd host=127.0.0.1 port=5432 dbname=stellar”
# Local Peer connection string
DATABASE=”postgresql://dbname=stellar user=stellar host=/var/run/postgresql/

# This example also adds a common name to NODE_NAMES list named `self` with the
# public key associated to this seed
# EDIT ME: replace the NODE_SEED with your own seed
# EDIT ME: for the node A, use `SA`, for node B, use `SB`, and so on.
NODE_SEED=“SA self”

# HOME_DOMAIN for this validator
# Required when NODE_IS_VALIDATOR=true
# When set, this validator will be grouped with other validators with the
# same HOME_DOMAIN (as defined in VALIDATORS/HOME_DOMAINS)
# EDIT ME: replace `example.com` with your domain
NODE_HOME_DOMAIN=“example.com”

# Only nodes that want to participate in SCP should set NODE_IS_VALIDATOR=true.
# Most instances should operate in observer mode with NODE_IS_VALIDATOR=false.
# See QUORUM_SET below.
NODE_IS_VALIDATOR=true

# CATCHUP_COMPLETE (true or false) defaults to false
# if true will catchup to the network “completely” (replaying all history)
# if false will look for CATCHUP_RECENT for catchup settings
CATCHUP_COMPLETE=true

# DEPRECATED_SQL_LEDGER_STATE (bool) default false
# When set to true, SQL is used to store all ledger state instead of
# BucketListDB. This is not recommended and may cause performance degregradation.
# This is deprecated and will be removed in the future. Note that offers table
# is still maintained in SQL when this is set to false, but all other ledger
# state tables are dropped.
DEPRECATED_SQL_LEDGER_STATE=false

# HTTP_PORT (integer) default 11626
# What port stellar-core listens for commands on.
# If set to 0, disable HTTP interface entirely
HTTP_PORT=11626

# PUBLIC_HTTP_PORT (true or false) default false
# If false you only accept stellar commands from localhost.
# Do not set to true and expose the port to the open internet. This will allow
# random people to run stellar commands on your server. (such as `stop`)
PUBLIC_HTTP_PORT=false

# Configure which network this instance should talk to
NETWORK_PASSPHRASE=“Public Global Stellar Network ; September 2015”

# COMMANDS (list of strings) default is empty
# List of commands to run on startup.
# Right now only setting log levels really makes sense.
COMMANDS=[“ll?level=info“]
############################
# list of HOME_DOMAINS
############################
[[HOME_DOMAINS]]
HOME_DOMAIN = “www.stellar.org”
QUALITY = “HIGH”

[[HOME_DOMAINS]]
HOME_DOMAIN = “stellar.blockdaemon.com”
QUALITY = “HIGH”

[[HOME_DOMAINS]]
HOME_DOMAIN = “publicnode.org”
QUALITY = “HIGH”

[[HOME_DOMAINS]]
HOME_DOMAIN = “satoshipay.io”
QUALITY = “HIGH”

[[HOME_DOMAINS]]
HOME_DOMAIN = “lobstr.co”
QUALITY = “HIGH”

[[HOME_DOMAINS]]
HOME_DOMAIN = “whalestack.com”
QUALITY = “HIGH”

# EDIT ME: edit the following to match your domain
[[HOME_DOMAINS]]
HOME_DOMAIN = “example.com”
QUALITY = “HIGH”

# EDIT ME: I suggest you choose a variety of validators
# EDIT ME: to increase the decentralization of the network.
############################
# List of Validators
############################
[[VALIDATORS]]
NAME = “SDF 1”
PUBLIC_KEY = “GCGB2S2KGYARPVIA37HYZXVRM2YZUEXA6S33ZU5BUDC6THSB62LZSTYH”
ADDRESS = “core-live-a.stellar.org:11625”
HISTORY = “curl -sf http://history.stellar.org/prd/core-live/core_live_001/{0} -o {1}”
HOME_DOMAIN = “www.stellar.org”

[[VALIDATORS]]
NAME = “SDF 2”
PUBLIC_KEY = “GCM6QMP3DLRPTAZW2UZPCPX2LF3SXWXKPMP3GKFZBDSF3QZGV2G5QSTK”
ADDRESS = “core-live-b.stellar.org:11625”
HISTORY = “curl -sf http://history.stellar.org/prd/core-live/core_live_002/{0} -o {1}”
HOME_DOMAIN = “www.stellar.org”

[[VALIDATORS]]
NAME = “SDF 3”
PUBLIC_KEY = “GABMKJM6I25XI4K7U6XWMULOUQIQ27BCTMLS6BYYSOWKTBUXVRJSXHYQ”
ADDRESS = “core-live-c.stellar.org:11625”
HISTORY = “curl -sf http://history.stellar.org/prd/core-live/core_live_003/{0} -o {1}”
HOME_DOMAIN = “www.stellar.org”

[[VALIDATORS]]
NAME = “Blockdaemon Validator 1”
PUBLIC_KEY = “GAAV2GCVFLNN522ORUYFV33E76VPC22E72S75AQ6MBR5V45Z5DWVPWEU”
ADDRESS = “stellar-full-validator1.bdnodes.net:11625”
HISTORY = “curl -sf https://stellar-full-history1.bdnodes.net/{0} -o {1}”
HOME_DOMAIN = “stellar.blockdaemon.com”

[[VALIDATORS]]
NAME = “Blockdaemon Validator 2”
PUBLIC_KEY = “GAVXB7SBJRYHSG6KSQHY74N7JAFRL4PFVZCNWW2ARI6ZEKNBJSMSKW7C”
ADDRESS = “stellar-full-validator2.bdnodes.net:11625”
HISTORY = “curl -sf https://stellar-full-history2.bdnodes.net/{0} -o {1}”
HOME_DOMAIN = “stellar.blockdaemon.com”

[[VALIDATORS]]
NAME = “Blockdaemon Validator 3”
PUBLIC_KEY = “GAYXZ4PZ7P6QOX7EBHPIZXNWY4KCOBYWJCA4WKWRKC7XIUS3UJPT6EZ4”
ADDRESS = “stellar-full-validator3.bdnodes.net:11625”
HISTORY = “curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}”
HOME_DOMAIN = “stellar.blockdaemon.com”

[[VALIDATORS]]
NAME = “Hercules by OG Technologies”
PUBLIC_KEY = “GBLJNN3AVZZPG2FYAYTYQKECNWTQYYUUY2KVFN2OUKZKBULXIXBZ4FCT”
ADDRESS = “hercules.publicnode.org:11625”
HISTORY = “curl -sf https://hercules-history.publicnode.org/{0} -o {1}”
HOME_DOMAIN = “publicnode.org”

[[VALIDATORS]]
NAME = “Lyra by BP Ventures”
PUBLIC_KEY = “GCIXVKNFPKWVMKJKVK2V4NK7D4TC6W3BUMXSIJ365QUAXWBRPPJXIR2Z”
ADDRESS = “lyra.publicnode.org:11625”
HISTORY = “curl -sf https://lyra-history.publicnode.org/{0} -o {1}”
HOME_DOMAIN = “publicnode.org”

[[VALIDATORS]]
NAME = “Boötes”
PUBLIC_KEY = “GCVJ4Z6TI6Z2SOGENSPXDQ2U4RKH3CNQKYUHNSSPYFPNWTLGS6EBH7I2”
ADDRESS = “bootes.publicnode.org:11625”
HISTORY = “curl -sf https://bootes-history.publicnode.org/{0} -o {1}”
HOME_DOMAIN = “publicnode.org”

[[VALIDATORS]]
NAME = “SatoshiPay Iowa”
PUBLIC_KEY = “GAK6Z5UVGUVSEK6PEOCAYJISTT5EJBB34PN3NOLEQG2SUKXRVV2F6HZY”
ADDRESS = “stellar-us-iowa.satoshipay.io:11625”
HISTORY = “curl -sf https://stellar-history-us-iowa.satoshipay.io/{0} -o {1}”
HOME_DOMAIN = “satoshipay.io”

[[VALIDATORS]]
NAME = “SatoshiPay Singapore”
PUBLIC_KEY = “GBJQUIXUO4XSNPAUT6ODLZUJRV2NPXYASKUBY4G5MYP3M47PCVI55MNT”
ADDRESS = “stellar-sg-sin.satoshipay.io:11625”
HISTORY = “curl -sf https://stellar-history-sg-sin.satoshipay.io/{0} -o {1}”
HOME_DOMAIN = “satoshipay.io”

[[VALIDATORS]]
NAME = “SatoshiPay Frankfurt”
PUBLIC_KEY = “GC5SXLNAM3C4NMGK2PXK4R34B5GNZ47FYQ24ZIBFDFOCU6D4KBN4POAE”
ADDRESS = “stellar-de-fra.satoshipay.io:11625”
HISTORY = “curl -sf https://stellar-history-de-fra.satoshipay.io/{0} -o {1}”
HOME_DOMAIN = “satoshipay.io”

[[VALIDATORS]]
NAME = “LOBSTR 1 (Europe)”
PUBLIC_KEY = “GCFONE23AB7Y6C5YZOMKUKGETPIAJA4QOYLS5VNS4JHBGKRZCPYHDLW7”
ADDRESS = “v1.stellar.lobstr.co:11625”
HISTORY = “curl -sf https://archive.v1.stellar.lobstr.co/{0} -o {1}”
HOME_DOMAIN = “lobstr.co”

[[VALIDATORS]]
NAME = “LOBSTR 2 (Europe)”
PUBLIC_KEY = “GCB2VSADESRV2DDTIVTFLBDI562K6KE3KMKILBHUHUWFXCUBHGQDI7VL”
ADDRESS = “v2.stellar.lobstr.co:11625”
HISTORY = “curl -sf https://archive.v2.stellar.lobstr.co/{0} -o {1}”
HOME_DOMAIN = “lobstr.co”

[[VALIDATORS]]
NAME = “LOBSTR 3 (North America)”
PUBLIC_KEY = “GD5QWEVV4GZZTQP46BRXV5CUMMMLP4JTGFD7FWYJJWRL54CELY6JGQ63”
ADDRESS = “v3.stellar.lobstr.co:11625”
HISTORY = “curl -sf https://archive.v3.stellar.lobstr.co/{0} -o {1}”
HOME_DOMAIN = “lobstr.co”

[[VALIDATORS]]
NAME = “LOBSTR 4 (Asia)”
PUBLIC_KEY = “GA7TEPCBDQKI7JQLQ34ZURRMK44DVYCIGVXQQWNSWAEQR6KB4FMCBT7J”
ADDRESS = “v4.stellar.lobstr.co:11625”
HISTORY = “curl -sf https://archive.v4.stellar.lobstr.co/{0} -o {1}”
HOME_DOMAIN = “lobstr.co”

[[VALIDATORS]]
NAME = “LOBSTR 5 (India)”
PUBLIC_KEY = “GA5STBMV6QDXFDGD62MEHLLHZTPDI77U3PFOD2SELU5RJDHQWBR5NNK7”
ADDRESS = “v5.stellar.lobstr.co:11625”
HISTORY = “curl -sf https://archive.v5.stellar.lobstr.co/{0} -o {1}”
HOME_DOMAIN = “lobstr.co”

[[VALIDATORS]]
NAME = “Whalestack (Germany)”
PUBLIC_KEY = “GD6SZQV3WEJUH352NTVLKEV2JM2RH266VPEM7EH5QLLI7ZZAALMLNUVN”
ADDRESS = “germany.stellar.whalestack.com:11625”
HISTORY = “curl -sf https://germany.stellar.whalestack.com/history/{0} -o {1}”
HOME_DOMAIN = “whalestack.com”

[[VALIDATORS]]
NAME = “Whalestack (Finland)”
PUBLIC_KEY = “GADLA6BJK6VK33EM2IDQM37L5KGVCY5MSHSHVJA4SCNGNUIEOTCR6J5T”
ADDRESS = “finland.stellar.whalestack.com:11625”
HISTORY = “curl -sf https://finland.stellar.whalestack.com/history/{0} -o {1}”
HOME_DOMAIN = “whalestack.com”

[[VALIDATORS]]
NAME = “Whalestack (Hong Kong)”
PUBLIC_KEY = “GAZ437J46SCFPZEDLVGDMKZPLFO77XJ4QVAURSJVRZK2T5S7XUFHXI2Z”
ADDRESS = “hongkong.stellar.whalestack.com:11625”
HISTORY = “curl -sf https://hongkong.stellar.whalestack.com/history/{0} -o {1}”
HOME_DOMAIN = “whalestack.com”

# EDIT ME: replace the following with your own validators, this is for the node A,
# EDIT ME: for the node B, replace `Example Node B` config with the node A’s info, and so on.
[[VALIDATORS]]
NAME = “Example Node B”
PUBLIC_KEY = “GB”
ADDRESS = “core-live-b.example.com:11625”
HISTORY = “curl -sf http://history.core-live-b.example.com/{0} -o {1}”
HOME_DOMAIN = “example.com”

[[VALIDATORS]]
NAME = “Example Node C”
PUBLIC_KEY = “GC”
ADDRESS = “core-live-c.example.com:11625”
HISTORY = “curl -sf http://history.core-live-c.example.com/{0} -o {1}”
HOME_DOMAIN = “example.com”

# HISTORY
# Used to specify where to fetch and store the history archives.
# Fetching and storing history is kept as general as possible.
# Any place you can save and load static files from should be usable by the
# stellar-core history system. s3, the file system, http, etc
# stellar-core will call any external process you specify and will pass it the
# name of the file to save or load.
# Simply use template parameters `{0}` and `{1}` in place of the files being transmitted or retrieved.
# You can specify multiple places to store and fetch from. stellar-core will
# use multiple fetching locations as backup in case there is a failure fetching from one.
#
# Note: any archive you *put* to you must run `$ stellar-core new-hist <historyarchive>`
# once before you start.
# for example this config you would run: $ stellar-core new-hist local

# this creates a `local` archive on the local drive
# NB: this is an example, in general you should probably not do this as
# archives grow indefinitely
[HISTORY.local]
get=“cp /var/lib/stellar/history/{0} {1}”
put=“cp {0} /var/lib/stellar/history/{1}”
mkdir=“mkdir -p /var/lib/stellar/history/{0}”

Initialize the database

sudo -u stellar stellar-core –conf /etc/stellar/stellar-core.cfg new-db

If the configuration is correct, you will not see any error message.

Initialize the history archive

sudo -u stellar stellar-core –conf /etc/stellar/stellar-core.cfg new-hist local

If you see cp: cannot stat ‘/var/lib/stellar/history/.well-known/stellar-history.json’: No such file or directory, don’t worry, it’s not your fault. You can ignore this message.

Start Stellar Core

sudo systemctl restart stellar-core

Check the status of Stellar Core:

sudo systemctl status stellar-core

You should see Active: active (running). If you see other messages, please check the log file /var/log/stellar/stellar-core.log.

Check the sync status

stellar-core –conf /etc/stellar/stellar-core.cfg http-command ‘info’

You should see the state is Catching up, now, you need to wait until the state is Synced!, this may take a few hours or even days depending on the network speed.

Publishing History Archives

Next, let’s publish the history archives. We’ll use Nginx to publish the locally stored history archives. You can use other methods to publish the history archives, such as AWS S3.

The following example publishes history archives on node A. For nodes B and C, you need to repeat this process, adjusting the configuration file EDIT ME sections and replacing the domain information appropriately.

Install Nginx and Certbot

sudo apt install nginx certbot python3-certbot-nginx

Setup Nginx

# Create a new site configuration file, replace `history.core-live-a.example.com` with your domain
sudo nano /etc/nginx/sites-available/history.core-live-a.example.com
# Add the following configuration
# Save the file
server {
listen 80;
root /var/lib/stellar/history/;

# EDIT ME: replace `history.core-live-a.example.com` with your domain
server_name history.core-live-a.example.com;

# do not cache 404 errors
error_page 404 /404.html;
location = /404.html {
add_header Cache-Control “no-cache” always;
}

# do not cache history state file
location ~ ^/.well-known/stellar-history.json$ {
add_header Cache-Control “no-cache” always;
try_files $uri =404;
}

# cache entire history archive for 1 day
location / {
add_header Cache-Control “max-age=86400”;
try_files $uri =404;
}
}

Enable the site

sudo ln -s /etc/nginx/sites-available/history.core-live-a.example.com /etc/nginx/sites-enabled/
# Test the configuration
sudo nginx -t
# Reload Nginx
sudo nginx -s reload

Setup SSL Certificate

sudo certbot –nginx -d history.core-live-a.example.com

Setup Stellar TOML

Add the following content to your stellar.toml file.
Check SEP-01 to learn more about the stellar.toml file.

[[VALIDATORS]]
ALIAS=“ena”
DISPLAY_NAME=“Example Node A”
HOST=“core-live-a.example.com:11625”
PUBLIC_KEY=“GA”
HISTORY=“https://history.core-live-a.example.com/”

[[VALIDATORS]]
ALIAS=“enb”
DISPLAY_NAME=“Example Node B”
HOST=“core-live-b.example.com:11625”
PUBLIC_KEY=“GA”
HISTORY=“https://history.core-live-b.example.com/”

[[VALIDATORS]]
ALIAS=“enc”
DISPLAY_NAME=“Example Node C”
HOST=“core-live-c.example.com:11625”
PUBLIC_KEY=“GC”
HISTORY=“https://history.core-live-a.example.com/”

Please follow and like us:
Pin Share