Overview

I was reading the IEEE magazine this month and noticed an interesting article on IPFS.

IPFS is a peer-to-peer protocol that centers around a key concept called content addressing, this allows a client to ask the network for a content item.

The idea behind this is that if possible a node closest to you can serve you the data if it has it.
The main benefits of this would be faster delivery of content and less overall network congestion. This would especially assist countries that do not have a lot of international bandwidth available to them.

This is different from HTTP where your client sends a request to a set server for a set resource. This request may travel over multiple international links before it gets to its destination, then it has to return back to you.

Each item pushed to IPFS has a unique CID (Content ID), this is a permanent locator for this resource at the point in time that it was published to the IPFS network.
This also means when content is modified it gets a new CID, thus preserving the history of that resource.

The main downside to this approach is that if you need to update something, let's say a blog or a git repository, you would need to give out the new CID to others to find the update.
This is where IPNS comes into play, these are signed public keys that point to a CID resource. Meaning users can access the content you publish via the same IPNS name.

Installing on Debian 10

Debian has a guide for setting up IPFS that I used for inspiration as I do not feel the way the guide is written takes security into consideration.

Firstly I don't fancy things running as root, and IPFS has no need to run as root either. Thus follow along to see how I install IPFS on Debian.

IPFS install

As root download the latest binary of kubo, unpack and install the binary:

tar -xvf kubo_v0.17.0_linux-amd64.tar.gz 
cd kubo/
chmod + install.sh 
./install.sh 

This will install ipfs into /usr/local/bin/, next check that the ipfs binary works by issuing ipfs --version this should list the version of ipfs you just downloaded.

IPFS user

Next up we want to create a user account for IPFS to run under, trying to adhere to the least privilege as possible. Create the ipfs user via:

adduser --system --home=/home/ipfs  --gecos="ipfs daemon" --shell=/bin/bash --group ipfs

Let's break this down for a moment.

--system makes the adduser tool select a UID and GID in the system range rather the general user range.
However, we need to run commands as the ipfs user and --system by default disables the user's shell, thus we pass --shell=/bin/bash to give the user an interactive shell.
The rest should be mostly obvious what it achieves.

IPFS configuration

Next, we need to setup IPFS for a server profile.
Become the ipfs user via su - ipfs and run the following command:
ipfs init --profile server.
This produces an output similar to this:

generating ED25519 keypair...done
peer identity: 12D3KooWDvWWc2kqq1G9rUXGXWAscTFPiy9sMHoXeCwY4xYNP17p
initializing IPFS node at /home/ipfs/.ipfs
to get started, enter:

	ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme 

This command should generate your keypair and peer identity. The peer identity is your node's unique ID, we can retrieve this information later on as well.

I also needed to increase the resource limits for inbound connections as I originaly received this error after startup:

Consider inspecting logs and raising the resource manager limits. Documentation: https://github.com/ipfs/kubo/blob/master/docs/config.md#swar
ERROR resourcemanager libp2p/rcmgr_logging.go:53 Resource limits were exceeded 36 times with error "system: cannot reserve inbound connection: resource limit exceeded"

To resolve this issue I edit the file .ipfs/config as the ipfs user.
I added the following:

"ResourceMgr": {
  "Limits": {
    "System": {
      "ConnsInbound": 1024,
      "ConnsOutbound": 1024
    }
}
},

By default the ResourceMgr JSON array is empty.

systemd unit file

I want the IPFS daemon to start and stop automatically with the system. Thus we need a systemd unit file.
This is mostly borrowed from the Debian page above, but edited to run as the ipfs user and added the --enable-namesys-pubsub daemon option, this enables faster IPFS resolution mechanisms.

Copy the following into /etc/systemd/system/ipfs.service

[Unit]

Description=IPFS Daemon
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ipfs daemon --enable-namesys-pubsub
User=ipfs

[Install]
WantedBy=multi-user.target

Then run systemctl daemon-reload then systemctl enable --now ipfs.
Check that its running via systemctl status -l ipfs.

● ipfs.service - IPFS Daemon
   Loaded: loaded (/etc/systemd/system/ipfs.service; disabled; vendor preset: enabled)
   Active: active (running) since Mon 2022-11-28 14:45:25 ACDT; 5min ago
 Main PID: 13400 (ipfs)
    Tasks: 14 (limit: 4915)
   Memory: 247.2M
   CGroup: /system.slice/ipfs.service
           └─13400 /usr/local/bin/ipfs daemon --enable-namesys-pubsub

Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip4/XXX.XXX.XXX.XXX/tcp/4001
Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip4/XXX.XXX.XXX.XX/udp/4001/quic
Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip6/abcd:abcd:abcd:abcd:1::7/tcp/4001
Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip6/abcd:abcd:abcd:abcd:1::7/udp/4001/quic
Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip6/::1/tcp/4001
Nov 28 14:45:25 diode ipfs[13400]: Swarm announcing /ip6/::1/udp/4001/quic
Nov 28 14:45:25 diode ipfs[13400]: API server listening on /ip4/127.0.0.1/tcp/5001
Nov 28 14:45:25 diode ipfs[13400]: WebUI: http://127.0.0.1:5001/webui
Nov 28 14:45:25 diode ipfs[13400]: Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Nov 28 14:45:25 diode ipfs[13400]: Daemon is ready

Testing the client

As the ipfs user, issue the command:
ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme.
If all goes well you should see something similar to this:

Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| Warning:                                              |
|   This is alpha software. Use at your own discretion! |
|   Much is missing or lacking polish. There are bugs.  |
|   Not yet secure. Read the security notes for more.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes

QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc is the CID for the quick start guide and readme for IPFS, published on the IPFS network.
You can view its contents in your browser via this link as it is passed through via a gateway.

Next up!

I plan to write some follow-up articles on IPNS and how to publish content into IPFS, but for now, your node should be up, connected to IPFS, and participating as an active node in the network.

Refreces