This blog is available via IPFS

#dev #blogging

Pourquoi

Toujours dans l’objectif de décentralisation de l’Internet (et donc du pouvoir), je continue de ramener le cloud à la maison..

Vous êtes sûrement arrivé ici via votre navigateur, qui a fait une requête DNS pour savoir à quel serveur demander le contenu de pierre.roullon.fr, puis a fait une requête sur mon serveur en demandant /post/2023/025-hugo-ipfs. Vous aviez une adresse, et vous avez demandé à un tiers de confiance (la poste…) l’adresse du serveur qui correspond à ce domaine.

De mon côté, je dois payer une adresse publique fixe pour diriger le traffic de votre ordinateur au contenu que je cherche à vous servir.

IPFS est un protocole de partage de contenu Peer-2-peer. Chaque objet (page html, fichier) est identifié par un unique hash.

L’idée principale est de ne pas avoir besoin de savoir trouver ce qu’on cherche mais quoi on cherche, ainsi le premier ordinateur qui possède l’information peut la renvoyer. On ne peut pas se tromper, puisque le hash est directement dérivé du fichier lui-même, ce n’est pas une adresse.

Il y a de nombreux problèmes avec ces protocoles, le principal étant de devoir faire confiance à des autorités “centrales” pour se diriger où on veut sur internet. C’est ce qui permet les états de censurer facilement le contenu dérangeant et aux mégacorporations de dominer internet.

IPFS est un protocole qui, dans son architecture, décentralise son fonctionnement et donc empêche toute forme de concentration de pouvoir.

(Techniquement c’est aussi terriblement cool d’un point de vue infrastructure parce que le contenu est hébergé “près” de là où il est consommé, et donc limite les besoins d’infrastructures réseaux couteuses, faillible et privée. On peut facilement imaginer un internet sans Orange avec IPFS et un service mesh de voisins en voisins (littéralement))

Installation et configuration de IPFS

Installation de Kubo:

Mon fichier ansible est sur Github

Enjaillement

Premier déploiement

Ajouter le dossier à IPFS:

$ ipfs add -r ./blog/output
...
added QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD output

Pin le dossier sur le node local (même chose pour tout autre node sous votre contrôle):

$ ipfs pin add QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD
pinned QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD recursively

Testons:

$ $ curl -i http://127.0.0.1:8080/ipfs/QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Headers: Range
Access-Control-Allow-Headers: User-Agent
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: HEAD
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Length
Access-Control-Expose-Headers: Content-Range
Access-Control-Expose-Headers: X-Chunked-Output
Access-Control-Expose-Headers: X-Ipfs-Path
Access-Control-Expose-Headers: X-Ipfs-Roots
Access-Control-Expose-Headers: X-Stream-Output
Cache-Control: public, max-age=29030400, immutable
Content-Length: 7177
Content-Type: text/html
Etag: "QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD"
X-Ipfs-Path: /ipfs/QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD/
X-Ipfs-Roots: QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD
Date: Sun, 10 Sep 2023 07:45:14 GMT

<!DOCTYPE html>
...
</html>

Créer un IPNS domain name:

$ ipfs name publish /ipfs/QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD
Published to k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w: /ipfs/QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD

Testons:

$ curl -i http://127.0.0.1:8080/ipns/k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w/
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Headers: Range
Access-Control-Allow-Headers: User-Agent
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: HEAD
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Length
Access-Control-Expose-Headers: Content-Range
Access-Control-Expose-Headers: X-Chunked-Output
Access-Control-Expose-Headers: X-Ipfs-Path
Access-Control-Expose-Headers: X-Ipfs-Roots
Access-Control-Expose-Headers: X-Stream-Output
Content-Length: 7177
Content-Type: text/html
Etag: "QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD"
Last-Modified: Sun, 10 Sep 2023 07:31:43 GMT
X-Ipfs-Path: /ipns/k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w/
X-Ipfs-Roots: QmVYjxZnp2Xc8JyviyZ6Bqgpz4gUfrS3GZWg3FnF3cvRLD
Date: Sun, 10 Sep 2023 07:31:43 GMT

<!DOCTYPE html>
<html lang="fr">
...
</html>

Configurer le reverse-proxy de pierre.roullon.fr pour pointer sur la gateway IPFS:

pierre.roullon.fr {
	handle /ipns/* {
		reverse_proxy http://127.0.0.1:8080
	}

	handle /* {
		rewrite * /ipns/k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w/{path}
		reverse_proxy http://127.0.0.1:8080
	}
}

Testons:

$ curl -i https://pierre.roullon.fr
HTTP/2 301
alt-svc: h3=":443"; ma=2592000
content-type: text/html; charset=utf-8
date: Sun, 10 Sep 2023 10:44:26 GMT
location: /ipns/k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w/
server: Caddy
content-length: 104

Dommage ça fait un redirect au lieu d’un vrai rewrite. Pas réussi à faire mieux avec Caddy pour le moment.

EDIT: On peut simplement utiliser le dns local vers la gateway IPFS:

pierre.roullon.fr {
     reverse_proxy http://k51qzi5uqu5dg7qb9fn9soqt0zop0gm99u8kt5q3f4ikowrcvqv5mo9r40zb6w.ipns.localhost:8080
}

Bref, si vous lisez ceci, vous êtes passé par IPFS !

Mise à jour sur site

Il suffit à priori de republier chez moi

$ ipfs add -r .

Conclusion

Mon blog est donc accessible:

Vous pouvez installer l’extention IPFS sur chrome et firefox


Init Kubo:

Blog:

Test from mobile:

Publish to IPNS: