I’ve been running my own zcashd node in a docker container for quite a while. But it has been hosted by my primary Windows machine. Today, I moved it to my Ubuntu 22.10 machine. While the official docs served as the basis for my setup, I had to devise my own configuration and migration steps slightly, which I share with you below.

I wanted a docker container that would be self-maintaining, meaning:

  1. The container would automatically start after I reboot the system.
  2. The container would either automatically upgrade zcashd periodically, or at least make it really easy to manually upgrade.
  3. I could recreate the docker container whenever I needed to, without losing my local wallet or having to redownload the blockchain or Zcash parameters.

To address all these, I went with a docker-compose.yml file. I created it inside a new ~/docker/zcashd directory. The name of the directory that contains the file is significant because it is prefixed onto the docker volumes that are automatically created.

version: '3.1'
services:
  zcashd:
    image: electriccoinco/zcashd
    restart: unless-stopped
    ports:
    - 8232:8232
    - 8233:8233
    volumes:
    - data:/srv/zcashd/.zcash
    - params:/srv/zcashd/.zcash-params
volumes:
  data:
  params:

The image field refers to the official zcashd docker image. The restart field tells docker to keep my container running across reboots unless I stopped it explicitly. I will discuss ports later on. The volumes are mounted in very specific locations within the container so that the zcashd process within the container will store the blockchain and wallet in the data volume and the Zcash parameters in the params volume.

Now just tell docker to create the container (and volumes, if they do not already exist):

docker-compose up -d

This command will create a container and print out its name. On my machine it was named zcash_zcashd_1. The -d switch causes the docker container to run in the background and return you to your shell.

The container should now be running and volumes created. If you’re setting up your zcash node for the first time, your work is done.

You can use this command to ‘watch’ the node work:

docker logs -f zcash_zcashd_1

This will show you updates such as downloading Zcash parameters, catching up and downloading new blocks on the blockchain, and any errors along the way.

Volumes

The data and params volumes were created under /var/lib/docker/volumes/zcash_data/_data and /var/lib/docker/volumes/zcash_params/_data, respectively. The zcash_ prefixed onto those volume directories comes from the name of the directory that contains the docker-compose.yml file.

These volumes persist even when the container is deleted. This is very important because containers are often considered to be volatile and may be deleted without concern for the files within them. You don’t want to lose your wallet that way, or have to re-download the entire blockchain because you accidentally deleted your copy.

Migrating

The most complicated step for me was in migrating my docker container. I didn’t want to spend days syncing down the blockchain on the new machine. I copied the .zcash directory from the old container into the new one. Since the container runs zcashd immediately, and I don’t want to copy this directory while the container is running and accessing that data, I did this ‘offline’.

First, I predicted the name of the volume that docker-compose would create: zcash_data. I created this manually before ever running docker-compose up by running this command:

docker volume create zcash_data

After mounting a remote file system between my Windows computer and linux, I copied the .zcash directory from the Windows machine directly into the linux machine directory that stores the volume. Something like this:

cp -R /mnt/windows/.zcashd/* /var/lib/docker/volumes/zcash_data/_data/

The blockchain is 173GB at the moment, so this took several minutes. But that’s much faster than downloading the blockchain from the Zcash network, which takes days and intense CPU power as it validates each block.

Finally, to ensure that the docker container would have access to these files, I changed ownership to 2001 which is the UID used within the docker container:

chown 2001.2001 -R /var/lib/docker/volumes/zcash_data/_data/

After this, running docker-compose up -d only had to download the zcash parameters which took only a minute or two. The local blockchain was accept and seen as (nearly) current.

Periodic upgrading of the zcashd software

The Zcash network is upgraded occasionally, and the zcashd software has to be upgraded too. If you don’t periodically upgrade zcashd, the container will shut itself down with an error about an upgrade being required in order to read past some particular numbered block on the chain.

Thanks to our docker-compose.yml file, this is trivially easy. Just recreate the container by running these commands in the directory containing that yml file:

docker-compose down
docker-compose up -d

Because we set up volumes that are mounted into the container, your new container will be able to pick up right where the old container left off.

Some thoughts on ports

The ports allow me to access the node and wallet from outside the container. Port 8232 is the RPC port and enables me to send REST calls to the node to create accounts, review balances, and spend my Zcash. These RPC calls are super-low level and may not be necessary as wallet software tends to make this much easier. If you’re just setting up your node to contribute to resiliency of the Zcash network and not to store a wallet, you can probably omit forwarding port 8232.

Port 8233 is the other port we expose via the yml file. This is the primary port by which Zcash nodes communicate with each other. It is how the Zcash blockchain grows globally. Every time you send a transaction, it gets relayed to all nodes via this port. If you do not expose this port, your local copy of the blockchain will still grow because your node can reach out to other nodes via their exposed port. But your machine will not help the network by being one of those nodes. It will only be a client.

The zcash.conf file

I modified the zcash.conf file that’s in the root of my data volume in order to enable the RPC server, and set credentials and allowed IP addresses for accessing it. Mine looks like this:

server=1
rpcuser=my-cleartext-username
rpcpassword=my-cleartext-password
rpcallowip=192.168.0.160/255.255.255.0
rpcallowip=172.17.0.1/255.255.255.0

Sending REST calls to this server requires each call to be authenticated with an Authorization header, but that is outside the scope of this post.

Preparing for hosting a litewalletd service

If you plan to host a litewalletd service based on this zcashd node, save yourself several days of reindexing the block chain later by adding these additional lines to zcash.conf when you are first setting up your node:

txindex=1
insightexplorer=1
experimentalfeatures=1

These are documented by litewalletd as necessary, and I found that to be true in practice.

Hardware specs on my Ubuntu machine

My Ubuntu machine is far more powerful than is required to run zcashd. But in case you’re interested, this is what I’m running:

  • Intel(R) Core(TM) i7-7700T CPU @ 2.90GHz (up to 3.6GHz)
  • 32GB RAM
  • 1TB NVMe SSD

As it is, with the container running and zcashd in a steady state (blockchain downloaded), my CPU is virtually idle. FireFox and keybase are taking more CPU and they are idle.

Running a zcashd node on Windows

Although Zcashd is only supported on Debian/Ubuntu (including their docker container equivalents), the popular Zcash wallet Zecwallet Fullnode for Windows actually runs a zcashd.exe process within Windows, so it presumably works well enough. That said, ever since the NU5 network upgrade, Zecwallet Fullnode has been totally broken for me. Zecwallet Lite works great, but it relies on a LiteWalletD server rather than a local zcashd node.

One thought on “How to host a Zcash node via docker”

Comments are closed.