Introducción a IPFS — InterPlanetary File System

per Victor Carceler darrera modificació 2021-07-12T17:14:19+02:00

https://upload.wikimedia.org/wikipedia/commons/1/18/Ipfs-logo-1024-ice-text.png IPFS — InterPlanetary File System es una herramienta libre que, tal y como su nombre indica, implementa un sistema de ficheros distribuido a nivel planetario y, quizás algún día, inter planetario :-)

Es decir los diferentes nodos que ejecutan IPFS se conectan entre sí utilizando tecnología P2P y colaboran para alojar ficheros en un espacio de nombres global.

Los datos en IPFS son inmutables y están direccionados por contenido.

Naturalmente se trata de un sistema descentralizado en el que cualquiera puede participar y permite compartir ficheros a lo largo y ancho del planeta con pocos recursos y buen rendimiento. Replicando la información de manera automática entre aquellos nodos que acceden a los contenidos.

Instalación de IPFS

Tal y como nos indican en https://ipfs.io/#install podemos instalar:

  • IPFS Desktop. Un archivo con todo lo necesario para ejecutar un nodo IPFS y acceder a la interfaz web desde un navegador sin tener que abrir la línea de comandos. En GNU/Linux está empaquetado como una aplicación AppImage así que es suficiente con descargar y ejecutar.
  • IPFS Command-line. Un archivo para trabajar desde la línea de comandos. Permite ejecutar un nodo IPFS, realizar cualquier operación en la red y, por supuesto, acceder a la interfaz web con un navegador.
  • IPFS Companion. Una extensión para Firefox —y otros navegadores— que añade soporte para URLS de IPFS. Utiliza un nodo local.

De las tres opciones IPFS Command-line es la que permite mayor flexibilidad, su instalación es realmente sencilla.

  1. Se descarga el código desde https://dist.ipfs.io/#go-ipfs
    wget https://dist.ipfs.io/go-ipfs/v0.9.0/go-ipfs_v0.9.0_linux-amd64.tar.gz
  2. Se desarchiva
    tar xzf go-ipfs_v0.9.0_linux-amd64.tar.gz
  3. Y se lanza la instalación que copia el binario ipfs en /usr/local/bin/ipfs
    cd go-ipfs
    sudo ./install.sh

Alternativamente se puede copiar el binario manualmente en algún directorio indicado en $PATH o bien declarar un alias para utilizar la herramienta. Ni es necesario ni se recomienda ser administrador para utilizar la herramienta.

Configuración del nodo y repositorio

Ya estamos a un paso de tener un nodo IPFS funcional. Únicamente nos falta ejecutar:

ipfs init

Para crear un fichero de configuración e inicializar el repositorio en el que se guardarán los datos. Por defecto se creará el directorio ~/.ipfs aunque la variable de entorno $IPFS_PATH nos permitirá trabajar con otro directorio si fuéra necesario.

La configuración será ~/.ipfs/config y por defecto tiene unos valores funcionales que nos permitirán operar un nodo teniendo:

  • El repositorio en ~/.ipfs. El subdirectorio ~/.ipfs/blocks crecerá a medida que accedamos a contenidos o publiquemos los nuestros. La configuración indica un tamaño StorageMax de 10GB para hacer de cache pero si añadimos nuestros propios contenidos (pin) podremos superar este valor sin problema.
  • La interfaz web se publicará en http://127.0.0.1:5001/webui y se podrá consultar desde el nodo local.
  • Un gateway IPFS en http://127.0.0.1:8080

Puestra en marcha del servicio

Para lanzar el demonio IPFS bastará con hacer:

ipfs daemon

Mientras tengamos el demonio en marcha se descubrirán nodos y se participará en la red de manera automática.

peers.webp

Acceso a los contenidos de IPFS

Una idea fundamental de IPFS es el direccionamiento por contenido. Normalmente en un sistema de archivos (o en la web) se accede a los contenidos a partir del lugar (directorio y nombre de fichero o URL y ruta) en el que están almacenados. Sin embargo en IPFS los nodos se conectan y desconectan de la red de manera dinámica y no necesitamos saber dónde están los contenidos a los que accedemos.

En IPFS todos los contenidos están direccionados por un CIDContent Identifier—. Si tienes el CID de un objeto se puedes acceder al objeto a partir de las réplicas que se guardan en los nodos que participan en la red. Y si del objeto se hace una nueva versión con otros contenidos entonces cada versión tendrá su CID diferente :-)

