IOTA IRI Full Node (Server) Copy-Paste
Installation Guide


Responsive image

This tutorial provides copy-paste Linux console commands to install and run a complete and stable IOTA full node within a few minutes. All you need is some time, patience, a rental server and basic console knowledge. I have deliberately chosen not to use automated installation tools like Ansible or Chef.

Discord is the primary communication platform for the IOTA community. If you have not already joined use this link. In the channel #fullnodes you can get support in English and in the channel #fullnodes-ger in German. Make sure to follow the instructions precisely. In case you already have a node installation which does not run properly you should reinstall the server before proceeding.

1. Server

A VPS (Virtual Private Server) with 2 cores and 4GB RAM (8GB / 4 cores would perform better) is currently sufficient. An SSD hard disk is highly recommended but not mandatory.

On the right hand side you can see a small list of EU / German host providers who already have nodes running on their machines.

For the sake of simplicity we will focus on Ubuntu. Please consider the following points:

  • minimal Ubuntu server installation 16.04. or higher
  • SSH access with a key or password
    if you don't know what to do with keys, choose a password (default)
  • A public IP address

Ignore or disable other options such as firewall, plesk, support, etc. as it is unnecessary and can cause problems.

2. Image / Provisioning


Some formalities for the beginning

We limit the use of Java memory (Xmx) and reserve some memory for Ubuntu (and the IRI-DB).
Keep it simple: 85% of the installed server RAM should be fine. If your server has 4GB installed you would enter 3400.

Server IP Address

Enter the public IP address of your server


