Manual Node Setup with systemd
  • 30 Apr 2024
  • 12 Minutes to read
  • Dark
  • PDF

Manual Node Setup with systemd

  • Dark
  • PDF

Article Summary


Welcome to the Radix node manual setup guide!
Before we begin, make sure you’ve read the Node Setup Introduction.

On this page we’ll guide you through the process of setting up your node to run directly on the host system, and we’ll do it manually (i.e. without the use of our helper babylonnode CLI). Using the CLI is an alternative and easier way (for dedicated server instances). Manual mode is however better suited for shared servers (i.e. when the server isn’t solely dedicated to running a Radix node) or non-Ubuntu hosts. If you wish to switch to a CLI path, go to Guided Setup Instructions.
There’s also an alternative path that utilizes Docker here (also manually, i.e. without using our CLI).

You can use any compatible operating system (again, check Node Setup Introduction for details), however all examples in this guide will be for Ubuntu 22.04. Consult your system’s manual for the corresponding packages/commands.


Update the system

First, let’s make sure that your system is up to date, if you’re on Ubuntu run:

sudo apt update && sudo apt -y upgrade

Install Java

Then, we’ll need Java (version 17). We recommend using OpenJDK. On Ubuntu it’s the openjdk-17-jdk package:

sudo apt install openjdk-17-jdk

Configure the firewall

You’ll need to open the p2p gossip port, which by default is 30000.

 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 and/or configure port forwarding.

Recommended: create a dedicated user for running the node

We recommend to run the node as a dedicated system user, rather than the root user. We’ll use the radixdlt user name throughout this tutorial, however you can choose any name you like.

sudo useradd radixdlt -m # create a new user
sudo passwd radixdlt # set its password

Preparing the directory structure

We’ll need a place to store both the node software package and the actual ledger data. You can choose any directory on your system, as long as it’s accessible to the user that runs the node process (`radixdlt` user in this tutorial). We’ll also need some place to put a keystore file (containing a private key that uniquely identifies your node on the network).

An example folder structure could look like this:

  • /opt/radixdlt/babylon-node - for the node software package

  • /srv/radixdlt/babylon-mainnet/data - for the node storage directory (ledger data)

  • /srv/radixdlt/babylon-mainnet/keystore.ks - for the keystore file

  • /srv/radixdlt/babylon-mainnet/mainnet.config - for the configuration file

Make sure to replace the paths in the steps below if you choose to use a different folder structure.
If you’re setting up a Stokenet node (you can read more about the different networks on the Node Setup Introduction page), you may wish to replace “mainnet” with “stokenet”.

Downloading the Radix node software

Radix node consists of two components: the main Java application and an additional native library (.dll or .so file, depending on your system).

You can find the latest release on our GitHub: babylon-node/releases/latest.
The main Java application is the zip file named (where a.b.c is the version number). Unlike the Java application, native library is platform-dependant. You should download the file that corresponds to your system architecture. For example for 64-bit Linux it’s the: file.

Download and extract both files, you can use wget. For example:

# install wget and unzip if they don't come preinstalled on your system
sudo apt install wget unzip

# make sure to replace the version (always use the latest!) and platform architecture

# extract both files

Following the directory structure we outlined above, let’s move both files to /opt/radixdlt/babylon-node:

sudo mkdir -p /opt/radixdlt/babylon-node
sudo mv core-v1.1.0 /opt/radixdlt/babylon-node
sudo mv /opt/radixdlt/babylon-node

We should also make sure that the files are accessible/owned by the radixdlt user:

sudo chown -R radixdlt:radixdlt /opt/radixdlt

The resultant folder structure should look like this:

tree /opt/radixdlt/babylon-node -L 2
├── core-v1.1.0
│   ├── bin
│   └── lib

Generating the key pair

The keystore contains a randomly-generated private key that determines your node’s unique address.

This means that if you lose your keystore file, you will forever lose your node address and you’ll need to generate a new key for your node.

We’ll be storing the key in /srv/radixdlt/babylon-node/keystore.ks , so let’s make sure the directory exists and has a correct owner/permissions:

sudo mkdir -p /srv/radixdlt/babylon-mainnet/data
sudo chown -R radixdlt:radixdlt /srv/radixdlt

Now let’s run the key generator tool that comes with the Radix node distribution:

sudo /opt/radixdlt/babylon-node/core-v1.1.0/bin/keygen \
  --keystore=/srv/radixdlt/babylon-mainnet/keystore.ks \

It goes without saying that you should replace <password> with an actual password. Use a strong one and don’t forget it!
Again, make sure the file belongs to our user:

sudo chown radixdlt:radixdlt /srv/radixdlt/babylon-mainnet/keystore.ks

Preparing the configuration file

It’s time to choose the network that your node will join (you can read more about the different networks on the Node Setup Introduction page).

  • Mainnet

    • use

    • use the following network.p2p.seed_nodes

  • Stokenet

    • use

    • use the following network.p2p.seed_nodes


Create a /srv/radixdlt/babylon-mainnet/mainnet.config file with the following content:

# The ID of the network to connect to (Mainnet=1, Stokenet=2), see above|2
# A comma-separated list of network seed nodes, copy-paste from above (must match


Remember to use your paths in node.key.path and db.location if they differ from the examples.

There are a few additional config options that you might wish to add to your config file at this point. They’re all optional and we provide reasonable defaults, however you may want to adjust some of them to fit your circumstances:

Additional config options

# Here you can specify your node's public IP address
# you can get it from, for example.
# You can leave this empty, in which case the node will
# try to get it automatically.

# The address that the Core API will bind to
# Defaults to
# It is recommended to keep the default and use
# a reverse-proxy (nginx) to access the Core API
# externally (if you need it).
# We show how to do it later on this page.
# Core API port defaults to 3333, you can chance it here

# Similarly, System API binds to by default
# and we recommend to keep it and use a reverse-proxy.
# System API port defaults to 3334, you can chance it here              

# Similarly to above APIs, this defaults to
# Prometheus API port defaults to 3335, you can chance it here

# This is the local port that the P2P server binds to
# If you change it, make sure to enable that port in your firewall
# (instructions how to do that have been shown above).
# This is a P2P port that's broadcasted to other peers (together with `network.host_ip`).
# If you're not using NAT/port-forwarding this should be the same as `listen_port`.

# An additional ledger index for transaction data, enabled by default 
# An additional ledger index for transactions that change accounts, enabled by default
# Enabled by default, allows to disable a subset of Core API endpoints whose responses are potentially unbounded

Don’t forget to change the owner of the config file to radixdlt :

sudo chown radixdlt:radixdlt /srv/radixdlt/babylon-mainnet/mainnet.config

Running the node

At this point we’re ready to actually run the node! We’ll start with a simple script that just runs the node process in a terminal session and then we’ll productionize our setup by introducing a systemd service for our node.

Manual test run

Running the node is just running an executable file that comes with node distribution. That executable is located in the bin folder: /opt/radixdlt/babylon-node/core-v1.1.0/bin/core (The path may vary if you’re running a never version than 1.1.0 which is used in this example. Always use the latest version!).
We’ll need to tell it where to find the files it requires (the keystore, config file, etc) as well as your keystore password. It’ll also require some additional JVM parameters. For clarity, let’s put the required environment variables in a separate file, and then create a node run script.

The environment file (e.g. /srv/radixdlt/babylon-mainnet/environment):

# Enter your keystore password here

# Update java.library.path if you're using a different path for your node dist
JAVA_OPTS="-Djava.library.path=/opt/radixdlt/babylon-node --enable-preview -server -Xms2g -Xmx12g  -XX:MaxDirectMemorySize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseCompressedOops -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"

# Update this if you're using a different path for your node dist

