{"id":583,"date":"2018-05-08T03:00:16","date_gmt":"2018-05-07T19:00:16","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=583"},"modified":"2026-03-17T01:12:26","modified_gmt":"2026-03-16T17:12:26","slug":"ipfs-the-very-slow-distributed-permanent-web","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/ipfs-the-very-slow-distributed-permanent-web.html","title":{"rendered":"IPFS: The (Very Slow) Distributed Permanent Web"},"content":{"rendered":"<p>IPFS stands for InterPlanetary File System, but you could simply consider it as a distributed, permanent, but ridiculously slow, not properly functioning version of web. You could upload any static file and static website to IPFS. And the whole swarm would probably distribute your files to the moon, that might be why IPFS is so fucking slow.<\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/\">https:\/\/ipfs.io\/<\/a><\/p>\n<h2>Installation<\/h2>\n<p>Install on macOS.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ brew install ipfs<\/code><\/pre>\n<p>Start your IPFS node.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs init\ninitializing IPFS node at \/Users\/vinta\/.ipfs\ngenerating 2048-bit RSA keypair... done\npeer identity: QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\n\n$ ipfs daemon<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-init\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-init<\/a><br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-daemon\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-daemon<\/a><\/p>\n<p>Furthermore, you might want to run your IPFS node in a Docker container.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-yaml\"># docker-compose.yml\nversion: \"3\"\nservices:\n    ipfs:\n        image: ipfs\/go-ipfs:v0.4.15\n        working_dir: \/export\n        ports:\n            - \"4001:4001\" # Swarm\n            - \"5001:5001\" # web UI\n            - \"8080:8080\" # HTTP proxy\n        volumes:\n            - \"~\/.ipfs:\/data\/ipfs\"\n            - \"~\/.ipfs\/export:\/export\"<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/hub.docker.com\/r\/ipfs\/go-ipfs\/\">https:\/\/hub.docker.com\/r\/ipfs\/go-ipfs\/<\/a><\/p>\n<h2>Usage<\/h2>\n<h3>Show Node Info<\/h3>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs id\n{\n    \"ID\": \"QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\",\n    \"PublicKey\": \"A_LONG_LONG_LONG_KEY,\n    \"Addresses\": [\n        \"\/ip4\/127.0.0.1\/tcp\/4001\/ipfs\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\",\n        \"\/ip4\/172.19.0.2\/tcp\/4001\/ipfs\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\"\n    ],\n    \"AgentVersion\": \"go-ipfs\/0.4.14\/5db3846\",\n    \"ProtocolVersion\": \"ipfs\/0.1.0\"\n}<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/getting-started\/\">https:\/\/ipfs.io\/docs\/getting-started\/<\/a><\/p>\n<h3>Add Other Nodes to Your Bootstrap List<\/h3>\n<p>This one is from Muzeum, <a href=\"https:\/\/muzeum.pro\/\">https:\/\/muzeum.pro\/<\/a>.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs bootstrap add \/ip4\/52.221.121.238\/tcp\/4001\/ipfs\/QmTKYdZDkqHiY24kPynSmKbmRdk7cJxWsvvfvvvZArQ1N9\n\n# you could also connect to a node directly\n$ ipfs swarm connect \/ip4\/52.221.121.238\/tcp\/4001\/ipfs\/QmTKYdZDkqHiY24kPynSmKbmRdk7cJxWsvvfvvvZArQ1N9<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-bootstrap\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-bootstrap<\/a><br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-swarm\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-swarm<\/a><\/p>\n<h3>Add Files to IPFS<\/h3>\n<p>Every IPFS node's default storage is <code>10GB<\/code>, and a single node could only store data it needs, which also means each node only stores a small amount of whole data on IPFS. <strong>If there is not enough nodes, your data might be distributed to no one except your own node.<\/strong><\/p>\n<p>Your content is automatically pinned when you <code>ipfs add<\/code> it.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs add -r mysite\nadded QmRticJ3P5fnb9GGnUj3U9XMkYvGEnv9AQfk6YmgRhivYA mysite\/index.html\nadded QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu mysite\/readme.md\nadded QmTLhFgeWLacpbiGNYmhchHGQAhfNyDZcLt5akJFFLV89V mysite<\/code><\/pre>\n<p>If files\/folders under the folder change, the hash of the folder changes too.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ vim mysite\/index.html\n$ ipfs add -r mysite\nadded QmQTTe3deLfeULKjPHnQTcyFuCmY5JZiwSTiPT4nSt1KVK mysite\/index.html # changed\nadded QmS85tb3aKQNurFm51FaxtK6NyNei4ej3gDR21baDZXRoU mysite            # changed<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-add\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-add<\/a><\/p>\n<h3>Pin Files from IPFS<\/h3>\n<p>Pinning means storing IPFS files on local node, and prevent them from getting garbage collected. Also, you could access them much more quickly. You only need to do <code>ipfs pin add<\/code> to pin contents someone else uploaded.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs pin add -r --progress \/ipns\/ipfs.soundscape.net\/\n\n$ ipfs pin add --progress \/ipns\/ipfs.soundscape.net\/music_group\/index.json\npinned QmZwTEhdjT4MyvEnWndVEJzBjp8zGGZH1cEBpshBQs75rY recursively\n\n$ ipfs pin add --progress \/ipns\/ipfs.soundscape.net\/music_album\/index.json\npinned QmSAuGU5xt5SdR2ca2EDgeHFATSrAQhTfTYpYs9K9qmqED recursively\n\n$ ipfs pin add --progress \/ipns\/ipfs.soundscape.net\/music_recording\/index.json\npinned QmcTiadA9jRMXx77tydPa6492QJAtjXkKkA4gERaFksy94 recursively\n\n$ ipfs pin add --progress \/ipns\/ipfs.soundscape.net\/music_composition\/index.json\npinned QmTfqVaGVRnaPRQgYypGYXUvTK1UcDfK5VWYvU4rwK3m26 recursively<\/code><\/pre>\n<p>P.S. Sometimes when I <code>ipfs pin add<\/code> a file which is not on my node, the command just hangs there. I'm not sure why that once I access the file first (through <code>curl<\/code> or any browser), then <code>ipfs pin add<\/code> works fine. But it does not make sense: if I already get\/access\/download the file, I could just <code>ipfs add<\/code> the file and it would be automatically pinned.<\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-pin\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-pin<\/a><\/p>\n<h3>Get Files<\/h3>\n<p>You have several ways to get files or folders from IPFS:<\/p>\n<ul>\n<li><code>ipfs get dir-hash -o readable-dir-name<\/code>\n<ul>\n<li><code>ipfs get QmbMQNcg8TTo5dXZPtuxbns1XVq6cZJaa7vNqZzeJpKwfk -o mysite<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>ipfs get file-hash -o readable-file-name.ext<\/code>\n<ul>\n<li><code>ipfs get Qmd286K6pohQcTKYqnS1YhWrCiS4gz7Xi34sdwMe9USZ7u -o cat.jpg<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>ipfs get \/ipfs\/dir-hash\/path\/to\/file.txt<\/code>\n<ul>\n<li><code>ipfs get \/ipfs\/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG\/readme<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>ipfs get \/ipns\/example.com\/path\/to\/file.txt<\/code>\n<ul>\n<li><code>ipfs get \/ipns\/ipfs.soundscape.net\/music_group\/index.json<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>You could also access IPFS files through any public gateway:<\/p>\n<ul>\n<li><code>curl https:\/\/ipfs.io\/ipns\/peer-id\/path\/to\/file.txt<\/code>\n<ul>\n<li><code>curl https:\/\/ipfs.io\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\/index.html<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>curl https:\/\/ipfs.io\/ipns\/example.com\/path\/to\/file.txt<\/code>\n<ul>\n<li><code>curl https:\/\/ipfs.io\/ipns\/ipfs.soundscape.net\/music_group\/index.json<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>curl http:\/\/127.0.0.1:8080\/ipns\/example.com\/path\/to\/file.txt<\/code>\n<ul>\n<li><code>curl http:\/\/127.0.0.1:8080\/ipns\/ipfs.soundscape.net\/music_group\/index.json<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Download IPFS objects with <code>ipfs get<\/code>.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs ls QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ\nQmd286K6pohQcTKYqnS1YhWrCiS4gz7Xi34sdwMe9USZ7u 443362 cat.jpg\n\n# you could get a folder\n$ ipfs get QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ\n$ ls QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ\ncat.jpg\n\n# as well as a file\n$ ipfs get Qmd286K6pohQcTKYqnS1YhWrCiS4gz7Xi34sdwMe9USZ7u -o cat.jpg\n\n# get files and rename them\n$ mkdir -p soundscape\/music_group\/ soundscape\/music_album\/ soundscape\/music_recording\/ soundscape\/music_composition\/ &amp;&amp; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_group\/index.json -o soundscape\/music_group\/index.json; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_album\/index.json -o soundscape\/music_album\/index.json; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_recording\/index.json -o soundscape\/music_recording\/index.json; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_composition\/index.json -o soundscape\/music_composition\/index.json\n\n# get whole folders\n$ ipfs get \/ipns\/ipfs.soundscape.net\/music_group; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_album; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_recording; \n  ipfs get \/ipns\/ipfs.soundscape.net\/music_composition<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-get\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-get<\/a><br \/>\n<a href=\"https:\/\/discuss.ipfs.io\/t\/trying-to-better-understand-the-pinning-concept\/754\">https:\/\/discuss.ipfs.io\/t\/trying-to-better-understand-the-pinning-concept\/754<\/a><\/p>\n<p>Display IPFS object data with <code>ipfs cat<\/code>.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs cat Qmd286K6pohQcTKYqnS1YhWrCiS4gz7Xi34sdwMe9USZ7u &gt; cat.jpg\n$ ipfs cat QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv\/readme<\/code><\/pre>\n<h3>Publish a Website to IPNS<\/h3>\n<p>IPNS stands for InterPlanetary Naming System.<\/p>\n<p>Everytime you change files under a folder, the hash of the folder also changes. So you need a static reference which always points to the latest hash of your folder. You could publish your static website (a folder) to IPNS with the static reference, which is your peer ID as well as the hash of your public key.<\/p>\n<p>By default, every IPFS node has only one pair of private and public key. Therefore, you could only publish one folder with your peer ID. But you could add new keypairs through <code>ipfs key gen<\/code> and publish multiple folders.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ ipfs add -r mysite\nadded QmeqHWZgvgx5C7T6DakX75CJDRgAUoSDZayLYrcnAP8Fma mysite\/index.html\nadded QmUtuRphD9rJgRkfxwj7DcyFEAcSeH3Q1fK8nHxxoDiKK5 mysite\n\n$ ipfs name publish QmUtuRphD9rJgRkfxwj7DcyFEAcSeH3Q1fK8nHxxoDiKK5\npublished to QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6: \/ipfs\/QmUtuRphD9rJgRkfxwj7DcyFEAcSeH3Q1fK8nHxxoDiKK5\n\n$ ipfs name resolve QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\n\/ipfs\/QmUtuRphD9rJgRkfxwj7DcyFEAcSeH3Q1fK8nHxxoDiKK5<\/code><\/pre>\n<p>Click following links to see contents.<\/p>\n<ul>\n<li><a href=\"https:\/\/ipfs.io\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\/\">https:\/\/ipfs.io\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\/<\/a><\/li>\n<li><a href=\"https:\/\/ipfs.io\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\/index.html\">https:\/\/ipfs.io\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\/index.html<\/a><\/li>\n<\/ul>\n<p>After you change something, publish it again with new hash.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ vim mysite\/index.html\n$ ipfs add -r mysite\nadded QmNjbhdks8RUgDt6QiNFe5QGe2HrbCsq5FKda9D9hLVkkU mysite\/index.html # changed\nadded QmbMQNcg8TTo5dXZPtuxbns1XVq6cZJaa7vNqZzeJpKwfk mysite            # changed\n\n$ ipfs name publish QmbMQNcg8TTo5dXZPtuxbns1XVq6cZJaa7vNqZzeJpKwfk\npublished to QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6: \/ipfs\/QmbMQNcg8TTo5dXZPtuxbns1XVq6cZJaa7vNqZzeJpKwfk<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/commands\/#ipfs-name\">https:\/\/ipfs.io\/docs\/commands\/#ipfs-name<\/a><\/p>\n<h3>Create a Domain Name Alias for Your Peer ID<\/h3>\n<p>The hash is not very friendly for humans. Fortunately, you could and probably should associate a domain name with your peer ID.<\/p>\n<p>First, you need to add a TXT record whose value is <code>dnslink=\/ipns\/YOUR_PEER_ID<\/code> to your domain name. In the following article, we assume the domain name you choose is <code>ipfs.kittenphile.com<\/code>.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-console\">$ dig +short TXT ipfs.kittenphile.com\n\"dnslink=\/ipns\/QmfNy1th16zscbpxe8Q2EQdQkNFn7Y3Rp9kGZWL1EQDyw6\"\n\n$ ipfs name resolve -r ipfs.kittenphile.com\n\/ipfs\/QmaE2DcNxGjPGPfzfTQuTBTW9D57abVSv319WqC89Av1y1<\/code><\/pre>\n<p>Click following links to see contents.<\/p>\n<ul>\n<li><a href=\"https:\/\/ipfs.io\/ipns\/ipfs.kittenphile.com\/\">https:\/\/ipfs.io\/ipns\/ipfs.kittenphile.com\/<\/a><\/li>\n<li><a href=\"https:\/\/ipfs.io\/ipns\/ipfs.kittenphile.com\/index.html\">https:\/\/ipfs.io\/ipns\/ipfs.kittenphile.com\/index.html<\/a><\/li>\n<\/ul>\n<p>ref:<br \/>\n<a href=\"https:\/\/ipfs.io\/docs\/examples\/example-viewer\/example#..\/websites\/README.md\">https:\/\/ipfs.io\/docs\/examples\/example-viewer\/example#..\/websites\/README.md<\/a><br \/>\n<a href=\"https:\/\/hackernoon.com\/ten-terrible-attempts-to-make-the-inter-planetary-file-system-human-friendly-e4e95df0c6fa\">https:\/\/hackernoon.com\/ten-terrible-attempts-to-make-the-inter-planetary-file-system-human-friendly-e4e95df0c6fa<\/a><\/p>\n<h3>Public Gateway<\/h3>\n<p>If you have a public gateway and people retrieve files through it. Your public gateway fetches and stores the data, but it doesn't pin them. Files get removed with the next garbage collection run.<\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/discuss.ipfs.io\/t\/public-facing-gateway-and-pinning\/449\">https:\/\/discuss.ipfs.io\/t\/public-facing-gateway-and-pinning\/449<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>IPFS stands for InterPlanetary File System, but you could simply consider it as a distributed, permanent, but ridiculously slow, not properly functioning version of web. You could upload any static file and static website to IPFS. And the whole swarm would probably distribute your files to the moon, that might be why IPFS is so fucking slow.<\/p>\n","protected":false},"author":1,"featured_media":584,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[137],"tags":[],"class_list":["post-583","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blockchain"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/583","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=583"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/583\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/584"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=583"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=583"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=583"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}