How To Create A Monero Service in Linux: Part 1 – Configuration

Introduction

In this post I will explain how to turn your monero daemon into a service, a monerod instance that will be stopped and started automatically by the system.

Then in Part 2 we will cover troubleshooting a service that won’t start.

Finally in Part 3 we will consider security issues, such as using selinux and firewalld.

What is the Monero Daemon?

Simply put monerod, is software that sits in between wallets (clients) and the rest of the monero network (other servers). An instance of monerod is itself part of the monero network. That is, it receives and validates blocks and, in the case of a ‘full node’ daemon, maintains a copy of the blockchain. If a wallet is connected, it will also validate and forward any transactions for that wallet to and from the network.

Why Run Monerod?

When you run your own daemon you’re contributing to the distributed nature of the blockchain by maintaining your own copy. You also provide a trusted place for your own wallets to connect to. Unlike in many other crypto-currencies, in Monero the wallet software is completely decoupled from the blockchain software.

Why Run Monerod as a service?

Services are generally things you want to be persistent. There is blockchain activity around the clock, and if you’re running a daemon, you probably want it to be up to date. When you create a service you are handing over some of the management of that service to the system. For example, your system will automatically start the service and grant it the appropriate resources.

Wallets are different, you really only need to sync them when you need to check balances or transact. Transactions are not stored in a wallet, only cached. Your transactions are always preserved on the blockchain.

Assumptions

We will run a full node, hosting a copy of the entire blockchain, and we will not be mining.

If you want to mine you can still benefit from running your own daemon, but it is recommended to use a dedicated miner such as XMRig.

Operating System

While this guide uses Centos 8, the configuration should be almost identical on any recent Fedora or Red Hat system. And the basic steps should be similar on any recent Linux system which uses systemd as the init manager.

Command-Line Only

A graphical interface is unnecessary for this guide, so we will use the command-line version of monero. Also I just like doing everything by command-line.

Root Access

All commands are being run as root (even if prompt says ‘>’). You can of course use sudo instead.

Angle Brackets

Replace any values enclosed in <> with your own.

Snipped Text

The exception is <..> which I used to indicate where unnecessary text has been snipped.

Text Editor

I’m using vim as a text editor, but feel free to substitute vi for nano or another editor of your choice.


Planning

System Resources

Normal Conditions

monerod is not particularly CPU and memory hungry, once it is synced, and as long as you’re not mining,  The main activity that consumes resources is validating new blocks when they come in. For this task it uses moderate amounts of CPU, and relatively smalls amounts of memory, disk IO and network bandwidth.

Initial Conditions

The most resource-intensive time is when initialising a new full node.

By default monerod will download a fresh copy of the entire blockchain from the server, validating each block as it goes. This can take days and consume a fair bit of CPU and network bandwidth. Even if you use an existing or partial copy of the blockchain in a new daemon, there are still resources consumed.

Even so, the average system today will have plenty of CPU and memory for this task, and the main bottleneck is most likely to be disk.

Disk Space

At time of writing the monero blockchain is just under 100 GB and growing at a rate of ~1GB a month. The bulk of this is in one single file.

As such, the first step is to have a filesystem with enough free space for now, and to have some kind of strategy for future growth. Your strategy may be just having plenty of free space. Or you may have a logical volume that you can expand later with extra disks or by expanding the filesystem.

For this guide I am going to assume you have an additional filesystem, mounted at /opt and with at least 110 GB free space. But in principle there is no issue with using your home directory instead.

Disk Speed

Fast disk will help a lot. monerod will even warn you about it at startup:

The blockchain is on a rotating drive: this will be very slow, use an SSD if possible

The big requirement here is for fast reads. Monero will mostly only write one block at a time, being the last block – by definition past blocks are supposed to be immutable, at least after a few are confirmed. But there may be situations where monerod will need to walk through the entire blockchain.