Node run script (e.g. /srv/radixdlt/babylon-mainnet/


# Load our environment variables from a file
set -a
source /srv/radixdlt/babylon-mainnet/environment
set +a

# Run the node; update the paths if needed
/opt/radixdlt/babylon-node/core-v1.1.0/bin/core -config=/srv/radixdlt/babylon-mainnet/mainnet.config

At this point, the only thing left to do is to make the script executable and run it!

# Let's also change the owner of both files...
sudo chown radixdlt:radixdlt /srv/radixdlt/babylon-mainnet/environment
sudo chown radixdlt:radixdlt /srv/radixdlt/babylon-mainnet/

# ...and set proper permissions for the environment file
sudo chmod 700 /srv/radixdlt/babylon-mainnet/environment

# Make the script executable
sudo chmod +x /srv/radixdlt/babylon-mainnet/

# ...and run it as the radixdlt user
sudo su - radixdlt -c /srv/radixdlt/babylon-mainnet/

Verifying that the node works

After you’ve run the script, your node should start processing the genesis transactions. You should be seeing messages that begin with “Committing data ingestion chunk…” in the output log. This may take up to 30 minutes to fully process, depending on your hardware. Usually it finishes in around 10-15 minutes.


Don’t terminate (or restart) the process while the genesis transactions are being committed!
If you do so before the whole process is completed you’ll need to wipe the data directory (e.g. /srv/radixdlt/babylon-mainnet/data) and start from scratch.

After the process completes you should start seeing messages like “lgr_commit{epoch= … }”, which indicate that the node is working correctly (at which point you can safely stop/restart it any time you wish).

At this point you can also query the System API and the Core API.
System API’s health endpoint provides an overall health summary of a node:


The response should include "status":"SYNCING. All possible statuses have been described in detail here.


jq is a great tool for querying the endpoints that return JSON data (such as node’s System and Core APIs). On Ubuntu you can install it with:

sudo apt install jq

We’ll use it from now on in the examples. But if you prefer not to install it, simply skip the | jq pipe suffix from the example commands.

You can also inspect the Core API and query the current state of the ledger:

curl -X POST -H 'Content-Type: application/json' --data '{"network": "mainnet"}' | jq

There’s a current_epoch_round field in the response and both the epoch and round number should be steadily growing as you re-run the query - this indicates that the node is correctly syncing the ledger state.

Congratulations! At this point you’ve got a fully operational Radix node connected to the network.
Note that it might take some time until it’s fully synced up with the latest ledger state. You can check the current epoch using one of the community-run Radix network dashboards on the internet.

We highly encourage you to follow the remainder of this tutorial to productionize your node.


If your node isn’t running at this point you can drop a message on Discord where Radix staff and community will be happy to help out.

Creating a systemd service

In rare cases would one be happy having to manually run a script every time the system reboots. To aid that, in this section we’ll create a systemd service that will manage our node process. We won’t be needing the script from the previous step anymore, but you’re free to keep it for debugging purposes. Just make sure that you’re not trying to run it at the same time when the systemd service is active. We’ll reuse the environment file from the previous section, so go ahead and create it, if you haven’t yet. Keep in mind that it’s a simple key-value file, not a bash script (so e.g. variable substitution like so ABC="$CDE" won’t work!).

We’ll create a system-wide service for our node, but with minimal adjustment it could also run as a user service, if that’s what you prefer. In any case, we’ll still run the process under the radixdlt user.

Create a systemd unit file (e.g. /etc/systemd/system/babylon-node.service):

Description=Radix Babylon Node

ExecStart=/opt/radixdlt/babylon-node/core-v1.1.0/bin/core -config=/srv/radixdlt/babylon-mainnet/mainnet.config


Don’t forget to update the paths if yours differ from the example!

Verifying that the systemd service works

Run the following command to start the service:

sudo systemctl start babylon-node

You can use journalctl to inspect the logs of a running node (or errors, if there are any):

sudo journalctl -f -u babylon-node

To stop the node use:

sudo systemctl stop babylon-node

Enabling systemd service autostart

Run the following command to enable the node service at startup:

sudo systemctl enable babylon-node.service

Configuring a reverse-proxy (nginx) for node APIs

nginx is a modern proxy server that we can use to securely expose our node’s APIs on a public network interface. Note that this is an optional step. You can skip it if you don’t need your node’s APIs to be accessible on the internet (you can still use e.g. ssh and query the API locally).

Installing nginx

To install nginx on Ubuntu run:

sudo apt install -y nginx apache2-utils

nginx comes with some predefined site directories that you’re not going to need, so you can delete them:

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

Download Radix Node nginx configuration files

We do provide a set of ready to use configuration files for your nginx server, which you can download from

  1. Go to and look for the entry with the Latest release marker.

  2. Download the file (e.g. copy its URL and use wget on your server).

  3. Unzip the nginx configuration you’ve just downloaded:

  4. Copy the files to the nginx setup directory.

    sudo cp -r conf.d/ /etc/nginx/
  5. And now copy the nginx configuration files:"

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

Create a 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

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.


If you run into trouble generating the SSL key due to lack of entropy, try running:

sudo apt install rng-tools
sudo rngd -r /dev/random
  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. Similary you can set the authentication password for the server’s metrics user:

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

Open the firewall port

sudo ufw allow 443/tcp

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 should return a JSON response with node details, including its address:

  "node_address": "node_...",

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 systemctl restart babylon-node
sudo systemctl restart nginx

Was this article helpful?