Web3 Workshop
IPFS Lab
Requirements
- 2 nodes for testing
- GNU/Linux Debian or Arch Based Distro (x86_64)
- curl
- tmux
Optional a third public node in case you want to connect 2 computers from diferent LANs by using it as a circuit-relay
Instalation
-
Install curl and coding base programs
$ sudo apt install curl build-essential
-
Download the Linux Kubo binary from
dist.ipfs.tech
.$ curl -O https://dist.ipfs.tech/kubo/v0.32.1/kubo_v0.32.1_linux-amd64.tar.gz
-
Untargz the file:
$ tar -xvzf kubo_v0.32.1_linux-amd64.tar.gz > x kubo/LICENSE > x kubo/LICENSE-APACHE > x kubo/LICENSE-MIT > x kubo/README.md > x kubo/install.sh > x kubo/ipfs
-
Move into the
go-ipfs
folder and run the install script:$ cd kubo $ sudo bash install.sh > Moved ./ipfs to /usr/local/bin
-
Test that IPFS has installed correctly:
$ ipfs --version > ipfs version 0.32.1
-
Setup ipfs config profile First time config setup:
$ ipfs init > generating ED25519 keypair...done > peer identity: 12D3KooWAc3ayFNYwMxooWU6tPi6fcAJaMqhBPx5oBMpdzkpq9ek > initializing IPFS node at /home/nodemaster/.ipfs
Optionally use the
--profile server
flag to remove local discovery requests
Usage
We will use the following basic commands as shown in Table 1
for our example.
Command | Description |
---|---|
ipfs init |
Initialize a new IPFS repository |
ipfs id |
Show information about your node |
ipfs daemon & |
Run IPFS daemon in the background |
ipfs add <file> |
Add a file to IPFS |
ipfs add -r <folder> |
Recursively add a folder to IPFS |
ipfs pin add <hash> |
Pin a file or directory to keep locally |
ipfs pin ls [<hash>] |
List all pinned files or directories |
ipfs pin rm <hash> |
Remove the pin on a file or directory |
ipfs get <hash> |
Retrieve a file or folder from IPFS |
ipfs dht findprovs <hash> |
Find providers of a hash |
ipfs dht provide <hash> |
Announce that you have a hash |
`ipfs dht findpeer |
Check if a node is reachable |
ipfs swarm addrs |
Show addresses connected to your node |
ipfs swarm addrs listen |
Show addresses connected to your node |
ipfs swarm connect <multiaddr> |
Manually connect to another node |
Table 1. Shows a simplied based CheatSheet for the IPFS.
Linking nodes
Verify if you can pin the node A from B and the oposite way
$ ipfs ping /ipfs/12D3KooWAc3ayFNYwMxooWU6tPi6fcAJaMqhBPx5oBMpdzkpq9ek
> .PING 12D3KooWAc3ayFNYwMxooWU6tPi6fcAJaMqhBPx5oBMpdzkpq9ek.
> .Pong received: time=0.58 ms
> .Pong received: time=0.18 ms
> .Pong received: time=0.68 ms
> .Pong received: time=0.75 ms
> .^C
> .Average latency: 0.55ms
Optionally use the
--profile server
flag to remove local discovery requests
If this doesn't work we can try to manually connect to the node by using
ipfs swarm connect
:
$ ipfs swarm connect /ipfs/12D3KooWAc3ayFNYwMxooWU6tPi6fcAJaMqhBPx5oBMpdzkpq9ek
> connect 12D3KooWAc3ayFNYwMxooWU6tPi6fcAJaMqhBPx5oBMpdzkpq9ek success
and you can verify the node is connected to your swarm
$ ipfs swarm addrs | grep 12D3KooWAVkXNR9Ym2rw2vrdnjW845AhtkjFN6BT9duLwN9ehPFo
> 12D3KooWAVkXNR9Ym2rw2vrdnjW845AhtkjFN6BT9duLwN9ehPFo (8)
Pinning (decentralizing files)
lets asume we have a file named axolotl-thoth.jpg
which we want to share
from node A to node B, first we add the file with the following command
to add and wrap it into the IPFS local node:
$ ipfs add --cid-version 1 -r -w axolotl-thoth.jpg
> added bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm axolotl-thoth.jpg
> added bafybeidry6pgmpjebqtqkq6g2lu3fu2ym64wfot5jvyuncyizvel3p2n5m
> 86.23 KiB / 86.23 KiB [========================================] 100.00%
we can verify the file is alleady pinned (added to the ipfs local node):
$ ipfs pin ls
> QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
> bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm indirect
> bafybeidry6pgmpjebqtqkq6g2lu3fu2ym64wfot5jvyuncyizvel3p2n5m recursive
if you have many files you can | grep <CID>
after the verification command.
Now on node B and once verified that bouth nodes are linked, we proceed with pinning the hash which will mean we have a copy in our IPFS node as tracked and shared (decentralized).
$ ipfs pin ls
> QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
$ ipfs pin add bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm
> pinned bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm recursively
$ ipfs pin ls
> bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm recursive
> QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn recursive
as shown we can se the file is already pinned and added to our nodes ipfs
and we can get it into our file system by using the ipfs get <CID>
$ ipfs get bafkreihiuou4poc45gqxg7fsdsd733cmmottsppr65ldqmbaxapx2vyfgm -o axolotl-thoth.jpg
> Saving file(s) to axolotl-thoth.jpg
> 86.23 KiB / 86.23 KiB [=====================================] 100.00% 0s
$ ls
> axolotl-thoth.jpg kubo_v0.32.1_linux-amd64.tar.gz -O
> kubo kubo_v0.32.1_linux-amd64.tar.gz.sig
$ sha256sum axolotl-thoth.jpg
> e8a3a9c7b85ce9a1737cb21c87fdec4c63a7393df1f756383020b81f7d570533 axolotl-thoth.jpg
here we also show the file and verify the sha256 checksum
Static Site Decentralization
Requirments
Instalation
First we go to the deno website and install it as it specifies for our OS:
$ curl -fsSL https://deno.land/install.sh | sh
> ######################################################################## 100.0%
> Archive: /home/nodemaster/.deno/bin/deno.zip
> inflating: /home/nodemaster/.deno/bin/deno
> Deno was installed successfully to /home/nodemaster/.deno/bin/deno
> info: backing '/home/nodemaster/.profile' up to '/home/nodemaster/.deno/.shellRcBackups/.profile.bak'
> info: backing '/home/nodemaster/.bashrc' up to '/home/nodemaster/.deno/.shellRcBackups/.bashrc.bak'
>
> Deno was added to the PATH.
> You may need to restart your shell for it to become available.
>
> Run '/home/nodemaster/.deno/bin/deno --help' to get started
>
> Stuck? Join our Discord https://discord.gg/deno
After restarting the shell we select a theme from lume land themes for the current example we will use the simple blog theme:
$ mkdir my-blog && cd my-blog
$ deno run -A https://lume.land/init.ts --theme=simple-blog
> Welcome to Lume v2.5.1!
>
> File saved: _data.yml
> File saved: 404.md
> File saved: favicon.png
> File saved: posts/instructions.md
>
> 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
>
> BENVIDO - WELCOME! 🎉🎉🎉
>
> Lume has been configured successfully!
> Theme installed: Simple Blog
>
> 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
>
> Quick start:
>
> deno task serve to start a local server
> deno task cms to start the CMS
>
> See https://lume.land for online documentation
> See https://discord.gg/YbTmpACHWB to propose new ideas and get help at Discord
> See https://github.com/lumeland/lume to view the source code and report issues
> See https://github.com/lumeland/theme-simple-blog to view the theme source code and report issues
> See https://opencollective.com/lume to support Lume development
Setup and Testing
The next steps is that we require to setup relative paths for our static
website this is require to work properly on any IPFS gateway. First edit
the file _config.ts
which looks like the following in the
decentralized science website:
1 import lume from "lume/mod.ts";
2 import relativeUrls from "lume/plugins/relative_urls.ts";
3 import wiki from "wiki/mod.ts";
4
5 const site = lume({
6 location: new URL("https://decentralizedscience.org"),
7 });
8
9 site.copy("img");
10
11 site.use(relativeUrls());
12 site.use(wiki());
13
14 export default site;
Notice that the lines to make the paths relative are 2
and 11
.
While you work on your website you can live watch the changes but executing
the command deno task serve
:
$ deno task serve
> Task serve deno task lume -s
> Task lume echo "import 'lume/cli.ts'" | deno run -A - "-s"
> Loading config file file:///home/nodemaster/_config.ts
> 🔥 /kubo/readme/ <- /kubo/README.md
> 🔥 /404.html <- /404.md
> 🔥 /posts/instructions/ <- /posts/instructions.md
> 🔥 / <- /index.vto
> 🔥 /styles.css <- /styles.css
> 🔥 /archive/instructions/ <- /archive_result[0].page.js
> 🔥 /author/oscar-otero/ <- /archive_result[1].page.js
> 🔥 /archive/ <- /archive[0].page.js
> 🔥 /pagefind/pagefind.en_facec4f167.pf_meta <- (generated)
> 🔥 /pagefind/wasm.en.pagefind <- (generated)
> 🔥 /pagefind/fragment/en_6e896e2.pf_fragment <- (generated)
> 🔥 /pagefind/index/en_8cead82.pf_index <- (generated)
> 🔥 /pagefind/filter/en_5b2039e.pf_filter <- (generated)
> 🔥 /pagefind/pagefind.js <- (generated)
> 🔥 /pagefind/pagefind-highlight.js <- (generated)
> 🔥 /pagefind/pagefind-ui.css <- (generated)
> 🔥 /pagefind/pagefind-modular-ui.js <- (generated)
> 🔥 /pagefind/pagefind-modular-ui.css <- (generated)
> 🔥 /pagefind/pagefind-entry.json <- (generated)
> 🔥 /sitemap.xml <- (generated)
> 🔥 /robots.txt <- (generated)
> 🔥 /feed.xml <- (generated)
> 🔥 /feed.json <- (generated)
> 🔥 /pagefind/pagefind-ui.js <- (generated)
> 🔥 /pagefind/wasm.unknown.pagefind <- (generated)
> 🔥 /favicon.png <- /favicon.png
> 🔥 /js/main.js <- https://deno.land/x/lume_theme_simple_blog@v0.15.10/src/js/main.js
> 🔥 /js/comments.js <- https://cdn.jsdelivr.net/npm/@oom/mastodon-comments@0.3.2/src/comments.js
> 🍾 Site built into ./_site
> 28 files generated in 5.92 seconds
> Server started at:
> http://localhost:3000/ (local)
> http://10.97.239.92:3000/ (network)
Decentralization
The process requires to build the project where we will get an output directory
that contains the our static site named _site
, and once we have it we will
do an ipfs pin add with some parameter for a better compatibiliy as shown:
$ deno task build
> Task build deno task lume
> Task lume echo "import 'lume/cli.ts'" | deno run -A -
> Loading config file file:///home/nodemaster/my-blog/_config.ts
> 🔥 /404.html <- /404.md
> 🔥 /posts/instructions/ <- /posts/instructions.md
> 🔥 / <- /index.vto
> 🔥 /styles.css <- /styles.css
> 🔥 /archive/instructions/ <- /archive_result[0].page.js
> 🔥 /author/oscar-otero/ <- /archive_result[1].page.js
> 🔥 /archive/ <- /archive[0].page.js
> 🔥 /pagefind/pagefind.en_facec4f167.pf_meta <- (generated)
> 🔥 /pagefind/wasm.en.pagefind <- (generated)
> 🔥 /pagefind/fragment/en_6e896e2.pf_fragment <- (generated)
> 🔥 /pagefind/index/en_8cead82.pf_index <- (generated)
> 🔥 /pagefind/filter/en_5b2039e.pf_filter <- (generated)
> 🔥 /pagefind/pagefind.js <- (generated)
> 🔥 /pagefind/pagefind-highlight.js <- (generated)
> 🔥 /pagefind/pagefind-ui.css <- (generated)
> 🔥 /pagefind/pagefind-modular-ui.js <- (generated)
> 🔥 /pagefind/pagefind-modular-ui.css <- (generated)
> 🔥 /pagefind/pagefind-entry.json <- (generated)
> 🔥 /sitemap.xml <- (generated)
> 🔥 /robots.txt <- (generated)
> 🔥 /feed.xml <- (generated)
> 🔥 /feed.json <- (generated)
> 🔥 /pagefind/pagefind-ui.js <- (generated)
> 🔥 /pagefind/wasm.unknown.pagefind <- (generated)
> 🔥 /favicon.png <- /favicon.png
> 🔥 /js/comments.js <- https://cdn.jsdelivr.net/npm/@oom/mastodon-comments@0.3.2/src/comments.js
> 🔥 /js/main.js <- https://deno.land/x/lume_theme_simple_blog@v0.15.10/src/js/main.js
> 🍾 Site built into ./_site
> 27 files generated in 0.12 seconds
Now we ipfs pin add
on our local node and save the output to a file
so that we remember which are the assets hashes, specifically the _site
which is the one of our highest interest because it links the others.
$ ipfs add --cid-version 1 -r -w _site/ > myBlogCID.txt
> 368.93 KiB / 368.93 KiB
> [================================================================================================================]
> 100.00%
$ tail myBlogCID.txt
> added bafybeiammkufyfabclfpkhiyuqvi33daoy63eghnm6ek5hpbt25n6hfkle _site/author
> added bafybeiheyhjqooii5rz6fycli3e5ut2dxn5aoei7pkgeeul4h33m53ne2y _site/js
> added bafybeibb4zvebkd34fggnigvay2nequ64isc5wfwlx27xzlqfvunf4e5ha _site/pagefind/filter
> added bafybeiaivvexmb7hnw2nl2s36z5u5rb36vdfmg3xolle22bctkyewlipca _site/pagefind/fragment
> added bafybeiacg6235tzuvg7rkpjmq7ii7ry56pl2fx6thczxit624vqbsrgrna _site/pagefind/index
> added bafybeifcqk7srojaphi7hiz4rswsg564ax63hsjgmlhlnb66zpqimy5snq _site/pagefind
> added bafybeiglzvnozx2w42gxjm3f3dhf7qselu5lia2tt267glsi42qibculfm _site/posts/instructions
> added bafybeighw2tyct7pe5dezbooxywwkni2l6kqu5esaj3tnu7exgdie7skae _site/posts
> added bafybeicvxfaxdmtpormu4yn33pn3apyqu6wbn7nksnn26bgoiuadnsa4je _site
> added bafybeigloh3jxjxxzcmypgga6hqcnu3w4pkoyqlsydshpulvpf22banise
You can verify in your local node that the site is already being served.
For this example url notice we write the CID of the _site
after /ipfs/
http://127.0.0.1:8080/ipfs/bafybeicvxfaxdmtpormu4yn33pn3apyqu6wbn7nksnn26bgoiuadnsa4je/
And finally now you can ipfs pin add
CID hash
bafybeicvxfaxdmtpormu4yn33pn3apyqu6wbn7nksnn26bgoiuadnsa4je
in other nodes
or online pinning services which probably also serve the site through their
gateway.
ToDo
- [x] Setup incus in both laptops with debian stable
- [x] Install requirements
- [x] Install IPFS
- [x] IPFS Usage and tests (share a file)
- [ ] Setup lume land blog
- [ ] Decentralize the blog
- [ ] pinning services
- [ ] [Blockchain integrationAlloy
- [ ] integrate dapp i ndexer
- [ ] setup ddns and domain names
- [ ] alt setup with nginx (future)