Decentralized hosting of a static react app with IPFS
Let’s learn how to deploy an app to the decentralized file system IPFS! We will also see how we can do this anonymous and how to mitigate censorship.
Get IPFS running
IPFS (Interplanetary File System) is a decentral organized P2P file system, that enables anyone to store and retrieve files from it. Each file is accessed by it’s hash, which serves as an unique identifier. You can download IPFS here and install it by executing following commands (Mac and Linux).
tar xvfz go-ipfs.tar.gz
Then you can run it with
ipfs help . Alternatively you can install a desktop client.
Create an example App
Now, that we have IPFS running, we need an application to deploy. For this purpose I will create an example app with
create-react-app. Proceed by creating a demo app with
npx create-react-app ipfsdemo. Once all the dependencies are downloaded start your development server with
cd ipfsdemo && yarn start. Navigate to the
App.js file in your favorite code editor and add some content. When you’re happy with your super simple react app and think it’s time to deploy you first have to go to the
package.json and add following line
“homepage”: “./”, to tell the build process that your base directory is in the same folder. Then you can build the static react app with
yarn build. Try and open the
build/index.html file in your browser and see if everything still looks fine.
Deploying to IPFS
To deploy the app you just have to add the folder to the ipfs using
ipfs add -r build. The last line of the console output should look similar to this:
added QmTVH3MTej9zB3ELAACGagE6C6976ha2yTFNftj5FeoCHu build
This is the hash of your folder, that can be used to globally identify it. Go ahead and try opening it via your local gateway
http://127.0.0.1:8080/ipfs/<yourHash>. Anyone that has an IPFS node up and running can now access this app in the same way. Pretty awesome, huh?
What about the people that don’t run an IPFS node? Enter public gateways. IPFS itself offers a public gateway, that exposes files living in the IPFS via HTTP. You can access it via
https://ipfs.io/ipfs/<yourHash>. Go ahead and send the link to a friend and see if he can open your app! Infura offers another public IPFS gateway at
ipfs.infura.io/ipfs/<yourHash>, but it can take a little while sometimes.
Remember that IPFS accesses the files via a P2P network? This means, that if you put your app onto your own IPFS node and then shut it down, no one can access your app via a public gateway, because the gateway looks for your file in the P2P network, and the only one (currently) having it is you! If other users, that run a local IPFS node, access your app they will get a local copy and be able to serve it from now on, until the garbage collection throws it away. To prevent garbage collection one can pin the file.
If you want your app to stay accessible by the network all the time, you have following options: Don’t turn off your computer and internet connection, host an IPFS node (for example with Nodefort) and pin the app, or pay a service, that runs an IPFS node, for pinning your service. These services are usually paid in crypto and let your files stay as long as you pay for it on their servers. Some services are IPFSstore, Pinbits and Eternum. For example Eternum takes $0.3 per GB/month for hosting your file, so for $1 the example react app can be pinned for roughly 14 years.
So now we are left with two new problems:
1. If we change something in our app and redeploy it, we — due to the very nature of hashes — get a different hash. That’s intended, but a little impractical.
2. A link containing a hash is a little but bulky and not even close to memorable.
In another article Mark Pors tried to solve the problems. IPFS has another built-in mechanism, that is named IPNS. With IPNS you can exchange the content behind a fixed hash, like a symlink, where you change what it points to. Using
ipfs name publish <yourHash> you can get an alias hash, that resolves to the published hash. You can then access it via
https://ipfs.io/ipns/<aliasHash>. If you publish another, different hash, the alias hash will stay the same. This hash is still hard to memorize. To solve this problem you can use your domain, e.g. example.com, and add an TXT record like this:
Now you can access the app via
https://ipfs.io/ipns/example.com, this is still a bit bulky but better.
Unfortunately — you may have noticed by now, if you followed along — IPNS is slow, really, really slow. It takes about 1–2 minutes to publish and resolve IPNS hashes. So this is not an option. Hopefully this will improve in future.
IPFS links are not human friendly and currently there is no good solution to that problem.
The only feasible alternative at the moment is to redirect your domain directly to the IPFS link, if you change something you have to change the redirect. At elbstack we are currently looking into a solution for this problem and hope to show up with a solution soon.
Anonymous and uncensorable
Why even consider deploying app or content decentralized? The answer is anonymity and little to no means to censor the content. While servers are usually owned, or rented, by a person, no one really knows who the owner of a file is that was pinned to an IPFS node, especially if other nodes access and locally replicate this file. With the right measures it is literally impossible to find the creator. Add a file to IPFS, pay a pinning service with cryptos, that can’t be tracked back to a person, remove the file from your local node.
The more people use IPFS, the harder it gets to censor content.
If someone, for example a central authority, would want to have content from the IPFS removed, they only can achieve this by tracking down all copies of the file. This is especially hard when users replicate the content on their local IPFS node and shut their computer down. The most they can do is remove the file from the server of a pinning service. But if your content only lives on one node, the pinning service, and is only accessed by the gateway, no replications will be made, which means it’s only central and not decentral distributed. This shows, that IPFS needs users with local nodes, to make it truly decentral.
We were able to deploy an app with one line of code and make it available in a decentral way, but faced new challenges regarding immutability and easy accessibility via domains, which still have no satisfying solution. And we have also seen, that the IPFS can contribute to making the internet uncensorable and anonymous. Maybe in the future IPFS could become a more common way to deploy applications, which would also provide the edgiest CDN of all times, all assets would be replicated by the user and would be available at many nodes in the P2P network.