Ideally you would install the data-dir on an SSD. Failing that, spinning disks in a RAID 1 or 5 will help. My system uses SAS disks in a RAID5 configuration which is perfectly ok for me. But note I haven’t actually tested with SSDs to see how much faster it actually is. It might cut down the initial sync by hours or more. Overall, use the best disk you have

CPU

The monero daemon is threaded and will use more cores when available. However, it’s possible to run on only 1 core without issue. If using a VM, I would recommend starting with between 2 and 4 cores and then experiment to find the optimal number.

Memory

Answering the question “how much memory does monerod need under Linux?” is a difficult one because of how Linux manages memory. As a rough guide, and on a system doing no heavy loads, 2GB will be ok but 4GB is better.

I suspect that giving a dedicated monero server more than 4GB will provide diminishing returns. For example, on my system with 36GB, Linux reports that monerod is virtual memory mapping just under 3GB, not including the blockchain itself. This figure includes shared libraries so the amount of additional memory required is going to be less than 3GB.

Large Pages

Large pages allow the operating system to allocate memory to processes in larger ‘chunks’ than normal. This can be more efficient for processes that churn through a lot of RAM. The downside is that any RAM allocated to huge pages is completely unavailable to regular pages, and not every process can use or even benefit from huge pages. So you can only allocate some fraction of your total RAM.

I have seen that monerod will use 100-200 2MB pages (200-400MB) when available, but it does not seem capable of using 1GB pages. This is not a lot of RAM, so I doubt it makes much difference at all performance-wise. Having said that large pages is very handy for mining and perhaps that’s why monerod supports it.

Overall large pages are probably going to make no practical difference to a full node, but won’t hurt either.

Network Bandwidth

Whatever you need to download 100+ GB in a reasonable time in the initial sync. After that, not a lot.


Installing

Monero Package

Login to your CLI and download the latest Linux CLI package from the Monero Project.

mkdir /opt/crypto
cd /opt/crypto
wget https://downloads.getmonero.org/cli/linux64

For later clarity we will rename the download package to a more useful name. For example:

mv linux64 monero-x86_64-linux-gnu-v0.17.1.9.tar.bz2

Extract the package and then create a soft link from the created folder to a new folder simply called monero.

tar -xjvf monero-x86_64-linux-gnu-v0.17.1.9.tar.bz2
	# extracts folder monero-x86_64-linux-gnu-v0.17.1.9
ln -s monero-x86_64-linux-gnu-v0.17.1.9 monero
	# creates a softlink

The purpose of the soft link is so that we can upgrade our monero package as new ones are released without changing any external references to the path /opt/crypto/monero. We just need to remove and create a new soft link.

Monero User

We are also going to create a dedicated user account to run the monero daemon. This is a Linux best practice.

The monero user will have no login or shell privileges, it will be used by the system directly.

useradd --no-create-home --home-dir /opt/crypto/monero-data -s /sbin/nologion --system monero

Data Folder

We do not want a separate copy of the blockchain for each version of Monero, so we will keep that in a separate folder.

Here we have called it monero-data. The Monero Project refers to this as the ‘data directory’. Create the directory. Note this is one level up from the monero package directory we extracted.

mkdir /opt/crypto/monero-data

Update Permissions

The daemon will need to write to the data directory, so change the ownership of this folder to the monero user.

chown -R monero /opt/crypto/monero-data

Your directory listing should now look something like this:

> ls -1 /opt/crypto
monero
monero-data
monero-x86_64-linux-gnu-v0.17.1.9
monero-x86_64-linux-gnu-v0.17.1.9.tar.bz2

Configuring

We should be ready to create our service now.

Systemd

What is systemd?

Systemd is the system init manager in Centos 8, and most other Linux systems today. That means it is the first process started by the kernel, ‘process id 1’, and is responsible for starting and stopping every other process on the system.

Another init system you might encounter on some distributions is Sys V. Note other types of init systems work completely differently to systemd and are not covered by this guide.

Create the Unit File

A systemd service configuration is called a unit file. Services are just one type of unit in systemd.