Naturalmente el acceso a los contenidos se puede realizar a partir de nuestro nodo y esto tiene la ventaja de que nuestro nodo pasará a ser una réplica más de esos contenidos, pero también se puede realizar a partir de un gateway público de IPFS como:

  • El que mantiene el propio proyecto en https://ipfs.io/
  • El que mantiene Cloudflare en https://cloudflare-ipfs.com/

Estos gateways resuelven peticiones /ipfs/<CID> que permiten acceder a IPFS desde cualquier navegador.

Por ejemplo, sabiendo que QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm es el CID de un directorio que contiene una colección de cómics de xkcd.com.

Se pueden utilizar los gateways anteriores para acceder a los contenidos en IPFS utilizando cualquiera de estas dos URLS:

Donde se puede consultar el archivo accediendo a un elemento:

  1. A partir de su ruta en el archivo. Por ejemplo https://ipfs.io/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm/1675%20-%20Message%20in%20a%20Bottle/1675%20-%20Message%20in%20a%20Bottle.png
  2. O directamente a partir del CID que tendrá dicho objeto https://ipfs.io/ipfs/QmPYybpotS8bvSiWaKdmPPLAaDBVXgr2PRnXJh4tmxmLg6

Acceso a los contenidos utilizando nuestro nodo IPFS

Al ejecutar ipfs daemon tendremos nuestro propio gateway IPFS disponible en http://127.0.0.1:8080. De manera que para acceder al directorio que contiene la anteriormente mencionada colección de cómics de xkcd.com y que tenía por CID QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm podremos acceder a la URL http://127.0.0.1:8080/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm desde nuestro navegador.

También será posible utilizar la interfaz web de nuestro nodo http://127.0.0.1:5001/webui para explorar la red y hacer diferentes operaciones con los contenidos.

O bien utilizar el comando ipfs en el terminal para explorar los contenidos:

[vcarceler@alumne-1-58 ~]$ ipfs ls /ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm
QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR - 1 - Barrel - Part 1/
QmdC5Hav9zdn2iS75reafXBq1PH4EnqUmoxwoxkS5QtuME - 10 - Pi Equals/
QmcyyLvDzCrduuvGVUQEh1DzFvM7UWGfc9sUg87PjjYCw7 - 100 - Family Circus/
Qmd8NDeJhzf614FSBxZwu4QD2Az14tQtJhQXJf8h4fqiSx - 1000 - 1000 Comics/
QmXWjDBMDHbYHkS1PiDLP4oHxfzLypg26Wt9R8tGvTBBL3 - 1001 - AAAAAA/
QmYuGMrnxr1mS62Q9W1ovY4LobTzMHDAvc2rJBVU5Bnz8a - 1002 - Game AIs/
QmQCt6Z9bdn4AJXkrw3ie6ZSGhUmLJTpRhWZXUKxChhkn4 - 1003 - Adam and Eve/
QmZqkuqX1qTspb1GgmnzyRFetf1uMyA3CemvvgPZD39sPo - 1004 - Batman/
QmQNZgecPDVQWrxZMK6dULq8FDXRnfkCr7vyZvqMHF17Rz - 1005 - SOPA/
:

Pero probablemente la opción más interesante sea montar los sistemas de ficheros ipfs e ipns —que es un sistema para nombrar a los contenidos— en dos directorios locales. Por defecto se intentan utilizar los directorios /ipfs e /ipns pero las opciones --ipfs-path y --ipfs-name nos permitirán especificar los directorios que queramos.

Por ejemplo:

[vcarceler@alumne-1-58 ~]$ mkdir ipfs ipns
[vcarceler@alumne-1-58 ~]$ ipfs mount --ipfs-path ~/ipfs --ipns-path ~/ipns
IPFS mounted at: /home/vcarceler/ipfs
IPNS mounted at: /home/vcarceler/ipns
[vcarceler@alumne-1-58 ~]$

Con lo cual podremos acceder a los contenidos de IPFS como si fueran ficheros locales.

[vcarceler@alumne-1-58 ~]$ cd ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm
[vcarceler@alumne-1-58 QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm]$ ll
total 0
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1 - Barrel - Part 1'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '10 - Pi Equals'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '100 - Family Circus'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1000 - 1000 Comics'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1001 - AAAAAA'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1002 - Game AIs'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1003 - Adam and Eve'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1004 - Batman'
dr-xr-xr-x. 1 root root 0 11 jul. 12:46 '1005 - SOPA'
:

