Once you have spawned your Garage cluster, you might want to federate or share efficiently your content with the rest of the world.
In this blog post, we try to connect the InterPlanetary File System (IPFS) daemon to Garage.
We discuss the different bottleneck and limitations of the currently available software.
<!-- more -->
<!--Garage has been designed to be operated inside the same "administrative area", ie. operated by a single organization made of members that fully trust each other.
It is an intended design decision: trusting each other enables Garage to spread data over the machines instead of duplicating it.
Still, you might want to share and collaborate with the rest of the world, and it can be done in 2 ways with Garage: through the integrated HTTP server that can serve your bucket as a static website,
or by connecting it to an application that will act as a "proxy" between Garage and the rest of the world.
We refer as proxy software that know how to speak federated protocols (eg. Activity Pub, Solid, RemoteStorage, etc.) or distributed/p2p protocols (eg. Bittorrent, IPFS, etc.).-->
People often struggle to see the difference between IPFS and Garage, so let's start by making clear that these projects are complementary and not interchangeable.
Personnaly, I see IPFS as the intersection between Bittorrent and a filesystem. Bittorrent remains probably one of the most efficient way to deliver
a copy of a file or a folder to a very large number of people. But it lacks some interactivity: once a torrent file has been generated, you can't simply
add a file to it. By adopting a filesystem abstraction, IPFS handles such use case smoothly.
<!--IPFS is a content-addressable network built in a peer-to-peer fashion.
With simple words, it means that you query the content you want with its identifier without having to know *where* it is hosted on the network, and especially on which machine.
However, you would probably not rely on Bittorrent to durably store your encrypted holiday pictures you shared with your friends, and this is the same for IPFS.
If at some time, everyone has a copy of the picture on their hard disk, people might delete it after a while without you knowing it.
You also can't easily collaborate to share this common treasure, for example, there is no automatic way to say that Alice and Bob
are in charge of storing the first half of the archive while Charlie and Eve are in charge of the second half.
[Resilio](https://www.resilio.com/individuals/) and [Syncthing](https://syncthing.net/) both feature protocols inspired by Bittorrent to synchronize a tree of your filesystem between multiple computers.
Reviewing these solutions is out of the scope of this article, feel free to try them by yourself!*
Garage, on the contrary, is designed to spread automatically your content over all your available nodes to optimize your storage space. At the same time, it ensures that your content is always replicated exactly 3 times across the cluster (or less if you change a configuration parameter!) on different geographical zones (if possible).
<!--To access this content, you must have an API key, and have a correctly configured machine available over the network (including DNS/IP address/etc.). If the amount of traffic you receive is way larger than what your cluster can handle, your cluster will become simply unresponsive. Sharing content across people that do not trust each other, ie. who operate independant clusters, is not a feature of Garage: you have to rely on external software.-->
But independant Garage nodes can not collaborate to deliver popular contents: every one is playing alone.
All ressources created (keys, files, buckets) are tightly coupled to a cluster, people from different clusters can't collaborate on the same data (without additional software).
➡️ **Garage is designed to durably store content.**
In this blog post, we will explore if we can combine both properties by connecting an IPFS node to a Garage cluster.
## Try #1: Vanilla IPFS over Garage
<!--If you are not familiar with IPFS, is available both as a desktop app and a [CLI app](https://docs.ipfs.io/install/command-line/), in this post we will cover the CLI app as it is often easier to understand how things are working internally.
You can quickly follow the official [quick start guide](https://docs.ipfs.io/how-to/command-line-quick-start/#initialize-the-repository) to have an up and running node.-->
IPFS is available as a pre-compiled binary. But to connect it with Garage, we need a plugin named [ipfs/go-ds-s3](https://github.com/ipfs/go-ds-s3).
The Peergos project has a fork because it seems that the plugin is notorious for hitting Amazon's rate limits [#105](https://github.com/ipfs/go-ds-s3/issues/105), [#205](https://github.com/ipfs/go-ds-s3/pull/205).
This is the one we will try in the following.
The easiest solution to use this plugin in IPFS is to bundle it in the main IPFS daemon, and thus recompile IPFS from source.
Following the instructions on the README file allowed me to spawn an IPFS daemon configured with S3 as the block store.
Just be careful when adding the plugin to the `plugin/loader/preload_list` file, the given command lacks a newline.
You must edit the file manually after running it, you will directly see the problem and be able to fix it.
After that, I just ran the daemon and accessed the web interface to upload a photo of my dog:
![A dog](./dog.jpg)
The photo is assigned a content identifier (CID):
```
QmNt7NSzyGkJ5K9QzyceDXd18PbLKrMAE93XuSC2487EFn
```
And it now accessible on the whole network.
You can inspect it [from the official gateway](https://explore.ipld.io/#/explore/QmNt7NSzyGkJ5K9QzyceDXd18PbLKrMAE93XuSC2487EFn) for example:
![A screenshot of the IPFS explorer](./explorer.png)
At the same time, I was monitoring Garage (through [the OpenTelemetry stack we have implemented earlier this year](/blog/2022-v0-7-released/)).
Just after launching the daemon and before doing anything, we have this surprisingly active Grafana plot:
![Grafana API request rate when IPFS is idle](./idle.png)
These requests are triggered by the DHT service of IPFS: my node being reachable over the Internet, it acts as a public DHT server and start answering global
block requests over the whole network. Each time it sees a block request, it sends a request to our backend to see if it exists.
*We will try to tweak the IPFS configuration later - we know that we can deactivate the DHT server. For now, we will continue with the default parameters.*
When I start interacting with IPFS by sending a file or browsing the default proposed catalogs (ie. the full XKCD archive), values become so high that our default OpenTelemetry configuration can not cope with them.
It is useless to change Garage parameters to see what is exactly the number of requests done on the cluster: it is way too high considering my targeted usage: sharing a picture.
As a comparison, this whole webpage, with its pictures, triggers around 10 requests on Garage to load, not thousands.
One important point of this integration is that your browser is able to bypass both the Peergos daemon and the IPFS daemon
to write and read IPFS blocks directly on the backemd.
<!--So let's see if we are able to connect Peergos on Garage and have some federation across the Internet through IPFS.-->
*I don't know exactly if Peergos is still considered in alpha or switched to beta, but keep in mind that it might be more experimental that you would like!*
<!--To give ourselves some courage in this adventure, let's start with a nice screenshot of their web UI:
![Peergos Web UI](./peergos.jpg)-->
Starting Peergos on top of Garage required some small patches on both sides,
but in the end, we were able to get it working.
I was able to upload my file, see it in the interface, create a link to share it,
rename it, move it in a folder, and so on:
![A screenshot of the Peergos interface](./upload.png)
At the same time, the fans of my computer started to become a bit loud.
A quick look at Grafana shows that Garage is still very busy.
![Screenshot of a grafana plot showing requests per second over time](./grafa.png)
*Legend: y axis = requests per 10 seconds on log(10) scale, x axis = time*
Again, the workload is dominated by the `HeadObject` requests.
After getting a look at `~/.peergos/.ipfs/config`, it seems the IPFS configuration used by the Peergos project is pretty standard.
And thus, again, we are acting as a DHT server, answering each second to thousands of block requests.
We also some traffic on the `GetObject` endpoints (peaks of ~45 req/sec) and the `OPTIONS` HTTP verb.
This is the traffic generated by Peergos. The `OPTIONS` HTTP verb is here because we use the direct access feature of Peergos: our browser is sending CORS requests to Garage.
Internally, IPFS splits files in blocks of less than 256 kB, my picture is thus split in 2 blocks, requiring 2 requests over Garage to fetch it.
But even by knowing that IPFS split files in small blocks, I can't explain why we have so much `GetObject` requests.
## Try #3: Optimizing IPFS
<!--
Routing = dhtclient
![](./grafa2.png)
-->
We have seen in our 2 precedent tries that the main source of load was the
federation, and more especially, the DHT server. In this section, we want
to artificially remove this problem of the equation by preventing our IPFS node from federating
and see what pressure is put by Peergos alone on our local cluster.
To isolate IPFS, we have set its routing type to `none`, we have cleared its bootstrap node list,
and we configured the swarm socket to listen only on localhost.
Finally, we restart Peergos and observe this more peaceful graph:
![Screenshot of a grafana plot showing requests per second over time](./grafa3.png)
*Legend: y axis = requests per 10 seconds on log(10) scale, x axis = time*
Now, for a given endpoint, we have peaks of around 10 req/sec which is way more reasonable.
Furthermore, we are not hammering anymore our backend with requests on objects that are not here.
As part of our test journey, we also read some posts about performance issues on IPFS (eg. [#6283](https://github.com/ipfs/go-ipfs/issues/6283)) that are not