Automated deploy to IPFS and ENS

How to automatically publish your decentralized website with IPFS and Ethereum Name Service

So you have registered a nice ENS name and want to make your site/dapp available via IPFS and the Ethereum Name Service. There are a few steps required to make this a seamless part of your deployment scripts.

Before we start…

In this guide I’m assuming you already know the basics of how to host a site with IPFS and ENS. The focus is on deployment automation and adapting your CI workflow. If you are not familiar with ENS and IPFS some question marks might come up :)

Node.js version: At the time of writing ens-updater can not be installed on node versions ≥ 12.x., as some dependency requires script module, which fails to build. This issue is tracked in https://github.com/TripleSpeeder/ens-updater/issues/44. Until the issue is solved please use node version 10 or lower.

Tasks to accomplish

Deploying your decentralized site is a two-step process:

Publish the content to IPFS, obtaining the new CID Set the IPFS record of your ENS name to point to the new CID

For both steps command-line tools are available. First, we will look at each step in detail, then we will create a Travis configuration that will fully automate the deployments.

Step 1 — Publish to IPFS

For this task, we will be using the CLI tool ipfs-deploy. Install it globally via npm:

> npm install -g ipfs-deploy

This tool is really simple to use. You just need to provide the build folder you want to deploy and select the IPFS pinning service(s) you want to use.

Assuming the production build of your app is located in the folder build you can run the following command to deploy through the public available infura ipfs node:

> ipfs-deploy build -p infura

Take note of the CID string Qm… provided by ipfs-deploy. This is the unique identifier for your build that needs to be added to your ENS name.

Ipfs-deploy supports a number of different IPFSpinning services, some of them require authentication. Check the Readme for more details.

That’s all for step 1 - Your build is now published! Read on to see how to update your ENS name record.

Step 2 — Set the contenthash record of your ENS name

For this step, we will be using the cli tool ens-updater. Install it globally via npm:

> npm install -g @triplespeeder/ens-updater

ens-updater supports a number of different commands to manage your ENS name. For this tutorial we are only interested in setting the contenthash entry of your name, to make it point to the CID you obtained in step 1. Check the output of ens-updater --help for an overview of supported commands and the github page for further information.

Since we need to interact with the ENS smart contracts to update the contenthash entry we need two things to continue:

Access to an ethereum node to interact with the contract

The private key of the account controlling the ENS name

You can either provide the private key directly or indirectly via the mnemonic string (and optional account index). For both options, you need to either put the information in the file .env or set an environment variable.

For this tutorial, we will save the private key in a .env file. Open your text editor of choice and create the file .env in your working directory:

PRIVATE_KEY=<private key here, without leading 0x>

To make sure everything is set up correctly, invoke ens-updater with the --dry-run option. With this option being set no real transactions will be performed, but potential configuration or setup issues will be reported.

Example: The full command to set the contenthash record of ENS name mysite.eth to the ipfs CID Qmd2yEHMTswLppDkWNjEMH4WwAgeuFXYeMHSn4VcJMcvKy in dry-run mode:

> ens-updater setContenthash mysite.eth ipfs-ns Qmd2yEHMTswLppDkWNjEMH4WwAgeuFXYeMHSn4VcJMcvKy --web3 http://localhost:8545 --verbose --dry-run

Check the resulting output to see if any error gets reported. Otherwise, you’re good to continue without the — dry-run option!

Now point your browser to http://mysite.eth. Assuming your system is set up correctly to work with .eth domains you should see your site in action!

That’s all for step 2 — Your site is now accessible via your ENS name! Read on for setting up Travis for automated deployment.

Putting it all together for fully automated deployments

To automate the above steps using Travis we need to:

create a deploy script that combines ipfs-deploy and ens-updater, to be executed by Travis in the deploy stage

Setup Travis to execute the deploy script

Setup environment variables for Travis so ens-updater has access to the private key

The deploy script

Since ipfs-deploy provides the CID via stdout and ens-updater can be set up to read the CID from stdin we can pipe the two commands together in a small shell script like this:

#!/bin/bash

ipfs-deploy build -p $1 -C -O | ens-updater setContenthash mysite.eth ipfs-ns stdin -v --web3 $2

This script expects the pinner service to use for deployment as the first argument and the web3 connection string as the second argument. Also, note that by specifying the special string “stdin” as CID for ens-updater it knows to read the CID from stdin.

Add this script to your project so it is part of the repository and available to Travis.

Travis configuration

Now edit travis.yaml to execute your script during the deploy stage. Here is a (stripped down) sample configuration from a real project, important parts emphasized:

os: linux

language: node_js

node_js: 10

jobs:

include:

- name: "IPFS"

install:

- npm ci

- npm install -g ipfs-deploy

- npm install -g @triplespeeder/ens-updater

script: npm run build

deploy:

provider: script

script: bash scripts/deploy_ipfs.sh pinata https://mainnet.infura.io/v3/$INFURA_ID

skip_cleanup: true

The install phase contains the additional commands to install the tools ipfs-deploy and ens-updater.

The deploy phase executes the deploy script we just created, using the ipfs pinner service “pinata” and a web3 instance from infura. Don’t forget the skip_cleanup option — Otherwise, Travis will wipe out the build folder before starting the deployment…

The last missing piece is providing the private key of the ENS name controller account. Let’s set this up!

Go to your project page in Travis

Open the settings page

Go to the section “Environment Variables”

Add a new environment variable with the name “PRIVATE_KEY” and paste your private key into the VALUE field. Set the BRANCH field to your master branch since deployments will only run from the master branch. Make sure to NOT check “DISPLAY VALUE IN BUILD LOG” — otherwise anyone could see your private key in the build logs.

In my case, I also added environment vars for the pinata IPFS service and Infura web3 service, and a GitHub token for optional deployment to Github-pages. Here is a screenshot of the complete setup:

With these changes in place, trigger a new build. If all goes well your build log will end like this:

And that’s it! Whenever you push an update to your master branch the changes will be deployed to IPFS and the contenthash record of your ENS name will be updated.