Publicar datos con IPFS

Ya hemos visto diferentes maneras de acceder a los datos publicados en IPFS pero todavía no hemos publicado ningún contenido nuevo.

Supongamos que queremos publicar en IPFS la traducción de un poema de Mayakovski que figura en esta página de Wikisource: https://es.wikisource.org/wiki/%C2%A1Escuchen!

El propio proyecto Wikisource nos permite descargar un fichero con la traducción del poema en formato EPUB. Una vez descargado se puede agregar al repositorio de nuestro nodo IPFS con un solo comando:

[vcarceler@alumne-1-58 ~]$ ipfs add ~/Baixades/¡Escuchen\!.epub 
added Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa ¡Escuchen!.epub
64.78 KiB / 64.78 KiB [=======================================================================================================================================] 100.00%[vcarceler@alumne-1-58 ~]$

Al añadir ficheros —se pueden añadir ficheros de manera recursiva con el parámetro -r o --recursive— se devuelve un CIDpara cada objeto. En este caso: Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa.

Podemos comprobar a través de nuestro nodo que el fichero está disponible en IPFS

[vcarceler@alumne-1-58 ~]$ ll /home/vcarceler/ipfs/Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa
-r--r--r--. 1 root root 66331 12 jul. 11:29 /home/vcarceler/ipfs/Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa
[vcarceler@alumne-1-58 ~]$

Y también, quizás pasados unos minutos, a través de cualquier gateway público.

Naturalmente cualquier otra copia exacta del mismo fichero tendrá el mismo CID y si se publica una nueva versión de la traducción del poema con algún cambio tendrá un CID diferente.

Repositorio de IPFS local: cache y persistencia

Cuando se utiliza un nodo IPFS para acceder a contenidos, estos contenidos se descargan al repositorio del nodo que por defecto se encuentra en ~/.ipfs. De esta manera el nodo mantiene su propia réplica de los contenidos y puede servir esos contenidos a otros nodos de la red.

Naturalmente existe un mecanismo para eliminar automáticamente estos contenidos del repositorio local cuando ya no son necesarios, es el mecanismo de recolección de basura.

La configuración por defecto de IPFS ~/.ipfs/config tiene los siguientes valores:

"StorageMax": "10GB",
"StorageGCWatermark": 90,
"GCPeriod": "1h",

De manera que:

  • Se fija como 10GiB la capacidad máxima del repositorio. Esto no quiere decir que no se pueda superar esta capacidad, sino que se intentará que los objetos en cache no superen esta capacidad.
  • Se indica que convendrá eliminar objetos de la cache cuando la capacidad del repositorio supere el 90% del tamaño máximo.
  • Se indica que cada hora convendrá lanzar el recolector de basura que intentará eliminar contenidos cacheados del repositorio su capacidad supera el 90% de la máxima.

Además existe un mecanismo —pin files— que permite marcar contenidos del repositorio de manera que no sean eliminados por el recolector de basura. Así podemos garantizar que nuestro nodo siempre estará publicando los contenidos que nosotros queramos.

Por defecto todos los contenidos que se añaden desde el terminal con el comando ipfs add se marcan como pinned para que persistan en el repositorio.

[vcarceler@alumne-1-58 ~]$ ipfs pin ls /ipfs/Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa
Qmdo7U491sboHdLeWNvHrVowijoW93juZon7bNWsFVnkfa recursive
[vcarceler@alumne-1-58 ~]$

IPNS un sistema de nombres para referenciar contenido

Como IPFS es un sistema en el que se utiliza direccionamiento por contenido el CID de un objeto cambia cada vez que se hace una modificación a dicho objeto.

Esto quiere decir que si se comparte un directorio con una colección de ficheros deberemos hacer llegar un nuevo CID a los usuarios cada vez que se haga un cambio en la colección. Afortunadamente existe IPNSInterPlanetary Name System— que es un sistema de nombres que permite obtener una referencia constante hacia un CID, de manera que al actualizar la colección se puede actualizar el nombre IPNS para que apunte al nuevo CID.

Veamos un ejmplo en el que queremos publicar un directorio que contiene una colección de ficheros.

