- 22 May 2024
- 7 Minutes to read
- DarkLight
- PDF
Manual Setup with Docker
- Updated on 22 May 2024
- 7 Minutes to read
- DarkLight
- PDF
Introduction
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 inside a Docker container 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 systemd, instead of 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.
We’ve split the installation into discrete stages:
Installing Docker and the secure key generation tools.
Using the
keygen
application to generate secure keys for your service.Installing and running the node on a provisioned server instance.
Note
We’re using Amazon Web Services throughout our example, but you can install Radix nodes on any cloud service that supports Java, such as Google’s cloud platform or Microsoft Azure – or follow similar step to deploy on a private server.
Installing Docker
Run the following commands to install docker
and docker-compose
.
Create the directory for the compose scripts:
sudo apt update mkdir radixdlt cd radixdlt mkdir babylon-ledger
All further instructions assume you are running the commands from
radixdlt
directory and useradixdlt/babylon-ledger
as your storage directory. Make sure to update the docker-compose file if these should be changed.Install
wget
,Docker
and the tools for key generating randomized keys:sudo apt install wget docker.io docker-compose rng-tools # Setup the random number generator sudo rngd -r /dev/random
Add user to Docker group:
sudo groupadd docker # ignore any errors if the group already exists sudo usermod -aG docker $USER newgrp docker
Get the Docker Compose Script
You will need a docker compose script to build the node, which you can download from the Radix repository on GitHub directly to your server. Here we provide an example Docker compose file for Mainet/Stokenet nodes.
Copy and paste the following code into a file and call it radix-fullnode-compose.yml
.
The list of all possible configuration is available here.
Mainnet node
version: '3.8'
services:
core:
cap_add:
- NET_ADMIN
environment:
RADIXDLT_NETWORK_ID: 1
RADIXDLT_NETWORK_SEEDS_REMOTE: "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"
JAVA_OPTS: --enable-preview -server -Xms4g -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
RADIXDLT_LOG_LEVEL: info
RADIXDLT_NETWORK_USE_PROXY_PROTOCOL: 'false'
RADIXDLT_VALIDATOR_KEY_LOCATION: /home/radixdlt/node-keystore.ks
RADIX_NODE_KEYSTORE_PASSWORD: "${RADIXDLT_NODE_KEY_PASSWORD}"
image: radixdlt/babylon-node:v1.2.1
init: true
mem_limit: 14000m
restart: unless-stopped
ulimits:
memlock: -1
nofile:
hard: 65536
soft: 65536
volumes:
- babylon_ledger:/home/radixdlt/RADIXDB
- ./node-keystore.ks:/home/radixdlt/node-keystore.ks
nginx:
environment:
RADIXDLT_GATEWAY_API_ENABLE: 'true'
RADIXDLT_GATEWAY_BEHIND_AUTH: 'true'
RADIXDLT_NETWORK_USE_PROXY_PROTOCOL: 'false'
RADIXDLT_TRANSACTIONS_API_ENABLE: 'false'
image: radixdlt/babylon-nginx:1.0.8
ports:
- 443:443
- 30000:30000
restart: unless-stopped
ulimits:
nofile:
hard: 65536
soft: 65536
volumes:
- nginx_secrets:/etc/nginx/secrets
volumes:
babylon_ledger:
driver: local
driver_opts:
device: ./babylon-ledger
o: bind
type: none
nginx_secrets:
Stokenet (testnet) node
version: '3.8'
services:
core:
cap_add:
- NET_ADMIN
environment:
RADIXDLT_NETWORK_ID: 2
RADIXDLT_NETWORK_SEEDS_REMOTE: "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"
JAVA_OPTS: --enable-preview -server -Xms4g -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
RADIXDLT_LOG_LEVEL: info
RADIXDLT_NETWORK_USE_PROXY_PROTOCOL: 'false'
RADIXDLT_VALIDATOR_KEY_LOCATION: /home/radixdlt/node-keystore.ks
RADIX_NODE_KEYSTORE_PASSWORD: "${RADIXDLT_NODE_KEY_PASSWORD}"
image: radixdlt/babylon-node:v1.2.1
init: true
mem_limit: 14000m
restart: unless-stopped
ulimits:
memlock: -1
nofile:
hard: 65536
soft: 65536
volumes:
- babylon_ledger:/home/radixdlt/RADIXDB
- ./node-keystore.ks:/home/radixdlt/node-keystore.ks
nginx:
environment:
RADIXDLT_GATEWAY_API_ENABLE: 'true'
RADIXDLT_GATEWAY_BEHIND_AUTH: 'true'
RADIXDLT_NETWORK_USE_PROXY_PROTOCOL: 'false'
RADIXDLT_TRANSACTIONS_API_ENABLE: 'false'
image: radixdlt/babylon-nginx:1.0.8
ports:
- 443:443
- 30000:30000
restart: unless-stopped
ulimits:
nofile:
hard: 65536
soft: 65536
volumes:
- nginx_secrets:/etc/nginx/secrets
volumes:
babylon_ledger:
driver: local
driver_opts:
device: ./babylon-ledger
o: bind
type: none
nginx_secrets:
Generate the keys
You’ll need the Radix Key Generator application to create secure keys for the node once it’s installed. (It’s a good idea to generate the keys first, just to get them out of the way).
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.
You can check for the latest version of the keygen
program here:
hub.docker.com/radixdlt/keygen
which should be used in the command given below to generate the secure keys.
Change the --password=
parameter in the following command to a secure password of your choice! Don’t forget it!
docker run --rm -v ${PWD}:/keygen/key radixdlt/keygen:v1.4.1 --keystore=/keygen/key/node-keystore.ks --password=your-password
If you check the directory, you should now have a key file called node-keystore.ks
.
The key generation process may take a long time if your server hasn’t generated a sufficiently large pool of random values to build fresh keys. Be prepared to wait up to twenty minutes for the key generation to complete.
You must change the key file’s permissions so that container can use it.
sudo chmod 644 node-keystore.ks
And update the password in the radix-fullnode-compose.yml
:
RADIX_NODE_KEYSTORE_PASSWORD: "your-password"
Configure the Ports
The node requires that a number of ports are accessible on your server instance. Ensure that ports 443
and 30000
are available and can be seen externally.
sudo ufw allow 30000/tcp
sudo ufw allow 443/tcp
Bear in mind that you must arrange for port access outside your cloud server instance: this is usually done through the management console provided by your cloud service.
Configure nginx admin password
The node uses nginx as its front end server. During startup, it creates an HTTP basic auth user named admin
. The password is generated automatically and printed to the logs. If you want to use your own password, you will need to use the Docker instruction below to set the password before running the node installation. Replace <nginx-admin-password>
with your password.
docker run --rm -v radixdlt_nginx_secrets:/secrets radixdlt/htpasswd:v1.1.0 htpasswd -bc /secrets/htpasswd.admin admin <nginx-admin-password>
If you omit the command, then nginx will create a password and print it out in the log. It will not appear in the logs if the nginx container restarts for any other reason.
To setup the metrics user, run the following command. Replace <nginx-metrics-password>
with your password:
docker run --rm -v radixdlt_nginx_secrets:/secrets radixdlt/htpasswd:v1.1.0 htpasswd -bc /secrets/htpasswd.metrics metrics <nginx-metrics-password>
Running the node
Run the compose script to install and run the node.
docker-compose -f radix-fullnode-compose.yml up -d
The docker-compose file uses relative paths and expects this command to be run from the radixdlt folder created in the first step.
Verifying that the node works
You can use docker logs -f radixdlt_core_1
to inspect the logs of a running node.
A fresh node should start with 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.
Warning
Don’t stop (or restart) the Docker container 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 (babylon-ledger
) 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 the container 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:
curl -k -u "admin:<nginx-admin-password>" https://127.0.0.1/system/health
The response should include "status":"SYNCING
. All possible statuses have been described in detail here.
Tip!
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 -k -u "admin:<nginx-admin-password>" https://127.0.0.1/core/status/network-status -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.
Troubleshooting
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.