Blogging on IPFS
With Hugo, IPNS, dnslink, and Cloudflare IPFS gateway
A little fun fact about this site
This blog is a static site generated by Hugo, hosted on IPFS. I personally run an IPFS node, and the files are pinned on my node. If you came here though your own IPFS gateway, then congrats! You already know where this is going. Otherwise, keep reading and I’ll explain the entire setup of the site.
- The site lives permanently by the IPNS name
/ipns/QmTctHYiuy3LXguP5jBP4DJAmnCD22gQbBAV24wH394vSs
https://push32.com
gets you on Cloudflare IPFS gateway, which actually resolves to
https://cloudflare-ipfs.com/ipns/<site-ipns-name>
dig
ging the TXT record of_dnslink.push32.com
will give you the IPNS name as well
The site can be accessed by:
- Simply going to
https://push32.com
- Use an IPFS gateway and go to
/ipns/push32.com
- You can resolve this to IPNS name with
ipfs dns push32.com
- Use an IPFS gateway and go to
/ipns/QmTctHYiuy3LXguP5jBP4DJAmnCD22gQbBAV24wH394vSs
- You can resolve this with
ipfs name resolve QmTctHYiuy3LXguP5jBP4DJAmnCD22gQbBAV24wH394vSs
- Once you resolved the IPNS name you can use an IPFS gateway and go to
/ipfs/<resolved-ipfs-path>
I’m writing this post as a tutorial on setting up your own uncensorable blog on IPFS.
Requirements
- Have
hugo
andipfs
installed - A server that’s connected to the internet, that can run an IPFS node
- Basic Linux knowledge
- Basic DNS knowledge
Hugo setup
Assume you already have a working site generated by Hugo. If you don’t I would refer you to their quick start guide.
Config
Make sure you add this in the config.toml
of your Hugo site
relativeurls = true
Generating the site
Once the config is updated, run hugo
to generate the site. The static site should be generated in public
folder.
IPFS setup
The IPFS setup should be done on whatever server you wish to run the IPFS node on. This can be your own laptop or whatever, but keep in mind that the server has to always be running IPFS node if you want your site to be always available.
Init
In case you have not already init’d IPFS, run
ipfs init
This will create ~/.ipfs
folder with default configs, and a fresh keypair. You probably want to back up ~/.ipfs/config
file as your private key is in it.
Starting IPFS daemon
ipfs daemon
This will run IPFS daemon on your server. Add &
if you want to run it in the background.
Protip: If you just want to try it out without annoncing your embarrassing “hello world” post to the world, run it with
--offline
flag.
Adding the files
Now we can add the public
folder to IPFS.
ipfs add public/ -r
This command should return all the files added along with their IPFS paths. The files are added to the local IPFS node. If the node is running with --offline
flag, the files will not be accessible outside localhost.
You shouldn’t have to do
ipfs pin add
since the files get pinned when you publish.
Publishing to IPNS
Copy the IPFS path of the public
folder from the output of the previous step.
ipfs name publish <root-folder-ipfs-path>
What this essentially does is that IPFS uses the private key to write a signed message saying that “an IPNS lookup with my peer-ID should resolve to this particular IPFS path”. So when other people do an IPNS lookup with your peer ID, they will see the IPFS path you published.
This command outputs both your IPNS name (peer-ID) and the IPFS path of the public
folder.
Checking the IPNS name record
ipfs name resolve <my-peer-id>
You can see your peer ID with ipfs id
. The output should match the IPFS path from the previous step.
Now, you should be able to see your site by going to
http://localhost:8080/ipns/<peer-id>
in your favorite browser.
dnslink setup
dnslink gives us the ability to resolve a DNS record like example.org
to either an IPFS path or IPNS name, so we don’t have to remember our long peer-id.
Adding a TXT record for dnslink
Now, depending on whether or not you want to use CNAME records to point at the DNS records of the gateway, there are 2 ways to set up dnslink.
Without CNAME to gateway
This method allows you to use any subdomain you wish, like sub.my.domain
. The drawback is you won’t be able to use CNAME with it, so you can’t just open up a browser and go to http://sub.my.domain
. You would have to use a gateway and do /ipns/<sub.my.domain>
.
Set up a DNS TXT record on the domain you wish to resolve to your IPNS name
dnslink=/ipns/<peer-id>
Once you’re done, wait until the DNS is propagated. Then you should be able to visit your site by going to
http://localhost:8080/ipns/<sub.my.domain>
Or replace localhost with some other gateway, like gateway.ipfs.io
or cloudflare-ipfs.com
, if your IPFS node isn’t running offline.
With CNAME to gateway
With CNAME you can visit your site by directly typing in the domain in the browser address bar. But the drawback is you can only put one dnslink on your domain.
Set up a DNS TXT record for _dnslink.my.domain
dnslink=/ipns/<peer-id>
Then set up a CNAME record for my.domain
to point to an IPFS gateway.
- You can try Cloudflare IPFS gateway, which is
cloudflare-ipfs.com
- This comes with HTTPS and all the fancy stuff. In reality, you don’t really need HTTPS if you aren’t too worried about privacy, since the client can always verify the integrity of the data over IPFS. Your ISP or whoever MITM is can see your request, but IPFS itself does not provide PIR (private information retrieval) privacy anyway.
- You can also try the gateway hosted by ipfs.io, which is
gateway.ipfs.io
Once you are done, go to http://my.domain
and see your shiny new site.
Bonus: Script for the lazy
Assume you have your hugo site source and ipfs on your server. Put this script to your hugo site source directory, run it to build site, add to ipfs, then publish.
#!/bin/sh
echo Building site...
hugo
echo Adding to IPFS...
ROOTHASH=$(ipfs add -r public/ | awk '{print $(NF-1)}' | tail -1)
echo "Root hash of the site is $ROOTHASH"
echo Publishing to IPNS...
ipfs name publish $ROOTHASH
echo Done!