Run Your Own Monero Node

Running your own Monero node can be a challenging, yet rewarding experience that gives you a better understanding how the anonymous cryptocurrency functions to protect your financial privacy – including balances & payment information.

Like other cryptocurrencies such as Bitcoin, the Monero network comprises of full nodes that sync with other nodes (peers) to maintain a copy of the distributed ledger, rebroadcast transactions, and optionally, mine blocks to secure the network.

To use Monero, you need a “wallet” which serves as a client application that connects to either a local daemon or remote node. By default, the official Monero wallet from getmonero.org starts a local daemon when you launch the software. Before you can check the balance of an existing wallet or send funds to others, the local daemon must download a complete copy of the blockchain – a process that can take two days or more depending on the speed of your Internet connection and whether you have a SSD or not.

Since the initial sync is a time-consuming process, many users opt to use a remote public node instead. In fact, we maintain a remote node at node.moneroxmr.org:18089 hosted in DigitalOcean’s AMS3 datacenter for the community to use. In effect, you are relying on a copy of the blockchain hosted on another machine over the Internet. No initial sync is needed, allowing the wallet to rapidly scan the blocks to determine balance and incoming transactions.

There are some privacy & security considerations to consider when using a remote node you do not own or control. Fortunately, a node cannot withdraw your funds unless you sign the transaction on your own computer, because your private keys are never shared with it.

On the other hand, you give up some privacy by revealing your IP address to the node, and associating it with your transaction IDs. This alone does not reveal your Monero balance, nor the amount or destination address of your transactions. However, a malicious node or man-in-the-middle (MITM) could deliberately cause your first attempt to send a transaction to return an error. Should you retry the payment, the new versus old ring signature (RingCT) could be compared to deduce the real from the decoy inputs that Monero uses to obscure your transactions.

Therefore, the best practice from an operational security (OpSec) standpoint would be either to use a local daemon, or a Monero node you control yourself. We realize it can be a hassle to sync the latest blocks each time you open your wallet, especially if you use Monero across multiple devices. Besides, the Monero blockchain is in excess of 52 GB as of May 2018, and will only continue to grow, taking up storage on every device set to “local daemon.”

By setting up a dedicated Monero node, you can always stay in sync with the latest blocks and conserve storage capacity, while avoiding the privacy pitfalls especially if you host the node within your local network. Using a VPS on the cloud is also okay, however it requires trusting any logs with your cloud provider and you should be wary of resending failed transactions, to mitigate the risk of a MITM attack that could compromise your privacy.

Running a node is also encouraged because it strengthens the Monero network. Monero users near your country or region will be able to download blocks and perform on-chain transactions faster and more reliably. Maintaining an additional copy of the blockchain also supports decentralization by making it less likely the immutable ledger can ever be destroyed or tampered with. If you own Monero as an investment, running a node supports the health of your investment.


Walkthrough — Set Up & Secure a Monero Full Node

In this tutorial, you will learn how to set up a Monero full node on DigitalOcean using the 2 GB, 1 vCPU Droplet ($10/month) and an attached block storage volume ($0.10 GB/month). The operating system used will be Ubuntu 18.04 64-bit. Sign up for DigitalOcean using this link for a free $10 credit.

The process is easy to adapt if you wish to set up a node locally, or with a different hosting provider — however the names of the block device (/dev/…) for mounting the external storage will vary.

If you are creating the Monero node within your LAN, you must forward ports 18080 (P2P), and 18081 or 18089 (RPC) to it from your router if you wish to access it over the Internet. If you only plan to access the node from a client on your local network, you can open port 18080 exclusively, which allows other Monero nodes to peer with your node.

This guide was last updated May 15, 2018 and reflects the process to install a Monero node using version 0.12.0.0, Lithium Luna. You can always find the latest version of the Monero wallet & daemon at the official download page.

Support my work: If this guide was helpful, I would appreciate a donation to XMR address: 83JyUuuGYBPJaAppobubt4P4Q4c8iZ3sFRCepEsJaeASLcNXB23djQBGVGy6uSF9kFc7D8M9afxcBJDwcU73LBsk7pRV9Mt

Create the Cloud Instance

Provision a new DigitalOcean compute instance in a region supporting Block Storage Volumes (NYC1, NYC3, SFO2, FRA1, SGP1, TOR1, BLR1, LON1, and AMS3) with the 2 GB, 1 vCPU plan or above using the Ubuntu 18.04 x64 image. Attach a 100 GB (or larger) external volume to the instance.

By default, the Monero data directory (data dir) is stored in the user’s home directory at ~/.bitmonero. However the root partition (50 GB SSD with 2 GB, 1 vCPU Droplet) is too small compared to the eventual size of blockchain LMDB and Monero logs. Configuring the data dir in an external volume (e.g. /mnt/monero_data/.bitmonero) instead makes the implementation scalable by simply expanding the volume size and remounting it.

Add a Regular User Account

Connect to the cloud instance as root by SSH, using the root password or SSH key you supplied when provisioning it. The Monero daemon (monerod) does not need to be run as root, so we will first create a regular user account, monero.

Specify a long & secure password for this user when prompted, and retype to verify.

adduser monero

Add this user to the sudo group so it can perform privileged commands using sudo or sudo su.

usermod -aG sudo monero

For enhanced security, set up public key authentication for this user. If you don’t have a SSH keypair, here are instructions to generate a RSA key on Mac OS/Linux using OpenSSH in the Terminal, or Windows using PuTTYgen. Make sure to replace your public key below with your actual public key string, which begins with ssh-rsa followed by a long string of random characters.

login monero

mkdir -p ~/.ssh

chmod 0700 ~/.ssh

touch ~/.ssh/authorized_keys

chmod 0644 ~/.ssh/authorized_keys

echo “ssh-rsa your public key” >> ~/.ssh/authorized_keys

Then, disable password authentication and root login over SSH by modifying PermitRootLogin and PasswordAuthentication to no in the SSH server-side configuration file, then restart the SSH daemon.

sudo nano /etc/ssh/sshd_config


PermitRootLogin no

PasswordAuthentication no

sudo service sshd restart

Configure Firewall and Open Ports

The Monero daemon supports incoming connections on a P2P and RPC port. The P2P port, 18080 by default, permits other Monero nodes to download new blocks from your node. The RPC port, 18081 by default, allows you to use your server as a remote node.

Opening neither of these ports is mandatory, however we suggest letting both through on your firewall to contribute to the Monero network. In fact, if you want to set up a public node, you should use RPC port 18089 instead to have MoneroWorld include your node in the list of IP addresses others can connect to.

This firewall configuration explicitly permits inbound traffic on ports 18080 (Monero P2P), 18089 (Monero RPC), and 22 (SSH), and has a default policy of allowing outbound traffic. The netfilter-persistent package is installed to persist the firewall configuration between restarts.

sudo apt update && sudo apt-get upgrade

sudo iptables -A INPUT -i lo -j ACCEPT

sudo iptables -A OUTPUT -o lo -j ACCEPT

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

sudo iptables -I INPUT -p tcp --dport 18080 -j ACCEPT

sudo iptables -I INPUT -p tcp --dport 18089 -j ACCEPT

sudo iptables -P INPUT DROP

sudo iptables -P FORWARD DROP

sudo iptables -P OUTPUT ACCEPT

sudo apt install iptables-persistent netfilter-persistent

sudo netfilter-persistent save

Set up a Swap File

Set up a swap file to prevent the Monero daemon from crashing by running out of memory. The instance we selected with 2GB physical RAM is sufficient to run a small Monero full node once it is fully synced, however, the initial sync requires more memory.

sudo fallocate -l 4G /swapfile

sudo chmod 600 /swapfile