Create the unit file:

vi /etc/systemd/system/monerod.service

..and add the text below.

[Unit]
Description=Monero Daemon
Documentation=https://getmonero.org
After=network.target

[Service]
User=monero
Group=monero
Type=idle
ExecStart=/opt/crytpo/monero/monerod --config-file /etc/monerod.conf --non-interactive
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
  • After tells systemd when to start the service
  • ExecStart which tells systemd how to start the service.
  • User and Group tells systemd who should run the service

Save the file and issue the following command to let systemd know there’s been a change to a unit file.

systemctl daemon-reload

Monerod Configuration File

We also going to maintain a separate configuration file for monerod. This is a more manageable alternative than passing command-line arguments to monerod in the unit file.

Create the following file. Note that this file does not need to be owned by the monero user.

vi /etc/monerod.conf

..and add the following text

data-dir=/opt/crytpo/monero-data
rpc-bind-ip=0.0.0.0
rpc-bind-port=18081
confirm-external-bind=1
restricted-rpc=1
log-level=0

Monerod Options

This will provides a few basic options to monerod when it starts. For a complete list of options to monerod, read:

/opt/crypto/monero/monerod --help

Here’s a brief explanation of these options:

data-dir overrides the default location for the monero blockchain (normally /root/.bitmonero).

rpc-bind-ip tells the daemon which interfaces to listen on. 0.0.0.0 means listen on all interfaces, which will be suitable for most people. This will allow connections from wallets on other systems. If you only want the service to listen on the loopback interface, simply comment the rpc-bind-ip option with a ‘#’.

rpc-bind-port is the TCP port that wallets will connect over. RPC stands for remote procedural call. Basically it’s an API to the daemon. Note that it is not actually using the old but still common RPC protocol, but a monero-specific version inspired by it.

confirm-external-bind confirms you want to allow connections from wallets that aren’t on this system, such as when binding to 0.0.0.0.

restricted-rpc furthers restricts what information can be requested from the daemon by any client. It’s best to enable this unless you need otherwise.

log-level increases log verbosity when > 0

Note

If you want allow some other systems to connect to your daemon but not others, we will cover firewalling your service in Part 3, but for now the daemon is not running so the port is still closed.

Use an existing copy of the monero blockchain

If you already have a copy of the blockchain, even one that may be out of date, you can potentially save a lot of time by reusing it. But it doesn’t necessarily make the whole process fast. If you don’t have an existing copy feel free to skip to the next section.

Your existing copy should be in a folder somewhere called lmdb and contain two files:

> ls -l lmdb/
total 101013504
-rw-r--r--. 1 monero root 103437815808 Jan 17 19:54 data.mdb
-rw-r--r--. 1 monero root         8192 Jan 17 19:54 lock.mdb

Move or copy this folder to the new data directory.

cp -r <source_dir>/lmdb /opt/crypto/monero-data

If all goes well, the blockchain will be revalidated by the service when we start it and then updated to the latest block. It does not always save much time however, so don’t be too concerned if you don’t have an existing copy.

Tip

Later when we start our service, monerod may report that your existing copy is corrupted. If so you can try adding the following option to your monerod.conf:

db-salvage=1


Enabling

Viewing Logs

We are almost ready to try and start the service. But before we do let’s up open another terminal, one that we will use for monitoring our logs (I’ll show activity on that terminal if different colours from here).

In our unit file, we told systemd to use journald for logging.

StandardOutput=journal
StandardError=journal

journald is the default logging collector for any system running systemd. Even though it still inspires plenty of hate among the Linux user community, it has many advantages over traditional syslog which writes to text files. We’ll cover the basic commands to monitor your service via journald below.

Once you are logged in as root, type the following:

journalctl -ef

This will display the last 100 or so logs captured by the system, and also start following new logs (similar to the tail -f you might run on a text log file).

If there are too many logs being displayed we can filter down to the relevant ones like so.

