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 just
ssh-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.pubssh-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_droplet
Identity 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 by
user@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 email@example.com
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:
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
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).
adduserwill 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
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
root@bitcoin-full-node-1:~# su - bitcoin
.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
bitcoin@, this denotes that you are running the command as the
bitcoinuser instead of
Next we’re going to use the
vi editor to create the
authorized_keys file and add paste in the SSH key contents:
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
You should now be able to SSH into the droplet using the
# ssh firstname.lastname@example.org
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 the
NOTE: Anytime you run a command with the
sudoprefix it means you may need to enter the
bitcoinpassword 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
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:
Next, we’ll create the
~/.bitcoin directory where our
bitcoin.conf file will be stored:
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
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:
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.