Skip to content

Instantly share code, notes, and snippets.

@s0lesurviv0r
Created November 9, 2022 08:24
Show Gist options
  • Save s0lesurviv0r/b181b7bac148146979adfb2c3e17ea2d to your computer and use it in GitHub Desktop.
Save s0lesurviv0r/b181b7bac148146979adfb2c3e17ea2d to your computer and use it in GitHub Desktop.
Publishing a Hugo sire to IPFS

Publishing a Hugo sire to IPFS

Introduction

If you're not familiar with the Interplanetary File System (IPFS) I highly encourage you to look at their site. IPFS aims to be the distributed peer-to-peer web. Files and web pages can be shared on multiple machines, starting with the one you share the content with. Additionally, user's can "pin" files and web pages on their local IPFS nodes to then further share them with others. This is as opposed to a centralized web where a webpage is served from a central source.

Having the ability to share my content (this Hugo site) with others in a distributed fashion, where others can even cache offline versions of this content, was the main motivator to put my site onto IPFS. There are many more interesting and ground breaking features of IPFS but this article only showcases the basic case of putting a statically generated Hugo site onto IPFS.

Terminology

To stay consistent, I'll document the terms I'll use and what they mean.

  • Site hash - IPFS addresses file and directories by their hashes. I refer to the hash of the root directory for the static hugo site as the site hash. Essentially, the site hash is the way of finding/addressing the static site's directory in IPFS.
  • IPNS hash - Technically a hash of your IPFS private key. IPNS is used to pin a stable address to an every changing IPFS hash. This is because IPFS hashes change when the content changes.

Procedure

1. Use relative URLs

In the Hugo site's config.xml, set relativeURLs = true. The reason is that when we access the site through a remote or local IPFS gateway the site won't be at the root (e.g. example.com) but instead something like http://example.com/subfolder. In the case of the IPFS gateway specifically the root of our site will not be the root of the IPFS gateway: http://localhost:8080/ipfs/<hash-for-site>.

2. Generate the site

Generate the site by running hugo. The static site will be generated and output into the public directory. The public directory is the one I serve in the traditional sense via the centralized web.

3. Publish to IPFS

Now we'll publish our statically generated Hugo site to IPFS by running ipfs add -r public/. This command will place the directory "into" IPFS. In the background the entire directory structure is chunked, hashed, and transformed into the structure needed to access/share this directory (our site) on IPFS. At this point the site will be ready to serve from our local IPFS node. The add command will give us a hash, something like QmV7PaSSAmS7r55y7jVAYM2dZ5oXfhV9m7LZPPNCGwBAbo, which will uniquely identify our site's directory. It will typically be on the last line of output, with the name of the folder (public in our case). This is our content will be addressed in IPFS.

Using the local gateway provided by the IPFS daemon. The content can then be view with the URL: http://127.0.0.1:8080/ipfs/<site-hash>.

4. Backup the IPFS private key

Before we move to the next step, we should backup our IPFS private key. The private key will be needed to create and update the IPNS hash. If we lose it we'll lose access to update that IPNS hash to the new site hash. The IPFS private key will typically be in the file ~/.ipfs/config where ~ is the user's home directory.

5. Generate IPNS name

We may want to update our site and not have to advertise the new site hash every time. In order to solve this we'll create an IPNS hash to point to our site hash and then update this IPNS hash to the new site hash on every site update. The command will be ipfs name publish <site-hash>. This will return the IPNS hash. More information on IPNS can be found here.

When we update our site we will get a new site hash and we will run the same command to update the IPNS hash pointer to the new site hash.

6. Pin the site (optional)

To access content on IPFS that content must be on at least one running IPFS instance. In step 3 we placed our static site on our local IPFS node. This is fine for serving assuming this local machine is always going to be online for others to download our site from. This may not always be the case and therefore it's preferable to "pin" the site on other IPFS nodes to ensure our site remains live. We can setup IPFS on a home server and run ipfs pin add -r /ipns/<ipns-hash>. This will instruct the IPFS daemon on that server to store a copy of the site locally, enabling it to be served to others.

Please note that when we update IPNS to point to our new site hash we will need to rerun the pin command. Based on what I've read this may not be necessary in future versions of IPFS.

There are also third party pinning services that can store your site, or really any IPFS content, for you. More information can be found here.

As an example, I pinned my site using Pinata cloud. After setup, all I needed to do was run the command: ipfs pin remote add --service=pinata /ipns/<ipns-hash>.

7. Setup DNS Link (optional)

Though the IPNS hash will always point to the latest site hash it's impossible to memorize this and hard to share with others. One way to bridge the gap is by using DNS Link. We can make our site addressable using our current domain name. For example, this site is addressable with /ipns/jacobzelek.com and /ipns/kg6mwi.com. To use DNS Link a TXT DNS entry needs to be added to the existing domain. For my site I had to add the record dnslink=/ipns/<ipns-hash> as a TXT record to _dnslink.jacobzelek.com. Here's a screenshot of how it looks like in my GoDaddy account.

GoDaddy DNS Settings

More information can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment