Installing and Running a Node using SystemD

Introduction

You can install a Radix Node as a systemd service, without using Docker as a container. The example given here assumes the use of an AWS instance, but can be applied to any Unix-based system. There are a number of steps to the installation:

  1. Create a radixdlt user for running the node.

  2. Install the required packages

  3. Install and run the node.

  4. Configure the Nginx server

If you’re looking to install the node as a Docker container, then follow the instructions here.

Prerequisites

We’re assuming that you have access to a Debian-based (e.g. Ubuntu) server with 250 GB of free SSD space and network bandwidth of 10 GBps or above. Other variants of distributions and/or Unix versions could be configured in similar way. It’ll probably take about half an hour to run through the whole installation.

Model vCPU Memory (GB) Storage(GB) Network Bandwidth (Gbps) Operating System

c5.2xlarge

8

16

Provision a gp2 storage volume.

You should initially provision 250 GB of SSD space

Up to 10

Ubuntu 22.04.2.0 LTS (Jammy Jellyfish)

You should initially provision 250 GB of SSD space

Despite these recommendations, it is fully possible to run it on Windows and MacOS. However we currently only offer support for the recommended setup.

1. Install Required Packages

  1. Execute the following command to make sure the packages on your system are up-to-date.

    sudo apt update -y
  2. You’re going to need to generate secure keys during the installation, so make sure that the necessary packages for this are installed. We will need wget to download the node binary and library, unzip to unpackage it, rng-tools to create secure keys, openjdk to run the java application and docker to run the Node key generation image.

    sudo apt install wget unzip rng-tools openjdk-17-jdk docker.io
    sudo rngd -r /dev/random

2. Configure the Ports

The node requires that a number of ports are accessible on your server. Ensure that ports 443 and 30000 are available and can be seen externally.

HTTPS port for all API end points

 sudo ufw allow 443/tcp

GOSSIP port for node to node communication

 sudo ufw allow 30000/tcp

If you are using a cloud service then you must also arrange for external port access through your service provider: this is usually done through the service management console.

If you are hosting the service yourself, then you may need to open access to the ports through your hardware router.

For more information on the ports used by the Radix service, please consult the Ports used by the Radix Node documentation.

3. Create the Radix User

For security, you’re going to run the node as a specialized user, rather than an administrator.

  1. Execute the following commands to create a new user called radixdlt.

    sudo useradd radixdlt -m

    And then to set the password:

    sudo passwd radixdlt
  2. You’re going to allow the radixdlt user to manage the radixdlt-node service by creating a file in /etc/sudoers with the following content:

    sudo sh -c ' cat > /etc/sudoers.d/radixdlt << EOF
    radixdlt ALL= NOPASSWD: /bin/systemctl enable radixdlt-node.service
    radixdlt ALL= NOPASSWD: /bin/systemctl restart radixdlt-node.service
    radixdlt ALL= NOPASSWD: /bin/systemctl stop radixdlt-node.service
    radixdlt ALL= NOPASSWD: /bin/systemctl start radixdlt-node.service
    radixdlt ALL= NOPASSWD: /bin/systemctl reload radixdlt-node.service
    EOF'
  3. You can check that the file has been created properly by executing the following command:

    sudo ls -l /etc/sudoers.d

    You should see the radixdlt file in the directory listing.

4. Create Directories

Here, you will create directories which will eventually hold the Node software and the ledger data.

  1. First, create the directory and set permissions for the Node software.

    sudo mkdir  /etc/radixdlt/
    sudo chown radixdlt:radixdlt -R /etc/radixdlt
  2. Now, create the directory and set permissions for the Radix ledger.

    sudo mkdir /babylon-ledger
    sudo chown radixdlt:radixdlt /babylon-ledger

5. Creating a systemd service file

Create a systemd service file and make the new user owner of that file.

sudo touch /etc/systemd/system/radixdlt-node.service
sudo vi /etc/systemd/system/radixdlt-node.service
sudo chown radixdlt:radixdlt /etc/systemd/system/radixdlt-node.service

Look at this example file for references on how to write the service file.

[Unit]
Description=Radix DLT Validator
After=local-fs.target
After=network-online.target
After=nss-lookup.target
After=time-sync.target
After=systemd-journald-dev-log.socket
Wants=network-online.target

[Service]
EnvironmentFile=/etc/radixdlt/node/secrets/environment
User=radixdlt
LimitNOFILE=65536
LimitNPROC=65536
LimitMEMLOCK=infinity
WorkingDirectory=/etc/radixdlt/node
ExecStart=/etc/radixdlt/node/v1.0.4/bin/core
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure

[Install]
WantedBy=multi-user.target

6. Download the Radix Distribution

Download and unpack the Radix distribution.

The following actions must be carried as the radixdlt user
  1. Execute the following command to switch to the radixdlt user you created in Section 3, “Create the Radix User”.

    sudo su - radixdlt
  2. Go to https://github.com/radixdlt/babylon-node/releases and look for the entry with the Latest release marker.

  3. Download the latest release from the CLI. Replace the PLATFORM_NAME variable in the following script to download them using wget. Beware that the distribution is platform dependent. We publish installations for different targets. Make sure to download for the correct platform.

    • Linux

    export PLATFORM_NAME=arch-linux-x86_64 (1)
    export VERSION=v1.0.4
    wget https://github.com/radixdlt/babylon-node/releases/download/v1.0.4/babylon-node-v1.0.4.zip
    wget https://github.com/radixdlt/babylon-node/releases/download/v1.0.4/babylon-node-rust-${PLATFORM_NAME}-release-v1.0.4.zip
    unzip babylon-node-${VERSION}.zip
    unzip babylon-node-rust-${PLATFORM_NAME}-release-${VERSION}.zip
  4. Move the java application into the systemd service directory.

    export VERSION=v1.0.4
    mkdir -p /etc/radixdlt/node/
    mv core-${VERSION} /etc/radixdlt/node/${VERSION}
  5. Move the libarary into your Java Class Path.

    • Linux

    export PLATFORM_NAME=arch-linux-x86_64
    export LIBRARY_FILENAME=libcorerust.so (1)
    export VERSION=v1.0.4
    unzip babylon-node-rust-${PLATFORM_NAME}-release-${VERSION}.zip
    sudo mkdir -p /usr/lib/jni
    sudo mv ${LIBRARY_FILENAME} /usr/lib/jni/${LIBRARY_FILENAME}
  6. Change to the directory:

    cd /etc/radixdlt/node/v1.0.4

At this stage, it’s worth checking the directory by executing the ls -al command. It should contain directories for bin and lib.

7. Create the Keys

You will use the Radix key generator to create secure keys for the node.

The key file contains a randomly-generated private key that determines your node’s unique address and (if choosing to register as a validator node) validator ID.

This means if you lose your key file, you will forever lose your node address and validator ID - forcing you to generate a new key file from scratch.

Any tokens held by the node address will be lost.

Always make sure that you securely back up your key file as soon as you’ve generated it, and carefully protect it.

  1. Create a directory to hold the keys.

    mkdir /etc/radixdlt/node/secrets
  2. Then, run they key generator

    docker run --rm  \
      -v /etc/radixdlt/node/secrets/:/keygen/key  \ (1)
      radixdlt/keygen:v1.4.1 \
      --keystore=/keygen/key/node-keystore.ks \
      --password=node-password (2)
    1 You can change the location. Make sure to update the path in the default.config file in the next section aswell.
    2 Enter the password protecting your node key here.

    This will create the keys and write them to the secrets folder.

Don’t forget to set your own password for the key!

The password to the keystore is passed to the application using an environment file. Create it using the following command.

default
cat > /etc/radixdlt/node/secrets/environment << EOF
JAVA_OPTS="--enable-preview -server -Xms12g -Xmx12g  -XX:MaxDirectMemorySize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCompressedOops -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts -Djavax.net.ssl.trustStoreType=jks -Djava.security.egd=file:/dev/urandom -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
RADIX_NODE_KEYSTORE_PASSWORD=node-password
EOF
migration
cat > /etc/radixdlt/node/secrets/environment << EOF
JAVA_OPTS="--enable-preview -server -Xms12g -Xmx12g  -XX:MaxDirectMemorySize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCompressedOops -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts -Djavax.net.ssl.trustStoreType=jks -Djava.security.egd=file:/dev/urandom -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
RADIX_NODE_KEYSTORE_PASSWORD=node-password
EOF

8. Configuration

8.1. Create Node Configuration File

Create the file: /etc/radixdlt/node/default.config and populate it with the following content:

  • Mainnet

  • Stokenet

network.id=1                                                        (1)
#network.genesis_data_file=<not-needed-for-mainnet>                 (2)
network.p2p.seed_nodes=radix://node_rdx1qf2x63qx4jdaxj83kkw2yytehvvmu6r2xll5gcp6c9rancmrfsgfw0vnc65@52.212.35.209,radix://node_rdx1qgxn3eeldj33kd98ha6wkjgk4k77z6xm0dv7mwnrkefknjcqsvhuu4gc609@54.79.136.139,radix://node_rdx1qwrrnhzfu99fg3yqgk3ut9vev2pdssv7hxhff80msjmmcj968487uugc0t2@43.204.226.50,radix://node_rdx1q0gnmwv0fmcp7ecq0znff7yzrt7ggwrp47sa9pssgyvrnl75tvxmvj78u7t@52.21.106.232 (3)

node.key.path=/etc/radixdlt/node/secrets/node-keystore.ks           (4)
db.location=/babylon-ledger                                         (5)

network.host_ip=35.178.201.42                                       (6)

api.core.bind_address=                                              (7)
api.core.port=
api.system.bind_address=                                            (8)
api.system.port=
api.prometheus.bind_address=                                        (9)
api.prometheus.port=

network.p2p.listen_port=30001                                       (10)
network.p2p.broadcast_port=30000
network.p2p.use_proxy_protocol=false                                (11)

db.local_transaction_execution_index.enable=                        (12)
db.account_change_index.enable=
api.core.flags.enable_unbounded_endpoints=

consensus.validator_address=                                        (13)

genesis.use_olympia=false                                           (14)
genesis.olympia.node_end_state_api_url=
genesis.olympia.node_end_state_api_auth_user=
genesis.olympia.node_end_state_api_auth_password=
genesis.olympia.node_bech32_address=
network.id=2                                                       (1)
#network.genesis_data_file=<not-needed-for-stokenet>                (2)
network.p2p.seed_nodes=radix://node_tdx_2_1qv89yg0la2jt429vqp8sxtpg95hj637gards67gpgqy2vuvwe4s5ss0va2y@13.126.248.88,radix://node_tdx_2_1qvtd9ffdhxyg7meqggr2ezsdfgjre5aqs6jwk5amdhjg86xhurgn5c79t9t@13.210.209.103,radix://node_tdx_2_1qwfh2nn0zx8cut5fqfz6n7pau2f7vdyl89mypldnn4fwlhaeg2tvunp8s8h@54.229.126.97,radix://node_tdx_2_1qwz237kqdpct5l3yjhmna66uxja2ymrf3x6hh528ng3gtvnwndtn5rsrad4@3.210.187.161 (3)

node.key.path=/etc/radixdlt/node/secrets/node-keystore.ks           (4)
db.location=/babylon-ledger                                         (5)

network.host_ip=35.178.201.42                                       (6)

api.core.bind_address=                                              (7)
api.core.port=
api.system.bind_address=                                            (8)
api.system.port=
api.prometheus.bind_address=                                        (9)
api.prometheus.port=

network.p2p.listen_port=30001                                       (10)
network.p2p.broadcast_port=30000
network.p2p.use_proxy_protocol=false                                (11)

db.local_transaction_execution_index.enable=                        (12)
db.account_change_index.enable=
api.core.flags.enable_unbounded_endpoints=

consensus.validator_address=                                        (13)