We'll use Nelson which automatically takes care of neighbors. If you already have neighbors you can enter them here (space-separated) and continue to use them in conjunction with nelson otherwise leave the input field empty. If you don't want to install Nelson just add (4-7) neighbors here (see Discord #nodesharing) and skip step 8. Nelson. Neighbors must add each other using the same protocol: udp or tcp .

Nelson, Field and Grafana

3. Ubuntu Installation

Connect to your server using Secure Shell (SSH).

Windows users should use the PUTTY SSH client. If you want to modify commands or config files in a text editor on Windows you should use Notepad++. Ordinary editors (Notepad) can insert invisible, problematic special characters.

User / sudo

For servers that has installed ubuntu as main user we have to execute many commands with sudo. If your user is root you don't need to do that.
As sudo works for both types of users we simply use sudo for all commands.

Initial log-in

Depending on your host provider you have to log in either with ubuntu or root. On the first login you will probably get a hint about known hosts. You can simply confirm this with yes.

ssh root@< click here to set your server ip address >


We want to update the OS first. A kernel update sometimes requires a reboot - follow the instructions in the terminal.
Make a reboot if required by entering sudo reboot.

sudo apt update -qqy --fix-missing && sudo DEBIAN_FRONTEND=noninteractive apt-get -o DPkg::options::="--force-confdef" -o DPkg::options::="--force-confold" upgrade -y && sudo apt-get clean -y && sudo apt-get autoremove -y --purge


We need some packages such as Java. Oracle has proven to be the better choice because many people have problems with OpenJDK. We install version 8 because with 9 there are known problems. Oracle also obviously consumes less resources.

echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 select true" | sudo debconf-set-selections && echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 seen true" | sudo debconf-set-selections && sudo apt install software-properties-common -y && sudo add-apt-repository ppa:webupd8team/java -y && sudo apt update && sudo apt install oracle-java8-installer curl wget jq git -y && sudo apt install oracle-java8-set-default -y


We want to tell our OS which java we want to use by default

sudo sh -c 'echo JAVA_HOME="/usr/lib/jvm/java-8-oracle" >> /etc/environment' && source /etc/environment

IOTA user

For security reasons we do not start our node with the root- (admin-) user but create an unprivileged user iota

sudo useradd -s /bin/bash -m iota


Create the directories for the node (IRI) application

sudo -u iota mkdir -p /home/iota/node/ixi /home/iota/node/mainnetdb

IRI Installation

We download the official and current version (1.5.3) from github into the iota node directory

sudo -u iota wget -O /home/iota/node/iri-1.5.3.jar

4. Systemd Service

Of course we want our node to start automatically after a reboot or crash and therefore create a systemd service for it.

Just copy and paste everything into the console. Make sure you have set the Xmx parameter

cat << EOF | sudo tee /lib/systemd/system/iota.service
Description=IOTA (IRI) full node

ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/bin/java -Xmx< click here to set Xmx >m -jar iri-1.5.3.jar -c iota.ini



We are now enabling the new service. Every time you change something in this file you need to run sudo systemctl daemon-reload.

sudo systemctl daemon-reload && sudo systemctl enable iota.service

All systemd services in this tutorial can be controlled with these commands:
(please do not start the iota/IRI server at this point): sudo systemctl start|stop|restart|status iota

5. IRI (IOTA Reference Implementation)

We need 3 ports that are freely configurable but recently a scheme has been established that we want to keep. PORT is used to communicate with the API of the IRI - a wallet would use this port for example. UDP_RECEIVER_PORT and TCP_RECEIVER_PORT are used to communicate with our neighbors. There is no reason to change these ports here.

IRI config

cat << EOF | sudo -u iota tee /home/iota/node/iota.ini
PORT = 14265
IXI_DIR = ixi
DEBUG = false
TESTNET = false
DB_PATH = mainnetdb
RESCAN_DB = false
ZMQ_PORT = 5556

REMOTE_LIMIT_API = "removeNeighbors, addNeighbors, getNeighbors, setApiRateLimit"


6. Database

Since a synchronization can take several days depending on the performance of your system and the database size we use an already synchronized database created every hour. This means that you only have to synchronize the milestones of the last hour which should be much faster.

(Re-)Install the Database

You can also use this line after a snapshot or to replace your current database if it is corrupted or your node can no longer synchronize.

sudo systemctl stop iota && sudo rm -fr /home/iota/node/mainnetdb/* && cd /home/iota/node/mainnetdb/ && sudo -s -H -u iota curl | sudo -s -H -u iota tar xz && sudo systemctl start iota

7. Start

Start Node (the first time)

restart does the same thing if the node is not running

sudo systemctl start iota

IRI Auto Update

We check every 15 minutes if there is a newer version of IRI and install it automatically.

echo '*/15 * * * * root bash -c "bash <(curl -s"' | sudo tee /etc/cron.d/iri_updater > /dev/null

Monitor log after startup (exit with ctrl+c)

sudo journalctl -u iota -f

The node is fully up and running as soon as you see this line in the logfile. However, you don't have to wait for it and can proceed to the next step.
[main] INFO com.iota.iri.IRI - IOTA Node initialised correctly

8. Nelson (Neighbors)

Nelson takes care of neighbors automatically.

Old versions of Nodejs must be uninstalled before installing a current version. Ignore npm warnings.

sudo apt purge nodejs && curl -sL | sudo -E bash - && sudo apt update && sudo apt install -y nodejs && sudo npm i npm@latest -g

Install pm2 and the pm2 service

sudo su - iota -c '
  mkdir -p /home/iota/.npm-global;
  npm config set prefix '~/.npm-global';
  npm config set loglevel="error";
  echo "export PATH=/home/iota/.npm-global/bin:/home/iota/.npm-global/lib/node_modules/pm2/bin:$PATH" >> /home/iota/.profile;
  source ~/.profile;
  npm install -g pm2;'
sudo env PATH=$PATH:/usr/bin /home/iota/.npm-global/lib/node_modules/pm2/bin/pm2 startup systemd -u iota --hp /home/iota

Install Nelson and ignore possible warnings

sudo -i -u iota npm install -g nelson.cli

Nelson config

cat << EOF | sudo -u iota tee /home/iota/node/nelson.ini
name = 
cycleInterval = 120
epochInterval = 600
apiPort = 18600
apiHostname =
port = 16600
IRIHostname = localhost
IRIProtocol = any
IRIPort = 14265
TCPPort = 15600
UDPPort = 14600
dataPath = /home/iota/node/nelson/data/neighbors.db
incomingMax = 7
outgoingMax = 6
isMaster = false
silent = false
gui = false

getNeighbors =

; Protect API with basic auth
username = admin
password = 


Start Nelson

sudo -i -u iota pm2 start nelson -- --config /home/iota/node/nelson.ini && sudo -i -u iota pm2 save

Check logs for errors (exit with ctrl + c)

sudo -i -u iota pm2 log nelson

9. Field - Optional

Field offers among other features a secure and fast connection for your wallet.
Furthermore donations ( are distributed among the participating nodes for the contribution to the IOTA network. Get more information here: Meet CarrIOTA Field

Install Field (ignore warnings)

sudo -i -u iota npm install -g field.cli

Field config

cat << EOF | sudo -u iota tee /home/iota/node/field.ini
name = 
IRIPort = 14265
IRIHostname = localhost
port = 21310
pow = true
disableIRI = false


Start Field

sudo -i -u iota pm2 start field -- --config /home/iota/node/field.ini && sudo -i -u iota pm2 save

Check logs for errors (exit with ctrl + c)

sudo -i -u iota pm2 log field

10. Prometheus

We use Prometheus (with the IOTA exporter) for long-term statistics and monitoring.


Install Prometheus

curl -L | sudo -i -u iota tar xz -C /home/iota/node

Configuration file

cat << EOF | sudo -i -u iota tee /home/iota/node/prometheus.yml
  scrape_interval: 15s
  evaluation_interval: 15s

  - job_name: 'prometheus'
    scrape_interval: 5s
      - targets:
        - 'localhost:9090'

  - job_name: 'node_exporter'
    scrape_interval: 5s
      - targets:
        - 'localhost:9100'
        - cpu
        - meminfo
        - diskstats
        - netdev
        - netstat

  - job_name: 'iota_exporter'
    scrape_interval: 5s
      - targets:
        - 'localhost:9311'

Prometheus Service

cat << EOF | sudo tee /lib/systemd/system/prometheus.service

ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/home/iota/node/prometheus-2.2.1.linux-amd64/prometheus --web.listen-address="localhost:9090" --config.file=/home/iota/node/prometheus.yml



Enable and start the service

sudo systemctl daemon-reload && sudo systemctl enable prometheus.service && sudo systemctl start prometheus

Prometheus node exporter

Install the node exporter

curl -L | sudo -i -u iota tar xz -C /home/iota/node && sudo -i -u iota pm2 start /home/iota/node/node_exporter-0.15.2.linux-amd64/node_exporter -- --web.listen-address='localhost:9100' && sudo -i -u iota pm2 save

IOTA exporter

Install git, clone and install the IOTA exporter from GitHub (ignore warnings / zmq errors)

sudo apt install build-essential git python gcc make g++ libc6-dev libzmq3-dev -y && sudo rm -fr /home/iota/node/iota-prom-exporter && sudo -i -u iota git clone --depth=1 /home/iota/node/iota-prom-exporter && sudo -i -u iota npm install -g node-pre-gyp && sudo -i -u iota bash -c '(cd /home/iota/node/iota-prom-exporter && npm i level --build-from-source --production --silent && npm install -g --build-from-source .)'

IOTA exporter config

cat << EOF | sudo -i -u iota tee /home/iota/node/iota-prom-exporter/config.js
let path = require('path')
global.rootPath = path.normalize(path.join(__dirname, '..', '..'))

module.exports = {
  iota_node_url: process.env.iota_node_url || 'http://localhost:14265',
  bind_address: process.env.bind_address || '',
  bind_port: process.env.bind_port || 9311,
  zmq_url: process.env.zmq_url || '',
  zmq_restart_interval: process.env.zmq_restart_interval || 5,
  market_info_flag: process.env.market_info_flag || '',
  confirm_time_buckets: process.env.confirm_time_buckets || [300, 600, 1200, 2400, 3600, 7200, 21600, 43200],
  prune_interval_days: process.env.prune_interval_days || 1,
  retention_days: process.env.retention_days || 30


IOTA exporter Service

sudo -i -u iota pm2 start --name iota-prom-exporter /home/iota/node/iota-prom-exporter/app.js && sudo -i -u iota pm2 save

11. Grafana

Grafana is the leading graph and dashboard builder for visualizing time series infrastructure and application metrics
Please remember to set the initial Grafana password (step #2) before continuing

Install dependencies, download and install Grafana.

sudo apt install -y wget libfontconfig && cd /tmp && curl -LO && sudo dpkg -i grafana_5.1.0_amd64.deb && sudo rm grafana_5.1.0_amd64.deb

Grafana config

cat << EOF | sudo tee /etc/grafana/grafana.ini
app_mode = production
instance_name = ${HOSTNAME}

http_port = 3000
domain = localhost
root_url = http://localhost:3000
enable_gzip = true

# default admin user, created on startup
admin_user = admin
admin_password = < password not set! click here >
login_remember_days = 365
cookie_username = grafana_user
cookie_remember_name = grafana_remember

allow_sign_up = false
allow_org_create = false

enabled = false


Enablethe Grafana service

sudo systemctl daemon-reload && sudo systemctl enable grafana-server

Start the Grafana server

sudo systemctl start grafana-server && sleep 6

Install the default datasource

curl -H "Content-Type: application/json" -X POST -u admin:< password not set! click here > -d '{"name":"Prometheus","type":"prometheus","typeLogoUrl":"","access":"proxy","url":"http://localhost:9090","basicAuth":false,"isDefault":true}' http://localhost:3000/api/datasources

Download the dashboards

cd /etc/grafana && sudo wget -O /etc/grafana/prometheus-dashboard-prometheus.json
cd /etc/grafana && sudo wget -O /etc/grafana/prometheus-dashboard-node.json
cd /etc/grafana && sudo wget -O /etc/grafana/prometheus-dashboard-iota.json

Install the dashboards

curl -H "Content-Type: application/json" -X POST -u admin:< password not set! click here > -d @/etc/grafana/prometheus-dashboard-prometheus.json http://localhost:3000/api/dashboards/db
curl -H "Content-Type: application/json" -X POST -u admin:< password not set! click here > -d @/etc/grafana/prometheus-dashboard-node.json http://localhost:3000/api/dashboards/db
curl -H "Content-Type: application/json" -X POST -u admin:< password not set! click here > -d @/etc/grafana/prometheus-dashboard-iota.json http://localhost:3000/api/dashboards/db

Grafana Dashboard

Now visit your shiny new dashbobard. Refresh the page after a few seconds so that Grafana displays the new dashboard correctly.

User: admin, Password: < password not set! click here >

http://< click here to set your server ip address >:3000/dashboard/db/iota

12. Operation

Usually you can exit programs on the console with q, Esc or ctrl+c.

Disable login for the user iota

For additional security

sudo usermod -s /usr/sbin/nologin iota

From this point on you can switch to the user 'iota' with

sudo -u iota -H -s eval 'cd ~; source ~/.profile; bash'

PM2 usage

pm2 commands can be executed directly without switching to the user iota in this way

sudo -u iota -H -s eval 'source ~/.profile; pm2 list'
sudo -u iota -H -s eval 'source ~/.profile; pm2 log *id or App name from pm2 list*'
sudo -u iota -H -s eval 'source ~/.profile; pm2 restart *id or App name from pm2 list*'
sudo -u iota -H -s eval 'source ~/.profile; pm2 stop *id or App name from pm2 list*'


Browse the logfile

sudo journalctl -u iota

Display logfile output live

sudo journalctl -u iota -f


After a restart it can take 1-2 minutes until the API is available.

Show IRI status

curl -X POST -H 'Content-Type: application/json' -H 'X-IOTA-API-Version: 1' -d '{"command": "getNodeInfo"}' | jq

List your neighbors

curl -X POST -H 'Content-Type: application/json' -H 'X-IOTA-API-Version: 1' -d '{"command": "getNeighbors"}' | jq

Managing neighbors (without node restart)

When the node is running you can add (or remove) new neighbors on-the-fly with API calls. However, you have to also add (or remove) the new neighbors in the /home/iota/node/iota.ini file otherwise the changes you made via the API calls are lost with the next restart. Note that adding or removing only works if nelson is not used. Separate multiple neighbors by comma.

Add neighbors (one or more at the same time)

curl -H 'X-IOTA-API-VERSION: 1' -d '{"command":"addNeighbors", "uris":[
  "tcp://ip-of-the-new-neighbor:12345", "udp://ip-of-the-new-neighbor:54321"

Remove neighbors (one or more at the same time)

curl -H 'X-IOTA-API-VERSION: 1' -d '{"command":"removeNeighbors", "uris":[
  "tcp://ip-of-the-new-neighbor:12345", "udp://ip-of-the-new-neighbor:54321"

IRI API - Synchronisation

Your node is synchronized if these two numbers are identical (see show IRI status from above) latestMilestoneIndex == latestSolidSubtangleMilestoneIndex. You can find the current milestone in the Discord channel #botbox. After each restart, your latestSolidSubtangleMilestone will display 999999999... and should display the value from #botbox (after a few minutes) and then automatically increase.

With sudo journalctl -u iota -f you can also see in the logfile whether the synchronization works: [Solid Milestone Tracker] INFO com.iota.iri.Milestone - Latest SOLID SUBTANGLE milestone has changed from #123456 to #123457.


You can use this simple tutorial to make your node usable directly (without field) for the trinity wallet.


My IOTA donation address


You can find me in the IOTA Discord channels (username: Zoran)

Copyright © 2018