Podemos comenzar con el directorio ficheros que contendrá El ingenioso hidalgo Don Quijote de la Mancha descargado desde https://es.wikisource.org/wiki/Don_Quijote_de_la_Mancha.

[vcarceler@alumne-1-58 ~]$ tree ficheros
ficheros
└── El_ingenioso_hidalgo_Don_Quijote_de_la_Mancha.epub

0 directories, 1 file
[vcarceler@alumne-1-58 ~]$

Como se trata de un directorio utilizaremos la opción -r o --recursive para añadir los contenidos al repositorio IPFS.

[vcarceler@alumne-1-58 ~]$ ipfs add -r ficheros/
added QmXrrEdaapBQ1pL5jLRFK1D8xDGapf9nWSDen7pgount7Z ficheros/El_ingenioso_hidalgo_Don_Quijote_de_la_Mancha.epub
added QmZzStXG2GCmYfX6arg34h6KsXnLf4L9jMbdBEEi8DEGjw ficheros
64.27 KiB / 64.27 KiB [=======================================================================================================================================] 100.00%[vcarceler@alumne-1-58 ~]$

Hemos obtenido dos CID que nos permiten referenciar el libro y el directorio que contiene la colección.

Podemos publicar el directorio con un nombre IPNS

[vcarceler@alumne-1-58 ~]$ ipfs name publish QmZzStXG2GCmYfX6arg34h6KsXnLf4L9jMbdBEEi8DEGjw
Published to k51qzi5uqu5dik6o9zqt3t8ana72l3jrm37adj0f2kwq7txevxwm2hyovw4fxe: /ipfs/QmZzStXG2GCmYfX6arg34h6KsXnLf4L9jMbdBEEi8DEGjw
[vcarceler@alumne-1-58 ~]$

Con lo que podremos acceder a la colección con el esquema /ipns/k51qzi5uqu5dik6o9zqt3t8ana72l3jrm37adj0f2kwq7txevxwm2hyovw4fxe.

quijote1.webp

Si añadimos un segundo libro a la colección

[vcarceler@alumne-1-58 ~]$ tree ficheros/
ficheros/
├── El_ingenioso_caballero_Don_Quijote_de_la_Mancha.epub
└── El_ingenioso_hidalgo_Don_Quijote_de_la_Mancha.epub

0 directories, 2 files
[vcarceler@alumne-1-58 ~]$

Será necesario añadir los nuevos contenidos al repositorio

[vcarceler@alumne-1-58 ~]$ ipfs add -r ficheros/
added QmSKpSc1Nw2g9er62Z4xmqf16jaPfiPnyUYvjKZoHyNv3X ficheros/El_ingenioso_caballero_Don_Quijote_de_la_Mancha.epub
added QmXrrEdaapBQ1pL5jLRFK1D8xDGapf9nWSDen7pgount7Z ficheros/El_ingenioso_hidalgo_Don_Quijote_de_la_Mancha.epub
added QmeD8s2RVVEfCT3PLV91YHyyq8Ye3MEgXPHxyzjA5Q9C94 ficheros
 128.50 KiB / 128.50 KiB [=====================================================================================================================================] 100.00%[vcarceler@alumne-1-58 ~]$

Y podremos observar:

  • El fichero El_ingenioso_hidalgo_Don_Quijote_de_la_Mancha.epub mantiene el mismo CID porque tiene el mismo contenido.
  • El fichero El_ingenioso_caballero_Don_Quijote_de_la_Mancha.epub que acabamos de añadir obtiene un CID propio.
  • El directorio ficheros obtiene un CID nuevo porque ahora no tiene el mismo contenido que antes.

Finalmente podemos volver a publicar el nuevo CID de ficheros con el mismo nombre IPNS.

[vcarceler@alumne-1-58 ~]$ ipfs name publish QmeD8s2RVVEfCT3PLV91YHyyq8Ye3MEgXPHxyzjA5Q9C94
Published to k51qzi5uqu5dik6o9zqt3t8ana72l3jrm37adj0f2kwq7txevxwm2hyovw4fxe: /ipfs/QmeD8s2RVVEfCT3PLV91YHyyq8Ye3MEgXPHxyzjA5Q9C94
[vcarceler@alumne-1-58 ~]$

quijote2.webp

Conviene observar que los nombres IPNS por defecto tienen una validez de 24h así que si queremos que sean permanentes convendrá tener una tarea periódica que republique el nombre, por ejemplo, cada 8h.