sudo mkswap /swapfile

sudo swapon /swapfile

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Mount the Attached Block Storage Volume

The block storage volume you created when provisioning the cloud instance must be mounted before it can be used by the system. For the purposes of this tutorial, we will be using this volume to store Monero data, therefore, it will be formatted, mounted at /mnt/monero_data, and added to /etc/fstab using the following commands.

Where xxx# is the DigitalOcean datacenter you launched your instance in lower case. For example, the AMS3 datacenter would be denoted as /dev/disk/by-id/scsi-0DO_Volume_volume-ams3-01

sudo mkfs.ext4 -F /dev/disk/by-id/scsi-0DO_Volume_volume-xxx#-01

sudo mkdir -p /mnt/monero_data; sudo mount -o discard,defaults /dev/disk/by-id/scsi-0DO_Volume_volume-xxx#-01 /mnt/monero_data; echo /dev/disk/by-id/scsi-0DO_Volume_volume-xxx#-01 /mnt/monero_data ext4 defaults,nofail,discard 0 0 | sudo tee -a /etc/fstab

Install Git and Dependencies

Install git, and the dependencies required for Monero.

sudo apt install git

sudo apt install build-essential cmake doxygen graphviz miniupnpc pkg-config libboost-all-dev libcurl4-openssl-dev libgtest-dev libminiupnpc-dev libreadline-dev libssl-dev libunbound-dev libunwind8-dev libzmq3-dev

cd /usr/src/gtest

sudo cmake .

sudo make -j2

sudo mv libg* /usr/lib/

Build and Install Monero

Download the source code for Monero from GitHub and build it on your machine. Then, install Monero by copying the binaries to /usr/local/bin/.

mkdir ~/source

cd ~/source

git clone --recursive https://github.com/monero-project/monero

cd monero

make -j2 release

