In this article I will upload a static website to IPFS to get myself familiar with the steps it takes to link an .eth domain to content hosted on the distributed web.
Install IPFS Desktop according to the install instructions. This will add IPFS to the toolbar (the cube icon).
Verify that IPFS is working properly by clicking the icon.
ipfs in the command line after enabling Command Line Tools in the Preferences:
❯ ipfs --version
ipfs version 0.6.0
By installing the Desktop will already start the daemon, so running
ipfs daemon is not necessary.
go-ipfs by retrieving the TAR-ball, extracing it and running the installation script.
~/ $ wget https://github.com/ipfs/go-ipfs/releases/download/v0.5.1/go-ipfs_v0.5.1_linux-amd64.tar.gz
~/ $ tar -xvzf go-ipfs_v0.5.1_linux-amd64.tar.gz
~/ $ cd go-ipfs
~/go-ipfs $ sudo bash install.sh
~/go-ipfs $ ipfs --version
ipfs version 0.5.1
Initialization will start the node in a local folder. Once you have been added as a node, the daemon can be started.
$ ipfs init --profile server
initializing IPFS node at /home/jitsejan/.ipfs
generating 2048-bit RSA keypair...done
peer identity: QmSztWC9dxLzUV7Ph5ZJLwhGW5aLRG2Pwptis3cw6cfK53
to get started, enter:
ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
$ ipfs daemon
go-ipfs version: 0.5.1
Repo version: 9
System version: amd64/linux
Golang version: go1.13.10
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/172.17.0.1/tcp/4001
Swarm listening on /ip4/172.21.0.1/tcp/4001
Swarm listening on /ip4/126.96.36.199/tcp/4001
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /p2p-circuit
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip4/188.8.131.52/tcp/4001
Swarm announcing /ip6/::1/tcp/4001
API server listening on /ip4/127.0.0.1/tcp/5001
Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Daemon is ready
Verify the peers that are connected.
$ ipfs swarm peers
Execute the sample test by adding a string to IPFS and querying it using
$ hash=`echo "I <3 IPFS -$(whoami)" | ipfs add -q`
$ echo $hash
$ curl "https://ipfs.io/ipfs/$hash"
I <3 IPFS -jitsejan
Create a basic website
The website that we will upload has the following structure. I chose to use subfolders for
images to make sure this is also supported by IPFS. In the future I want to upload more complex websites to IPFS, for example my personal blog that is statis website created using Pelican. From my understanding of IPFS it is not possible to upload dynamic content at this point.
│ └── style.css
│ └── blockchain.jpg
The template for the website has a link to the stylesheet, some content and an image.
<link rel="stylesheet" type="text/css" href="style.css">
<title>My first IPFS site!</title>
<img src="images/blockchain.jpg" alt="A random Blockchain image" />
IPFS is the <b>future</b>!
The stylesheet sets the background for the page and makes sure the image is aligned in the center.
margin: 50px auto 0px auto;
Add files to IPFS
Now that the files have been created the website should be added to the filesystem. Run
ipfs add -r in the folder that should be uploaded to recursively add the files to IPFS.
❯ ipfs add -r .
added QmNfVVQsXyekrNiM2dK35oQXg2dGqQ97Gz2PDBxUH6Piqu ipfs-static-website/README.md
added QmZEZJRrb6WxoenKzuXtu9jUgmCxGpg777Y2zqcFwifGNS ipfs-static-website/css/style.css
added QmQaYCUpUzHLiefmonVSHFnBhWw9bHTi1Js3QMddMxStKE ipfs-static-website/images/blockchain.jpg
added QmSFgajgQq1XtjsLxxDupPH1Ys1tAuJ8DQoPScEUEZZX2U ipfs-static-website/index.html
added QmUnsAAQ5vpH4gX1ypR5WaQJb1KDP7KsTEomiijJzetUvM ipfs-static-website/css
added QmYBwq5uLGX6zfEBwjQ7UHgEv3Ton9hX4QjxxkTfg1tdVx ipfs-static-website/images
added Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u ipfs-static-website
77.86 KiB / 178.67 KiB [===========================>----------------------------------] 43.58%
SITE_ID would be
Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u as it is the hash of the main folder (bottom element). Opening up the file browser in IPFS desktop and searching for the QmHash will show the files from the repository.
To confirm that the files are correct you can view the files. For example, you can navigate to images and open the
blockchain.jpg to see the actual content.
Verify the content
In the previous step we found the hash of the main folder of the website. Since the ipfs daemon is running, we can view the files locally by navigating to http://localhost:8080/ipfs/ and adding the hash. Opening the hash in the browser http://localhost:8080/ipfs/Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u/ will show the page as we expect:
Use IPNS to host content
A downside of using IPFS is that every time the website changes the corresponding hashes will be updated. If you link directly to the IPFS hash with your DNS this will break the next time you update the website. To avoid manually updating the hash with every update we could use IPNS instead. The IPNS hash should remain the same even though the website gets updated. In order to get the IPNS hash we will need to publish using
ipfs name publish <IPFS_HASH> and wait for the IPFS hash to be returned. In my case it took a minute before the publishing was completed.
❯ ipfs name publish Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u
Published to QmSztWC9dxLzUV7Ph5ZJLwhGW5aLRG2Pwptis3cw6cfK53: /ipfs/Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u
The return value contains the hash for IPNS which again we can verify using our localhost. The
$PEER_ID will be QmSztWC9dxLzUV7Ph5ZJLwhGW5aLRG2Pwptis3cw6cfK53 and can be appended to http://localhost:8080/ipns/. Indeed opening http://localhost:8080/ipns/QmXwD1dj6ywm3pNQPY2vuEzjdxz1zvrnVe7DrJp56yBnPU/ shows again the basic website.
Setup DNS with Cloudflare
Cloudflare is a service I use for my DNS management and security of my website. Cloudfare also supports an IPFS gateway which means we can setup the DNS to the IPFS content with this service. In order to link a domain name to the IPFS content we need to add two elements. In my case I want to link the IPFS content to https://ipfs.jitsejan.com.
- CNAME containing the subdomain with a target to cloudflare-ipfs.com.
- TXT with the name following the pattern
These settings can be verified with
dig by checking the answer to a call to
_dnslink.<subdomain>.<domain>. This should return the
dnslink with the correct IPFS hash.
❯ dig +noall +answer TXT _dnslink.ipfs.jitsejan.com
_dnslink.ipfs.jitsejan.com. 300 IN TXT "dnslink=/ipfs/Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u"
As an additional step we can add a certificate to the domain by navigating to https://www.cloudflare.com/distributed-web-gateway/ and scrolling down to the bottom:
After a few seconds this should complete:
Before checking if my domain is working I will verify the content on the IPFS server of Cloudflare. By navigating to https://cloudflare-ipfs.com/ipfs/Qmeg3LpczHYLWFhQ9htz6qjizkf2aPKm3qZEyW4autpo5u/ I can check if the website is available. Initially it showed me the right page, but without the image.
After waiting a couple of minutes the image shows too:
I have registered my
eth domain with https://app.ens.domains to make sure nobody would take
jitsejan.eth. To see my domains I will need to connect to my wallet which was used to buy the domains.
Because I bought the domain on my phone using the Cipher Browser some time ago and since then Cipher Browser got acquired by Coinbase the Cipher app was disabled. I did not have access to the Ethereum network and could not access https://app.ens.domains. Using the recovery phrase I was able to import my wallet into Firefox with MetaMask on my laptop and manage my domains.
Navigate to your
eth domain page, for example https://app.ens.domains/name/jitsejan.eth, and by clicking the
+ under Records add the content with your IPFS link:
Note: Adding content to the network will cost gas!
After being very patience the website will be visible on http://jitsejan.eth.link. Note the
.link in the end to make sure the DNS can handle the content hosted on ENS (info: http://eth.link/). Viewing the page is free, so refreshing every second wouldn't cost you money.
- Add a Pelican blog to IPFS
- Use IPNS in combination with the .eth domain