genesis.use_olympia=false                                           (14)
genesis.olympia.node_end_state_api_url=
genesis.olympia.node_end_state_api_auth_user=
genesis.olympia.node_end_state_api_auth_password=
genesis.olympia.node_bech32_address=
1 the id of the given Radix network.
2 the location of the genesis data file. This is not neccessary for mainnet or stokenet.
3 this is a comma-separated list of seed node addresses that your node will use to discover the rest of the network. Select the correct list for your environment from the tabs below.
4 the location and name of node key file.
Always make sure you have an up-to-date copy of this file
5 the location of the node’s ledger database.
6 the external ip address of your server. If this is not provided, the node will attempt to discover this from a number of public services at start-up time. You can find out your external IP address with the following command:
curl ifconfig.me
7 the interface address and HTTP port for the Core API, defaults to 127.0.0.1 and 3333. It is not recommend to bind this to a public interface. Instead, consider binding to localhost, and if necessary, exposing it through some form of possibly authenticated reverse proxy such as Nginx.
8 the interface address and HTTP port for the System API, defaults to 127.0.0.1 and 3334. It is not recommend to bind this to a public interface. Instead, consider binding to localhost, and if necessary, exposing it through some form of possibly authenticated reverse proxy such as Nginx.
9 the interface address and HTTP port for the Prometheus API for metrics, defaults to 127.0.0.1 and 3335. It is not recommend to bind this to a public interface. Instead, consider binding to localhost, and if necessary, exposing it through some form of possibly authenticated reverse proxy such as Nginx.
10 the TCP port for listening to inbound connections. Set the port address to 30001 so that it doesn’t clash with the Nginx server you’ll be installing later.
11 set this true if you using nginx or set it to false. This allows nginx to pass the remote ip address for tcp connections on gossip port.
12 you can choose to disable these indexes for minor performance and storage-size gains, however some Core API endpoints will not work if these are disabled.
Whenever you enable an index, the ledger on the node may need wiping and then syncing from fresh. There is a check at boot-up time to either create the index, or prevent boot-up if the setting is inconsistent with the previous setting.
13 your node’s Babylon validator address. This is only needed if your node’s key wasn’t already registered as a validator at Babylon genesis. See the section Validator Setup for more information
14 configurations for starting a babylon node based on the ledger of olympia. This is used during the changeover from the Olympia network to the Babylon network. See Olympia to Babylon node migration for more information.
  • Mainnet Seed Nodes

  • Stokenet Seed Nodes

radix://node_rdx1qf2x63qx4jdaxj83kkw2yytehvvmu6r2xll5gcp6c9rancmrfsgfw0vnc65@52.212.35.209,radix://node_rdx1qgxn3eeldj33kd98ha6wkjgk4k77z6xm0dv7mwnrkefknjcqsvhuu4gc609@54.79.136.139,radix://node_rdx1qwrrnhzfu99fg3yqgk3ut9vev2pdssv7hxhff80msjmmcj968487uugc0t2@43.204.226.50,radix://node_rdx1q0gnmwv0fmcp7ecq0znff7yzrt7ggwrp47sa9pssgyvrnl75tvxmvj78u7t@52.21.106.232
radix://node_tdx_2_1qv89yg0la2jt429vqp8sxtpg95hj637gards67gpgqy2vuvwe4s5ss0va2y@13.126.248.88,radix://node_tdx_2_1qvtd9ffdhxyg7meqggr2ezsdfgjre5aqs6jwk5amdhjg86xhurgn5c79t9t@13.210.209.103,radix://node_tdx_2_1qwfh2nn0zx8cut5fqfz6n7pau2f7vdyl89mypldnn4fwlhaeg2tvunp8s8h@54.229.126.97,radix://node_tdx_2_1qwz237kqdpct5l3yjhmna66uxja2ymrf3x6hh528ng3gtvnwndtn5rsrad4@3.210.187.161

9. Start Your Node

You are now ready to start your node. Execute the command:

sudo systemctl start radixdlt-node.service

10. Enable Your Node at Startup

You can now enable your node service to start up at when the server starts. Execute the command:

sudo systemctl enable radixdlt-node.service

11. Installing Nginx

