One of the major things that made me want to support neocities is that one of the founders is a big supporter of Web 3.0 and web decentralization. The main way he seems to be supporting it is by IPFS integration in neocities. IPFS is a project I've had my eye on for a while. The concept is simple. It's a blockchain based DHT and P2P network for sharing websites. The idea is simple. You hash any file, and start hosting it. The hash winds up on the blockchain, and anyone else can access the file by requesting the hash. This way, the whole internet sort of works like bit torrent. You connect to the IPFS swarm, and retrieve the internet by peers who are closest to you. IPFS stands for Interplanetary filesystem. The idea is that even if you're on the moon, you could probably retrieve a static website that's hosted on earth pretty quickly if one of your peers on the moon already has it.

However, there's another interesting use case that the neocities guy brought up, and that's persistence of information. If the swarm is wet with some data, even if the original host goes down, the peers will still have it. However, that's a big if, as we'll see shortly.

How it Works

This website you're reading right now is static data. There's a little pinch of javascript in the theme, but the posts you're seeing are not dynamic. Like a pure function, no matter how many times you visit this page, it will always be the way you see it unless I update it down the line. This is a perfect candidate for storing or caching. When the page is published, each part of the site is hashed and hosted on the neocities IPFS daemon (I guess?). This makes it initially available for peers. When peers go out to retrieve it through the IPFS gateway at ipfs.io or through your local daemon, you temporarily mirror the pages. Here's an example of a thing that you'll probably always be able to see through the IPFS gateway. You can see there that the name of the hash is QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB, which contains some subnodes in it, including the readme node. If you wanted to see this directly through IPFS and you have it installed, you'd run ipfs cat QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB to view it. In the appropriate P2P way, this would go talk to the swarm and retrieve it from whoever has it. If I wanted to, I could then pin it to make sure it stays live in my cache and I can keep hosting it in case the original went down.

However, it should be clear that this is a garbage way to find files. Humans can't remember IPv6 addresses, let alone that gargantuan hash. Also, if that hash is your home page, and you make a change to it, your hash will change when it gets rehosted in the DHT. In order to combat this, IPNS (pronounced iPenis) was developed. The way IPNS works is instead of uploading your index page directly, you publish a pubkey to IPFS, which links to signed information about the latest hash of some resource. Since you have the private key, you can update this. You access IPNS addresses using /ipns/<hash> instead of /ipfs/<hash> A name in IPNS is the hash of a public key. It is associated with a record containing information about the hash it links to that is signed by the corresponding private key. New records can be signed and published at any time.

Yet this still isn't a good solution, because although now we can address dynamic content in a static way, there's still a huge hash necessary to identify your content. Enter DNSLink. DNSLink is a simple concept. If you have control of a domain, you can publish TXT domain records which point to an IPNS resource. The entries look like this:

[neko@shimapan ~]$ dig TXT testipfs.neocities.org

; <<>> DiG 9.10.5-P2-RedHat-9.10.5-2.P2.fc25 <<>> TXT testipfs.neocities.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21953
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;testipfs.neocities.org.                IN      TXT

;; ANSWER SECTION:
testipfs.neocities.org. 3600    IN      TXT     "dnslink=/ipfs/QmdJtiWqGEDsUJqW41aTQcds7U2PzmLDWs8qQ346mNoPkF"

;; Query time: 16 msec
;; SERVER: 173.255.243.5#53(173.255.243.5)
;; WHEN: Fri Mar 01 21:29:31 PST 2019
;; MSG SIZE  rcvd: 124

Here we can see the dnslink record for a well-known neocities test page. Whenever testipfs.neocities.org is updated, this domain record is updated with the new hash. You can see that we're talking about a tradition IPFS resource because it's prefixed with /ipfs/ instead of /ipns/. The way that this is supposed to work is by using the FQDN which has the TXT record instead of the hash during an IPNS lookup:

ipfs cat /ipns/testipfs.neocities.org
> Error: this dag node is a directory

C:\Users\neko>ipfs cat /ipns/testipfs.neocities.org/index.html
<!doctype HTML>
<html>
  <head>
    <title>Hello!</title>
    <style>
      h1 {
        text-align: center;
      }
    </style>
  </head>
  <body>
    <h1>This is a test of the DNSLINK records with Neocities!</h1>
  </body>
</html>

Let's take a closer look at the actual node used in the DNS record:

Picture of a DAG related to the IPFS node as viewed from the DAG explorer in IPFS's web UI

That's it. That's how neocities' IPFS integration works.

But...

It doesn't seem to work for pages other than that one test page. Let's look at another page:

[neko@shimapan ~]$ dig TXT lainzine.neocities.org

; <<>> DiG 9.10.5-P2-RedHat-9.10.5-2.P2.fc25 <<>> TXT lainzine.neocities.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3317
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;lainzine.neocities.org.                IN      TXT

;; ANSWER SECTION:
lainzine.neocities.org. 3600    IN      TXT     "dnslink=/ipfs/QmP2KjhvDgFTDYpQgUqwXu7EjPvPa5sG7nnrWaaSUebHSN"

;; Query time: 5 msec
;; SERVER: 173.255.243.5#53(173.255.243.5)
;; WHEN: Fri Mar 01 21:29:46 PST 2019
;; MSG SIZE  rcvd: 124

Okay, we have a DNSLink entry for this page! But if we try to resolve it or even just try to look at it with ipfs cat, it just times out. This I believe is the behavior exhibited when there is an IPFS entry for something, but the content isn't available in the IPFS network. I'd imagine that the issue is the content isn't being hosted by neocities from an IPFS daemon. It's strange though. It goes to the work of publishing the DNS TXT record and the file is already being hosted by the site, but it's not exposing it over IPFS. I'd like to send the neocities staff an email about this, but I can't manage to find my way back to the page I found in the first place. Maybe I'll update this if I get around to hunting down the email and messaging him.

- neko.py