How to Run a Bitcoin Node on AWS For Free

This past weekend I went down something of a bitcoin programming rabbit hole while exploring an idea for sending crypto to people over Twitter. I ultimately decided not to pursue the idea any further than the the proof of concept phase, but I ended up spending a decent chunk of time playing around with self-hosting my own bitcoin node in the cloud. I wrote up my learnings into this guide, which will hopefully be useful to someone as an intro into bitcoin hacking 🙂

[Warning: The bcoin software is no longer actively maintained, but several companies (including purse.io) use it in production. As time goes on, however, and bcoin remains unmaintained, it will not be smart to use in mission-critical projects. I still think it is a valuable educational tool that can be used for smaller, non-critical projects.]

Table of Contents

  1. Create a Free-Tier AWS Account
  2. Launch an EC2 Instance
  3. Login to Your Server
  4. Install bcoin
  5. Run bcoin
  6. Secure the Node
  7. Access The bcoin Node Remotely

Create a Free-Tier AWS Account

AWS offers one year of free but limited resources to anyone signing up for a new account. The server that you can run within these limits is quite capable of hosting something for a personal project, so the deal is actually really great. (Note: After the year is up, if you still don’t want to pay for the hosting, you can sign up again with the same email using the + format. ex: matt+aws2021@gmail.com. Don’t worry, you’re not hurting Jeff’s bottom line.)

Head over to this link to create your account. You will have to enter payment information but as long as you stay within the free tier you won’t be charged. Everything we do in this guide falls under the free tier.

Launch an EC2 Instance

EC2 stands for Elastic Cloud Compute, and is the AWS product for running servers in the cloud. This is where we will run our Bitcoin node.

  • From the AWS dashboard view (which you will see when you log in for the first time), select EC2 from the top section.

  • On the next page, click the big orange button that says Launch Instance.

  • Find and select Ubuntu Server 20.04 in Step 1: Choose an Amazon Machine Image (AMI). Click Next.
  • Select Type t2.micro from Step 2: Choose an Instance Type. Click Next.
  • Leave default settings in Step 3: Configure Instance Details. Click Next.
  • Leave default settings in Step 4: Add Storage. Click Next.
  • Leave default settings in Step 5: Add Tags. Click Next.
  • In Step 6: Configure Security Group:
    • Edit the Security group name to be bcoin-node-sg.
    • Add the following rule:
      • Type: HTTP
      • Port range: 80
      • Source: Anywhere
    • Add the following rule:
      • Type: Custom TCP
      • Port range: 8332
      • Source: My IP
      • Description: bcoin node main net
    • Add the following rule:
      • Type: Custom TCP
      • Port range: 8334
      • Source: My IP
      • Description: bcoin wallet main net
    • Click Review and Launch.
  • Click Launch.
  • When the modal asks you to download a new key, name it something descriptive like bcoin-node-key, and click Download.
    • Navigate back to the EC2 Dashboard and click into the Instances page. You will see your new server! You can name it something fun by clicking the pencil that shows up in the Name column. Mine is called boringly just “bcoin”.

Login To Your Server

First thing is to move your private key file to some location where you’ll remember where it is. I have a ~/keys directory in my home folder where I keep private keys. You can set that up like this

$ mkdir ~/keys
$ mv ~/Downloads/bcoin-node-key.pem ~/keys

Then find the IP address of the new server. You can find it by clicking on its row in the Instances page in the EC2 console, and copying the Public IPv4 address from the top middle of the Details section.

Then, using the key as authentication, ssh into your new server at that address.

$ ssh -i ~/keys/bcoin-node-key.pem ubuntu@

You should get a prompt that looks something like this:

Yay!

Install bcoin

Run this command to install nvm, a version manager for Node.

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

Then log out and back in so that the nvm executable gets put into the PATH. And run this to install the latest version of Node.

$ nvm install node

Install build tools

$ sudo apt-get install build-essential

Download bcoin

$ git clone git://github.com/bcoin-org/bcoin.git

Install bcoin

$ cd bcoin
$ npm rebuild
$ npm install --global

This will install the bcoin executable on your system.

Run bcoin

Next step is running the node, which you can do by executing the bcoin command and passing in some configuration options.

It’s possible to run a full node with bcoin, which means downloading every single block included in the Bitcoin blockchain and keeping it on disk. This requires a lot of disk space – over 300GB – and that would mean paying for that storage because it doesn’t fall within the AWS free tier.

So instead of running a full node, we will run a Simple Payment Verification (SPV) node. This means instead of our node downloading and saving every single block in the Bitcoin blockchain, it will just download the headers for the entire blockchain. This takes up much less disk space, not even a gig on my machine. This trimmed down version of a node will still enable us to send and store Bitcoin, but we are essentially trusting other full nodes that the chain information we are receiving from them is correct.

Ok so we want to run an spv node, and we want to expose the Node API through HTTP so we can send send requests to get info, initiate transactions, and manage our wallet. We also want to run the node as a background process so that it keeps running after we log out.

The bcoin executable provides configuration options for supporting this setup. Here is the command you want to run. Note that you will probably want to change the API key.

$ bcoin \
  --http-host=0.0.0.0 \
  --api-key= \
  --wallet-http-host=0.0.0.0 \
  --wallet-api-key= \
  --spv \
  --daemon

To confirm bcoin is running properly, run bcoin-cli info ——api-key <your-api-key>. You should see output that looks something like this:

