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. 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 and used an Arkenfox 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
.
{ ... }: {
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.
...
# 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 (which can be found in the Nix repo) to
behave properly:
...
networking.firewall.allowedTCPPorts = [ 7656 ];
services.i2pd.proto.sam.enable = true;
...
Click here to see everything together
{ ... }: {
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;
};
};
};
}
}
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
:
{ pkgs, config, ... }: {
imports = [
./hardware-configuration.nix
./services/services.nix
...
];
...
}
/etc/nixos/services/services.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
:
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 - link index
- stats.i2p - link index
- notbob.i2p - link index
- My site