---
title: "I2p on NixOS"
date: 2023-07-27T00:21:37+02:00
draft: true
author: "$HUMANOID"
tags: ["nix", "linux", "i2p"]
description: "My i2p configuration on NixOS"
draft: false
toc: true
---

# Introduction

Recently I've decided to move most of my hardware over to NixOS. It's been an
amazing experience being able to configure everything OS related from one
central point.

A few years ago, I discovered [i2p](https://geti2p.net/en/). I really liked the
idea of it; a different darknet than tor with different kinds of people on it --
more blog oriented. At the time I ran a node on a Raspberry Pi running Debian. I
connected to it using an ssh tunnel over
[Yggdrasil](https://yggdrasil-network.github.io/) and used an
[Arkenfox](https://github.com/arkenfox/user.js) hardened Firefox profile to
browse around.

That Raspberry Pi no longer serves as a (har) server. Instead I now have a NixOS
machine churning away. As with a lot of NixOS topics, there isn't a lot
of documentation on configuring i2p. Though truth be told, when comparing it to
the config files I had on Debian, a lot of it was rather self explanatory and
easy to implement in a Nix module.

What follows is my current setup on my desktop. Initially I set this up as a
test environment, but it works well to the point where I don't really feel the
need to move it to another machine.

# The i2p module

I'll be using the `i2pd` implementation of the i2p daemon as it requires less
resources than the java implementation and has less features out of the box that
need configuring.

Since it is safe to assume that the i2p stack is frequently under attack as it
is a darknet protocol, I decided to run it inside of a Nix container. If you
don't want to do this, only declare a `services.i2pd` instance.

With that out of the way, let's declare a basic container environment named
`i2pd-container`.

```nix
{ ... }: {
  containers.i2pd-container = {
    autoStart = true;
    config = { ... }: {

      system.stateVersion = "23.05"; # If you don't add a state version, nix will complain at every rebuild

    };
  }
}
```

From here there are a couple of things you can do with your i2p configuration.
My initial goal was to be able to search the i2p net. To that end, the following
will suffice.
```nix
...
      # Exposing the nessecary ports in order to interact with i2p from outside the container
      networking.firewall.allowedTCPPorts = [
        7070 # default web interface port
        4447 # default socks proxy port
        4444 # default http proxy port
      ];

      services.i2pd = {
        enable = true;
        address = "127.0.0.1"; # you may want to set this to 0.0.0.0 if you are planning to use an ssh tunnel
        proto = {
          http.enable = true;
          socksProxy.enable = true;
          httpProxy.enable = true;
        };
      };
...
```
The SOCKS proxy isn't strictly required, but needed when wanting to use anything
else than an HTTP connection to interact with i2p.

## Torrents

After a little while, I wanted to see what kinds of _linux distros_ the i2p
network has to offer, I also enabled `services.i2pd.proto.sam` and added the
corresponding default port to the container's firewall in order to get
[XD](https://xd-torrent.github.io/) (which can be found in the Nix repo) to
behave properly:

```nix
...
      networking.firewall.allowedTCPPorts = [ 7656 ];
      services.i2pd.proto.sam.enable = true;
...
```
{{< start-details summary="Click here to see everything together" >}}
```nix
{ ... }: {
  containers.i2pd-container = {
    autoStart = true;
    config = { ... }: {

      system.stateVersion = "23.05"; # If you don't add a state version, nix will complain at every rebuild

      # Exposing the nessecary ports in order to interact with i2p from outside the container
      networking.firewall.allowedTCPPorts = [
        7656 # default sam port
        7070 # default web interface port
        4447 # default socks proxy port
        4444 # default http proxy port
      ];

      services.i2pd = {
        enable = true;
        address = "127.0.0.1"; # you may want to set this to 0.0.0.0 if you are planning to use an ssh tunnel
        proto = {
          http.enable = true;
          socksProxy.enable = true;
          httpProxy.enable = true;
          sam.enable = true;
        };
      };
    };
  }
}
```
{{< end-details >}}

# Tying it to `/etc/nixos/configuration.nix`

I have a perhaps somewhat over engineered structure when it comes to adding my
modules to `/etc/nixos/configuration.nix`.

I have a `/etc/nixos/services` directory with my own modules, one of which being
`services.nix`. `services.nix` imports all the other modules found in the
directory. From there, `/etc/nixos/configuration.nix` has
`./services/services.nix` in it's import section:

`/etc/nixos/configuration.nix`:
```nix
{ pkgs, config, ... }: {
  imports = [
    ./hardware-configuration.nix
    ./services/services.nix
    ...
  ];
  ...
}
```
`/etc/nixos/services/services.nix`:
```nix
{ ... }: {
  imports = [
    ./i2pd-container.nix
    ...
  ];
}
```

# Browser profile

The next step was to set up a browser profile. Since Mullvad recently released a
browser, I decided to use it as a basis for my i2p browser.

To create a new profile in Firefox or any of it's forks, type/paste
`about:profiles` in the URL bar and click the "Create a New Profile" button at
the top. You will then be prompted for a name. I named mine "i2p".

Open this profile in a new session and navigate to `about:preferencess#general`
and scroll all the way down to "Network Settings". In there, check "Manual proxy
configuration" and "Also use this proxy for HTTPS". From there, fill in the
address you used in `services.i2pd.address` or the address of the machine you're
tying it to if you're using an ssh tunnel. For ports, use `4444` for the HTTP
proxy and `4447` for the SOCKS proxy. 

Then move over to `about:preferencess#privacy` and scroll down to "Security". I
recommend putting it to "Safest". If you _really need_ to run any JavaScript,
you can always add the NoScript icon to your window bar.

Then scroll a bit further down to "HTTPS-Only Mode" and disable it, as the i2p
network doesn't use browser level encryption and thus it would only get in the
way.

As a final step, go to `about:config` and set `keyword.enabled` to false. This
isn't strictly necessary, but will make your like a whole lot easier when typing
`.i2p` domains and not having your browser attempt -- and fail -- to query the
default search engine.

## `.desktop` entry via `home-manager`

If you're using the `home-manager`, you can quite easily create a `.desktop`
file to make starting your i2p profile more convenient. This is assuming that
have either a full on desktop environment or use some other way of parsing
`.desktop` entries such as `rofi`'s `drun` mode.

I have the following in my `$HOME/.config/home-manager/home.nix`:
```nix
xdg.desktopEntries = {
  i2p-browser = {
    name = "i2p Browser";
    genericName = "Web Browser";
    exec = "${pkgs.mullvad-browser}/bin/mullvad-browser -p i2p";
  };
};
```

Firefox and it's forks allow you to start a session with a profile using the
`-p` parameter. Similarly the `-P` (that is, an upper case 'P' rather than lower
case) parameter brings up a profiles menu that allows you to easily change the
default profile when running the binary the next time.

# Using everything

After starting the container, wait at least 15 minutes for i2pd to build a few
tunnels before attempting to connect to anything. Once you have, open your
i2p browser profile and you should be able to browse the i2p net. Don't expect
things to be fast however, i2p is a much slower network in my experience than
Tor.

Some pages to get you started:

- [reg.i2p](http://reg.i2p) - link index
- [stats.i2p](http://stats.i2p/) - link index
- [notbob.i2p](http://notbob.i2p/) - link index
- [My site](http://lmwr2pugnmv4pkkxlneeepi4oysfly33zfuj7x25s6hfydysnpfq.b32.i2p/)