Nginx is the front-end web server that handles secure requests between the node and the outside world. The installation runs as a superuser, so if you are still using your terminal as radixdlt user then exit the radixdlt session now:

exit

Now run the following command to run the installation:

sudo apt install -y nginx apache2-utils

Nginx comes with a predefined site directories that you’re not going to need, so you can delete them.

sudo rm -rf /etc/nginx/{sites-available,sites-enabled}

12. Download Nginx Configuration Files

Download and unpack the Nginx distribution.

  1. Go to https://github.com/radixdlt/babylon-nginx/releases and look for the entry with the Latest release marker.

  2. You should see release assets for two .zip files.

    If you’re running a full node then copy the URL for babylon-nginx-fullnode-conf.zip.

    Archive node is not supported from release 1.1.0 onwards

  3. Paste the URL you copied into a wget command on your server to retrieve the zip file.

  4. Unzip the nginx configuration you’ve just downloaded. Either:

    • full node

    unzip babylon-nginx-fullnode-conf.zip
  5. Copy the files to the Nginx setup directory.

    sudo cp -r conf.d/ /etc/nginx/
  6. And now copy the nginx configuration files for your node type:

    • full node

    sudo cp nginx-fullnode.conf /etc/nginx/nginx.conf

13. Create Nginx Cache Directory

Nginx requires a cache directory for storing the reusable artifacts it downloads. Use the following command to create the cache:

sudo mkdir -p /var/cache/nginx/radixdlt-hot

14. Create the SSL Certificates

You can use your own SSL certificates if you wish, but for convenience, you’ll find the instructions for creating a set here.

  1. Create the directory to hold the certificates:

    sudo mkdir /etc/nginx/secrets
  2. Create the SSL keys using the following command:

    sudo openssl req  -nodes -new -x509 -nodes -subj '/CN=localhost' -keyout "/etc/nginx/secrets/server.key" -out "/etc/nginx/secrets/server.pem"
  3. And now execute this command to make sure the keys are in the correct format:

    sudo openssl dhparam -out /etc/nginx/secrets/dhparam.pem  4096
    This command may take a minute or more to run.
  4. Run the next command to set the authentication password for the server’s admin user:

    sudo htpasswd -c /etc/nginx/secrets/htpasswd.admin admin
  5. You can set the authentication password for the server’s superadmin user:

    sudo htpasswd -c /etc/nginx/secrets/htpasswd.superadmin superadmin
  6. Similary you can set the authentication password for the server’s metrics user:

sudo htpasswd -c /etc/nginx/secrets/htpasswd.metrics metrics

15. Start Nginx

  1. Now, to start Nginx, execute the following command:

    sudo systemctl start nginx
  2. And now run this command to make sure that nginx starts up when the host server restarts:

    sudo systemctl enable nginx
  3. You can check if the service is running by executing this command:

    curl -k -u admin:{nginx-admin-password} 'https://localhost/system/identity' --header 'Content-Type: text/plain'

    which spools out a few basic node details:

    {
      "public_key_hex": "03073b82dc0f9....f7795e8ef67271",
      "node_address": "node_tdx_e_1qvrn...7ee8zx3pvg3",
      "node_uri": "radix://node_tdx_e_1qvrnh...7ee8zx3pvg3@35.178.142.54:30000",
      "node_name": "no...e8zx3pvg3",
      "node_id": "NodeId[03073b82dc0f98b...af7795e8ef67271]",
      "validator_name": "030...2dc",
      "consensus_status": "NOT_CONFIGURED_AS_VALIDATOR"
    }

If you’re getting connection errors when trying to connect to the node, then you may need to restart both the node and nginx so they sync correctly. Try executing the following commands:

sudo su - radixdlt
sudo systemctl restart radixdlt-node.service
exit
sudo systemctl restart nginx
It might take some times for your node’s ledger to be up to date, since your newly-created node will have to sync up.

Troubleshooting

If your node isn’t running at this point, then consult the Troubleshooting Guide, or drop a message on Discord where Radix staff and community will be happy to help out.

Where to next …?

Once your node is up and running you can configure it to run as a validator by following the steps in Registering a Validator Node.