{
  "version": "2.1.2",
  "network": "main",
  "chain": {
    "height": 677373,
    "tip": "0000000000000000000b200dd7167a1751b8542e4a74bdb60ee54a55666a582f",
    "progress": 1
  },
  "indexes": {
    "addr": {
      "enabled": false,
      "height": 0
    },
    "tx": {
      "enabled": false,
      "height": 0
    },
    "filter": {
      "enabled": false,
      "height": 0
    }
  },
  "pool": {
    "host": "0.0.0.0",
    "port": 8333,
    "agent": "/bcoin:2.1.2/",
    "services": "1000",
    "outbound": 8,
    "inbound": 0
  },
  "mempool": {
    "tx": 0,
    "size": 0,
    "orphans": 0
  },
  "time": {
    "uptime": 36685,
    "system": 1617325819,
    "adjusted": 1617325819,
    "offset": 0
  },
  "memory": {
    "total": 285,
    "jsHeap": 12,
    "jsHeapTotal": 13,
    "nativeHeap": 271,
    "external": 8
  }
}

Secure The Node

Set Up A Domain Name

The bcoin node that’s running at this point is serving unencrypted connections. This isn’t secure and we need to do something about it, otherwise people would be able to snoop on your communications to the node. They would be able to steal your API key and then use that to steal your Bitcoin 😮

To secure the communications to our node, we will set up an SSL (Secure Sockets Layer) Certificate on the server, which will be used to encrypt traffic.

SSL certs are free from a great product called LetsEncrypt, but we need a domain name first. There are lots of places to get a domain name, and most are on the order of $10-12 per year. I use Google Domains.

If you already have a domain name, you don’t need to buy a new one for this project. You can just use a subdomain like bcoin.mywebsite.com. In fact that’s what I’m doing and is what we will learn how to do in this guide.

So, please go and buy a domain name if you don’t have one yet 🙂. The following sections will assume you have one.

Create An A Record

Before we can set up our SSL cert, we need to point our domain name at the server. Do this by going into the admin panel of whatever domain name registrar you bought the domain from. For Google Domains,

  • Go to this link
  • Click into the domain name
  • Select DNS from the left side panel
  • Scroll all the way down to the Custom resource records section
  • Type bcoin into the leftmost text box, and copy/paste your server’s IP address into the rightmost text box.

  • Leave the record type as A.
  • Click Add.

Set Up LetsEncrypt

We will be using the LetsEncrypt software developed by the non-profit Internet Security Research Group (ISRG).

Run the following

$ sudo snap install core; sudo snap refresh core
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
$ sudo certbot certonly --standalone

When prompted for the domain name, enter it as bcoin.mywebsite.com without any protocol information like http:// or https://. When the certification process finishes you’ll see an output with something like this at the bottom.

The first file listed in that message is the certificate file, and the second file listed is the key file. These will be important in a second when we update our bcoin command with the newly created SSL info.

In order to update our bcoin node to start encrypting traffic, we need to stop it and start it up again with configuration options containing the SSL files.

Stop the bcoin node by running

$ bcoin-cli rpc stop

Then start it up again with the following command. We pass in configuration options to point both the node server and the wallet server to the same SSL cert files.

$ bcoin \
  --http-host=0.0.0.0 \
  --api-key= \
  --wallet-http-host=0.0.0.0 \
  --wallet-api-key= \
  --ssl-cert= \
  --ssl-key= \
  --wallet-ssl-cert= \
  --wallet-ssl-key= \
  --spv \
  --daemon

Access The bcoin Node Remotely

We’ve seen that it’s pretty easy to SSH into the server that’s running the node and interact with it from there, but there is a much more flexible way of querying the node.

When we passed in the http-* and ssl-* config options to the bcoin daemon, we told it to start up a web server and start listening to API requests. We will now do some setup on our local machine and see some examples of sending API requests to the cloud server from your computer at home or wherever you are.

On your local machine (which just means your laptop or desktop when you’re not logged into a remote server), follow the steps from the Install bcoin section above to install bcoin. We won’t be using it to run a node, but it comes bundled with command line tools for querying the node and the wallet server running with the node.

Create Config Files

Once you have bcoin on your system, create a file at ~/.bcoin/bcoin.conf and add the following:

url: bcoin.mywebsite.com
api-key: 

Create another file at ~/.bcoin/wallet.conf and add the following:

url: bcoin.mywebsite.com
api-key: 

Now when we use the command line tools, they will automatically find the remote host and the api key, so we won’t have to explicitly pass in those options for every command.

Run Some Commands

Get Node Info

The most simple command is

$ bcoin-cli info

It shows you some metadata about your node like how much progress it’s made syncing up with the full chain (1 means it is fully synced), what version it’s running, how long it’s been running and how much RAM it’s using.

Manage Your Wallet

The bcoin software comes with a bitcoin wallet, which you can see a more in depth guide for here. I basically followed that guide and will just reproduce some commands here.

To see all of the existing wallets, run

$ bwallet-cli admin wallets

To create a new account inside an existing wallet run

$ bwallet-cli account create  --id=

To get the address of an account in an existing wallet, run

$ bwallet-cli address --account= --id=

That’s about the extent to which I’ve explored the bcoin wallet software at this point. Like I said up top, I’m not storing any BTC in this node. Just hacking around for pure fun so far.

Matt Roll @mroll