sudo cp ./build/release/bin/* /usr/local/bin/

Configure Monero as a System Service

Since you are running a dedicated Monero node, you will want to configure Monero to start at every boot by configuring it as a system service. For now, we will be creating the service but will not be enabling nor running it until a later step.

sudo touch /lib/systemd/system/monerod.service

sudo nano /lib/systemd/system/monerod.service

[Unit] Description=Monero Full Node
After=network.target

[Service] User=monero
Group=monero
WorkingDirectory=~
RuntimeDirectory=monero

# Clearnet config
#
Type=forking
PIDFile=/run/monero/monerod.pid
ExecStart=/usr/local/bin/monerod –restricted-rpc –block-sync-size 3 –confirm-external-bind –config-file /mnt/monero_data/.bitmonero/monerod.conf –detach –pidfile /run/monero/monerod.pid

# Tor config
#
## We have to use simple, not forking, because we cannot pass –detach
## because stderr/stdout is not available when detached, but torsocks
## attempts to write to it, and fails with ‘invalid argument’, causing
## monerod to fail.
#Type=simple
#Environment=DNS_PUBLIC=tcp
## The following is needed only when accessing wallet from a different
## host in the LAN, VPN, etc, the RPC must bind to 0.0.0.0, but
## by default torsocks only allows binding to localhost.
#Environment=TORSOCKS_ALLOW_INBOUND=1
#ExecStart=/usr/bin/torsocks /usr/bin/monerod –config-file /etc/monerod.conf \
#    –non-interactive

Restart=always

[Install] WantedBy=multi-user.target

Create a monerod.conf Config File

The Monero configuration file (monerod.conf) specifies where you would like Monero to store its data dir, log and which RPC port it should listen on.

mkdir -p /mnt/monero_data/.bitmonero

cd /mnt/monero_data/.bitmonero

touch /mnt/monero_data/.bitmonero/monerod.conf

nano /mnt/monero_data/.bitmonero/monerod.conf

data-dir=/mnt/monero_data/.bitmonero
log-file=/mnt/monero_data/.bitmonero/monero.log
log-level=0
rpc-bind-ip=0.0.0.0
rpc-bind-port=18089

Import the Bootstrap Directly from getmonero.org (Optional)

To speed up the initial blockchain sync, you may download the latest blockchain.raw (bootstrap) directly from downloads.getmonero.org. The bootstrap will include all but a few of the blocks that were generated after the dump was published by the Monero team. This is the only trusted source to download the bootstrap file.

Assuming you haven’t started the monerod service before, the lmdb directory should be blank in your data dir. Otherwise you should first delete the data.mdb and lock.mdb files before proceeding with an import.

rm -f /mnt/monero_data/.bitmonero/lmdb/data.mdb

rm -f /mnt/monero_data/.bitmonero/lmdb/lock.mdb

Download the Monero bootstrap file from getmonero.org to the server to initiate the import. First ensure that the Monero daemon is not running by checking service monerod status — otherwise the import will fail.

cd /mnt/monero_data

wget https://downloads.getmonero.org/blockchain.raw

cd /usr/local/bin/

nohup ./monero-blockchain-import --guard-against-pwnage 0 --input-file /mnt/monero_data/blockchain.raw --data-dir /mnt/monero_data/.bitmonero &

Note that the command above includes the --guard-against-pwnage 0 flag which turns off verification of the file being imported. You should only ever use this option if you are importing from a trusted source, either downloaded directly from downloads.getmonero.org over HTTPS, or generated using the monero-blockchain-export tool from another machine you control. If you transfer the .raw file over an untrusted network such as the Internet, be sure to use an encrypted link such as SCP, rsync over SSH, or HTTPS.

By appending nohup to the command, the import will continue running even if the SSH session is terminated. Please be patient, it may take a few hours. You can check whether the process has completed anytime by opening another SSH session and typing in this command to check the background process log.

tail -f ~/nohup.out

2018-05-11 13:39:11.613     7f93b835c5c0 INFO bcutil src/blockchain_utilities/blockchain_import.cpp:553 Finished at block: 1540000  total blocks: 1540001

Once you see output stating “Finished at block” and “total blocks” similar to the above, the blockchain import has completed and you may proceed to start the Monero daemon. Remember to remove the blockchain.raw file using rm -f /mnt/monero_data/blockchain.raw to free up disk space.

Enable and Run the Monero Service

Congratulations! If you got to this stage you are ready to start your Monero node and begin syncing the blockchain. It may take a day or more to download the entire blockchain from other nodes if you haven’t manually imported it from getmonero.org.

sudo systemctl enable monerod

sudo service monerod start

You can monitor the progress of the initial sync by viewing the logs written to /mnt/monero_data/.bitmonero/monero.log in real time. Use Ctrl-C to return to the interactive terminal once done.

tail -f /mnt/monero_data/.bitmonero/monero.log

Once the node is synced up to the current block height of the Monero network, this message will be written to the log.

**********************************************************************
You are now synchronized with the network. You may now start monero-wallet-cli.

Use the “help” command to see the list of available commands.
**********************************************************************

Connect to the Monero Remote Node

At this time, you can connect to the remote node from the GUI or CLI wallet on your PC — where node.moneroxmr.org is replaced with the public IP address or hostname of your own node. To give your node a real domain name instead of a bare IP address, simply register a domain at any ICANN-accredited registrar and create an A record pointing to your node’s IP address in the DNS zone file.

Monero GUI Wallet

“Remote Node” should be greyed out to indicate you have chose to connect to a remote node. Once the Monero client has finished scanning the balance of your wallet against the blocks provided by the remote node (using your view key locally), it will show “Wallet is synchronized” on the lower left hand corner.

Below, it shows the current block height of the remote node you are using. If that number is within one or two blocks of the block height displayed at MoneroBlocks.info, the daemon running on your remote node is up to date.

Monero CLI Wallet

monero-wallet-cli --daemon-address node.moneroxmr.org:18089