--- 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/)