How I’m running a Bitcoin Full Node on Digital Ocean for $35 a month
Enjoyed the story? Leave some claps 👏 here on Medium and share it with your bitcoin-curious friends. Want to stay up-to-date on the latest in bitcoin? Follow me on Twitter here
NOTE: This post has been updated to reflect Digital Ocean’s updated Droplet configurations as of Jan 18, 2018
ANOTHER NOTE: If you’ve run into issues with your storage volume filling up, I’ve written an additional article on how to expand the volume storage space and get your full node back up and running
In the last couple months, I’ve become obsessed with Bitcoin and have been tinkering with different full node setups. A full node is a node that fully enforces all of the rules of the blockchain, and one that ensures that I give value to the protocol that I deem valid.
A “node” is just a fancy word for running the bitcoin protocol in the form of a software program on a computer connected to other computers running the bitcoin protocol
$40/mo is kinda expensive when compared with the free wallet services that you can get from custodial providers, but the real advantage of bitcoin is the ability to control complete validation of the ledger and to write code that interacts with the blockchain instead of being limited by a third-party API provider.
When you run a full node, you get to tinker with a database worth over $117,000,000,000
The problem is, running a full node is resource intensive. It requires (as of Nov 2017) almost 180G of space to store the entire bitcoin blockchain, the unspent transaction index, and other transaction indexes for fast transaction lookup. It’s memory needs are modest (1–2 GB of RAM), but it can eat through bandwidth pretty quickly, and I wanted it to be running 24/7, so I could connect to it through an SPV wallet of my choice.
Digital Ocean has a new(ish) feature called “Volumes” that allows you to attach storage to a droplet to extend the storage space. A 200GB volume costs $20 a month; combine that with a droplet running Ubuntu 16.04 with 2 CPUs, 2GB of RAM, and 3TB of data transfer for $20 and the final cost is “only” $40 a month. Without volumes, you would have to run a $320/month droplet to get enough storage space to run a proper full node.
If you’d like to run a similar setup, I’ve included detailed instructions below. Note that I’m running the Full Node with the wallet functionality disabled, although there is no reason to do this if you aren’t planning on using the wallet to store any bitcoins. If you do want a full node to use the wallet functionality, I’d suggest a more secure solution than a Virtual Machine on a cloud provider.
Step 1: Prepare your SSH keys
We’re going to be SSHing into the droplet later using a public/private key, so the first thing we need to do is generate a new SSH Key and upload the public key to Digital Ocean.
Open your Terminal on your local computer and issue the following command to generate a new public/private key pair:
# ssh-keygen -t rsa
NOTE: In the above line, there is no need to enter the hashtag character
#
. It’s merely there to denote a terminal command. The entire command is justssh-keygen -t rsa
You’ll be asked a few questions, such as what you’d like to name the files and a passphrase. I’ve left the passphrase out and I saved my public/private key files to ~/.ssh/digtal_ocean_droplet
. The output of running this command should look like something this:
Next up we need to upload the public key to Digital Ocean. Back in your terminal output the contents of the public key by issuing the following command:
# cat ~/.ssh/digital_ocean_droplet.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC74S3oh79sKw3zEqS5Y+CG7ZMcNLi9IuJ+WQws1HkeQZ8tKiaVZ62jpkNRtlxvADGv/LwJ9lAUdQ9nDa5GJt99bz9tV3Hsc5iUkPBsQaDQIYfstxkQpxbUvpmDNmSNfMVF95TFcyGPs3lTvvr9s7dIE4G/Y5Ov5H3fsUUEvZgpjB8/XnQDcfQTN9ocoIj6Sj15bLeSomEHoudwi7LKGRmABRrv2w44Ml0k5GzjdQdVu5cUsKlSyzsciENhh506kJrLeht6acdwQHAe0u1drCYEMEQpUfcm2VV8Hldm/ob/wH/8FHrhf1op9JpeX+/XfxrEG9N/SbWjnswjjioIsCLd eric@Erics-MacBook-Pro-4.local
Copy the entire output and then in your browser, navigate over to the Security settings in Digital Ocean and click the “Add SSH Key” button. Paste the previously copied public key contents and give your key a name, like so:
Finally, back on your machine in the terminal, add the private key to your SSH agent to allow you to later SSH into the droplet by issuing the following command:
# ssh-add ~/.ssh/digital_ocean_dropletIdentity added: /Users/eric/.ssh/digital_ocean_droplet (/Users/eric/.ssh/digital_ocean_droplet)
Step 2: Create droplet and volume
Now that we have our SSH key setup, it’s time to create the droplet and storage volume. Head over to the New Droplet page and select the following options:
Step 3: Initial Server Setup
After a few minutes your new droplet will be ready to go. Head over to the droplet page and copy the IP address for the droplet as shown here:
Before we can do anything too interesting, we need to do the initial server setup by creating a new linux user “bitcoin”, giving it sudo priveledges, and allowing us to SSH in to the server as “bitcoin” and not the default “root” user.
NOTE: In the following instructions, any command that is preceded by just a
#
signifies a command run on your local machine, and a command that is preceded byuser@bitcoin-full-node-1:~#
signifies a command run on the droplet.
First, SSH into the droplet using the IP Address you copied previously using this command:
# ssh root@138.68.177.109
You’ll be shown a prompt that “The authencity of host X can’t be established”. When asked if you want to continue just type “YES” and hit Enter.
If everything was done correctly up until this point, after a lovely welcome message from Ubuntu is displayed, you should be shown a prompt like the following:
root@bitcoin-full-node-1:~#
You’re in! The first thing we need to do is stop using the root
user to login to our server and instead create a new bitcoin
user and give it sudo
access:
root@bitcoin-full-node-1:~# adduser bitcoin
root@bitcoin-full-node-1:~# usermod -aG sudo bitcoin
When executing the adduser
command you’ll be asked to supply a new password. I suggest generating a strong password and using a password manager (e.g. 1Password). adduser
will also ask for a bunch of other information but feel free to just leave that blank.
Next up we’ll need to add our public SSH key to the bitcoin
user’s authorized_key
file so we can SSH into the droplet using bitcoin
instead of root
. Copy the public key again following the same instructions in Step 1, and then, as root
on the droplet, become the bitcoin
user:
root@bitcoin-full-node-1:~# su - bitcoin
Create the .ssh
directory and give it the correct permissions:
bitcoin@bitcoin-full-node-1:~# mkdir ~/.ssh
bitcoin@bitcoin-full-node-1:~# chmod 700 ~/.ssh
NOTE: Notice how
root@
becamebitcoin@
, this denotes that you are running the command as thebitcoin
user instead ofroot
.
Next we’re going to use the vi
editor to create the authorized_keys
file and add paste in the SSH key contents:
The authorized_keys
file needs the correct permissions, so issue the following command:
bitcoin@bitcoin-full-node-1:~# chmod 600 ~/.ssh/authorized_keys
Now logout of the droplet by issuing two exit
commands:
bitcoin@bitcoin-full-node-1:~# exit
root@bitcoin-full-node-1:~# exit
You should now be able to SSH into the droplet using the bitcoin
user:
# ssh bitcoin@138.68.177.109
Step 4: Format and attach the volume
The 200GB storage volume we created in Step 2 still needs some configuration before we can use it to store our bitcoin blockchain. The first thing we need to do is find out the name of the volume in the Digital Ocean dashboard. Navigate to your droplet and click the Volumes link and you can find the name of your volume here:
Now, as the bitcoin
user on your droplet, run the following commands, but make sure you replace all instances of volume-lon1-03
with your volume name:
NOTE: I’ve stopped prepending terminal commands with
bitcoin@bitcoin-full-node-1:~#
because all commands from here on out will be run on the droplet as thebitcoin
user.
NOTE: Anytime you run a command with the
sudo
prefix it means you may need to enter thebitcoin
password you created in Step 2.
You’ll now have a 197GB volume mounted at the /mtn/volume-lon1-03-part1
directory. We’ll be using it as our Data Directory when we configure Bitcoin Core in Step 6. But first, we need to install Bitcoin Core.
Step 5: Install Bitcoin Core
Installing Bitcoin Core is easy using the apt-get
utility provided by Ubuntu. Follow the commands below to install the latest version of Bitcoin Core (at the time of this writing the latest release available is 0.15.1)
If prompted to confirm when running install
, type Y
for “Yes” and hit Enter. You should now have bitcoind
installed; test and make sure by issuing the bitcoind --version
command.
Step 6: Configure Bitcoin Core
Before we can start running bitcoind
and doing our initial synchronisation with the network, we’ll need to create the Data Directory, set our options in bitcoin.conf
, and create a Ubuntu service to make it easier to start/stop/restart our bitcoind
executable and ensure it runs even if the machine reboots.
First, we’ll create the Data Directory we’re we’ll store the blockchain and all related files, inside the volume we configured above:
mkdir /mnt/volume-lon1-03-part1/Bitcoin
Next, we’ll create the ~/.bitcoin
directory where our bitcoin.conf
file will be stored:
mkdir ~/.bitcoin
Now, using vi
, create the ~/.bitcoin/bitcoin.conf
file and paste in this configuration:
Make sure to replace the enterpasswordhere
text with a strong password, especially if you’d like to make RPC calls to this full node from a remote client.
Also note the dbcache=1000
option. This is specifying, in megabytes, how much space you’d like the database cache size to be. The larger this value, the faster the initial sync will be, but it depends on the amount of RAM on the machine. Since I’m using the 2GB droplet, I’ve set the index size to be ~1GB. With an 8GB machine, and a dbcache=6000
set, the initial sync took just under 8 hours.
Finally, create the bitcoin.service
file at /lib/systemd/system/bitcoin.service
using vi
like so:
sudo vi /lib/systemd/system/bitcoin.service
And paste in the following contents:
Again, make sure you replace any instance of volume-lon1-03
with the name of your volume.
Step 7: Run Bitcoin
After all that, it’s time to fire up the bitcoin process and start the initial sync:
sudo service bitcoin start
After a minute or so, you should be able to query the node for information about the blockchain and view your progress:
bitcoin-cli getblockchaininfo
Which will give you output similar to this:
And see how many other nodes you are connected to with this command:
bitcoin-cli getnetworkinfo | grep connections
Which will be at most 8 until the synchronisation process is complete. You can now logout of your service with exit
and come back about 36 hours later to see a fully validated bitcoin blockchain. Once that happens, you can test to see if you can connect to your full node using the “Join the Network” tester on Bitnodes:
Some improvements to this setup that I’d like to make is to configure my node always to hold open an incoming connection for my SPV wallet, adding a firewall for more protection, and also do a little more research around the possibility of running wallet services on a VM.
There is also the issue of the growth in storage requirements. With a fully validated blockchain at height 493,617, my 200GB volume has about 20G of room left. With 10 minute blocks, that gives me about ~4–5 months before I’ll need to increase the volume storage, and more likely it’ll need to happen before that to account for index size and to leave some buffer.
And that doesn’t take into account the possible 2x hard fork coming at block 494,784. If for some reason the 2x fork “wins” and most of the users of bitcoin switch to the 2x chain, then the increase will have to come even sooner in as little as 50–60 days. And the storage requirements for the full blockchain and indexes will grow approximately 120–150GB per year, not to mention bandwidth increases which may price out the $20/mo droplet.
For this reason and a few others, I’m going to be voting with my node to try and keep the 1x chain the dominant chain. With the instructions above, and a little bit of money, you can too.