journalctl -ef -t systemd -t setroubleshoot -t monerod

This instructs journald to only show logs from the units named systemd, and monerod.

Another useful option to journalctl is the -g option, which allows you to filter on any message text. For example:

journalctl -ef -g "monero"

First attempt: Enabling the service

Let’s start and enable the service in one shot. Enabling means that the service will be started automatically at boot from now on.

Go back to the other terminal and enter the following.

systemctl enable --now 

Basic Management of Systemd Services

For future reference, the basic commands for starting and stopping the service are as follows.

systemctl start monerod
systemctl stop monerod
systemctl restart monerod        
	# shorthand for stopping then starting the service

You can check the current status of the service as follows. This command will also show the last few journal lines which may be useful when troubleshooting or to confirm normal activity at any point:

systemctl status monerod

Checking the Service Status

So let’s try this ourselves. I usually wait a few seconds after starting a service to give the journals time to catch up:

> systemctl status monerod
â monerod.service - Monero Daemon
Loaded: loaded (/etc/systemd/system/monerod.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2021-02-15 12:49:44 AEDT; 5 days ago
Docs: https://getmonero.org
Main PID: 1493 (monerod)
Tasks: 30 (limit: 230032)
Memory: 1.1G
CGroup: /system.slice/monerod.service
1493 /kvm/cc/monero/monerod --config-file /etc/monerod.conf --non-interactive
<..logs..>

You are looking for active and enabled. If you see anything else, we are going to cover troubleshooting in Part 2.

Checking Startup Logs

Now switch back to your logging terminal and you should see something like below:

Jan 17 19:59:15 crypto.upaya.net.au systemd[1]: Started Monero Daemon.
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.816        I Monero 'Oxygen Orion' (v0.17.1.9-release)
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.816        I Initializing cryptonote protocol...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.816        I Cryptonote protocol initialized OK
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.817        I Initializing core...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.817        I Loading blockchain from folder /kvm/cc/monero-data/lmdb ...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.817        W The blockchain is on a rotating drive: this will be very slow, use an SSD if possible
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.896        I Loading checkpoints
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.897        I Core initialized OK
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.897        I Initializing p2p server...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.903        I p2p server initialized OK
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.903        I Initializing core RPC server...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.903        I Binding on 0.0.0.0 (IPv4):18081
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.903        I core RPC server initialized OK on port: 18081
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.904        I Starting core RPC server...
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.904        I core RPC server started ok
Jan 17 19:59:16 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:16.904        I Starting p2p net loop...
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I **********************************************************************
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I The daemon will start synchronizing with the network. This may take a long time to complete.
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I You can set the level of process detailization through "set_log <level|categories>" command,
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING).
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I Use the "help" command to see the list of available commands.
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I Use "help <command>" to see a command's documentation.
Jan 17 19:59:17 crypto.upaya.net.au monerod[167062]: 2021-01-17 08:59:17.905        I 
<..>

Note

Some of these startup messages seem to suggest your daemon while accept interactive commands. This is not the case. You will not be able to type anything into the service and have it respond. That’s part of the point of having it as a service – monerod will not be tied to particular user being logged or a particular shell & terminal process.

Summary

With luck your service is now downloading and validating 100GB of blockchain! Expect this to take several days the first time.

Now, if your service is not active and you don’t seem to see the right logs, then it’s time to troubleshoot! Head over to Part 2 – Troubleshooting.


Connecting a CLI Wallet

This is not a full guide to using the CLI wallet. Just a quick note on which options you’ll need to work with your new service and connect a wallet located on another system:

/opt/crypto/monero/monero-wallet-cli --daemon-address <system-ip>:<rpc-bind-port> --wallet-file <path-to-wallet>

Once you enter your wallet password, you should see the wallet connecting to the daemon and starting to refresh. If your wallet is reporting any connection issues it may be a firewall problem. We’ll cover that in Part 3 – Security.

Leave a Comment

Your email address will not be published. Required fields are marked *