Production Ready Bitcoin Under systemd

Posted in Articles on Mar 22, 2015

Hi folks,

Finally, a new post! Today, we'll be investigating running bitcoind as a system-level service under systemd, the controversial service manager that many Linux distributions are starting to implement as the default - Ubuntu Vivid Vervet, Debian Jessie, Oracle Linux and RHEL have just added systemd as their default process manager between mid 2014 and now. Fedora, Arch Linux, Mageia, and openSUSE however have all been enabled by default for some years.

Starting cryptocurrency daemons under process managers has long been a relatively easy process, as they behave much like traditional Linux system daemons, so we'll look into how to set bitcoind up in a production ready environment. Systemd will be configured to run the daemon as a locked down system user, with a custom and protected data directory, and automatically restart the daemon if it happens to exit for any reason.

We will also set up the permissions so you can easily give your administrators control over the daemon via CLI. I'll be basing this guide on Bitcoin Core 0.10.0, although this same guide should work for core-0.9.x, and be easily modifiable for core-0.8.x.

Preparation

To start out, you need to create the following files, and fill them out with the content I provide...

/etc/systemd/system/bitcoin.service

[Unit]
Description=Bitcoin daemon service
After=network.target

[Service]
Type=simple
Restart=always
User=bitcoin
ExecStart=/usr/local/bin/bitcoind -datadir=/var/lib/bitcoin -conf=/etc/bitcoin.conf
ExecStop=/usr/local/bin/bitcoin-cli -datadir=/var/lib/bitcoin stop
PIDFile=/var/run/bitcoin/bitcoin.pid

[Install]
WantedBy=multi-user.target

/etc/logrotate.d/bitcoin

This file ensures bitcoind's log files don't overfill the partition on which they're stored.

/var/lib/bitcoin/debug.log {
        create 640 bitcoin bitcoin
        daily
        rotate 14
        compress
        sharedscripts
        postrotate
            killall -HUP bitcoind
        endscript
}

/etc/bash.bashrc or /etc/bashrc

Modify whichever of these two files already exists. This wraps the bitcoin CLI binary with its runtime configuration, so instead of running the whole command, we can just type bitcoin instead. Do NOT replace the whole file with this content, APPEND it to the end.

alias bitcoin="/usr/local/bin/bitcoin-cli -datadir=/var/lib/bitcoin -conf=/etc/bitcoin.conf"

/etc/bitcoin.conf

rpcuser=bitcoinrpc
rpcpassword=Sup3RsecR3tpa45sW0rdg0E5hEr3+!|
server=1
pid=/var/run/bitcoin/bitcoin.pid

Software Installation

Ok, now we're ready to install the daemon and its utilities into /usr/local/bin, as we're going to use the pre-compiled daemon from the Bitcoin website. This will save us having to worry about dependencies the binaries are statically compiled. This does, however, come at the expense of having to manage the daemon's versions ourselves and upgrade them manually as required. Navigate to the folder into which you would like to download the software, and enter the following, but change VERSION or ARCH depending on your server's distribution and the latest available client version:

export VERSION="0.10.0"
export ARCH="64"
wget https://bitcoin.org/bin/bitcoin-core-$VERSION/bitcoin-$VERSION-linux$ARCH.tar.gz
tar -xf tar -xf bitcoin-$VERSION-linux$ARCH.tar.gz
sudo cp bitcoin-$VERSION/bin/bitcoin* /usr/local/bin

Set up the base environment

We need to create a standard set of folders, which follow the same pattern as most other Linux daemons. Bear in mind that while this guide is designed pretty generically and should work for any standard Linux distribution that follows the Linux Filesystem Hierarchy Standard closely, if your favourite distribution deviates from it, then you may need to modify the guide - so make sure you know your distribution inside out before going much further! Run the following command:

sudo mkdir /var/{lib,log,run}/bitcoin

We now create a system user to handle the service, and a group if the system doesn't create one automatically:

sudo useradd -r -s /bin/false -d /var/lib/bitcoin bitcoin
[[ ! $(grep bitcoin /etc/group) ]] && (sudo groupadd bitcoin && sudo usermod -aG bitcoin bitcoin)
echo "umask 037" | sudo tee /var/lib/bitcoin/.profile
sudo chown -R bitcoin:bitcoin /var/{lib,log,run}/bitcoin
sudo find /var/lib/bitcoin -type f -exec chmod 640 {} \;
sudo find /var/lib/bitcoin -type d -exec chmod 750 {} \;

This series of commands sets up sane defaults for the system user's environment. It ensures there is a system user and group with the name "bitcoin", and that the user only ever creates files that have permissions of 640 (user read/write, group read, other refuse access).

This means that only the users "bitcoin" and "root" can create files in its home directory, and that files created by the bitcoin user can also be read by any other user in the bitcoin group. This will allow other administrators than those with root access to be able to read the daemon's logs and debug it as required, but not to make changes to any of the daemon's files.

Logging

Now we are going to set up a symbolic link to standardise the location of bitcoind's log files. Enter the following commands, to ensure that bitcoind's log file is viewable from /var/log/bitcoin.log. It would be even better if we could output stderr to /var/log/bitcoin.err, but I couldn't work out how to make systemd do this without throwing bitcoind's logging to std{out,err} and redirecting again it from syslog, which is out of the scope of this guide.

sudo ln -s /var/lib/bitcoin/debug.log /var/log/bitcoin/debug.log
sudo ln -s /var/lib/bitcoin/db.log /var/log/bitcoin/db.log
sudo chown root:bitcoin /var/log/bitcoin/*
sudo chmod 660 /var/log/bitcoin/*

This file does not exist yet, so your symlink will currently be dangling. Don't worry about it for now. When we start the bitcoin service, it will cease to be broken.

Bitcoin Daemon Configuration

The file we set up before at /etc/bitcoin.conf needs to be further configured to be ready for production. First of all, change the rpcpassword field to be something unique, long and secure. Make sure it's a decent length. I suggest 32 characters or more.

Now we can set up the permissions:

chown root:bitcoin /etc/bitcoin.conf
chmod 640 /etc/bitcoin.conf

This will make sure that the configuration file cannot be edited by anybody except root (not even the bitcoin user itself), and can only be read by those who are members of the bitcoin group.

Done! Start the service!

We've reached the final stages. Here we'll enable the service to start on boot and test it out!

sudo systemctl daemon-reload
sudo systemctl enable bitcoin
sudo service bitcoin start

You should be able to now see the daemon starting by running `tail -f /var/log/bitcoin.log` while logged in as either root, or a user you have added to the bitcoin group with `usermod -aG bitcoin USERNAME`. If the file doesn't exist, you need to debug the systemd service, which will probably involve grepping systemd from /var/log/syslog.

If all has gone well, however, reboot the system and make sure bitcoind is running with `pgrep bitcoind`. If it isn't, time to check syslog for potential systemd failures.

If anybody has any improvements or questions, contact me via one of my social media accounts on the Contact page!