Open-source project
PurpleI2P/i2pd avatar
PurpleI2P/i2pd

The build switches i2pd keeps in its root Makefile

I2P: End-to-End encrypted and anonymous Internet. I2P allows people from all around the world to communicate and share information without restrictions.

4,263 stars523 forksC++BSD-3-Clause

At a glance

What is it?
The daemon is one output out of nine, a bare make keeps debug symbols, and on macOS the Homebrew path only opens for the literal value 1. Meanwhile the README hands out documentation links instead of a single command.
Who is it for?
Read the build system rather than the anonymity paragraph when judging this project. Everything a first time builder needs is visible in the tree: seven platform makefiles, a filelist.mk that holds the actual source list, DEBUG defaulting to yes, UPnP defaulting to no, and a macOS branch that only reaches Makefile.homebrew for the exact value 1.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 12, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • PurpleI2P/i2pd4,263 ★ · +111
Star history
Repository2026-07-282026-11-12
PurpleI2P/i2pd4.2k4.3k

111 Stars in the last 107 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

One root Makefile, seven platform includes

The root Makefile does little on its own. It sets .DEFAULT_GOAL to all, asks the compiler what it is with SYS := $(shell $(CXX) -dumpmachine), then branches on that answer twice: once to pick the shared library suffix, and once more to include exactly one platform makefile out of the seven sitting beside it, Makefile.bsd, Makefile.haiku, Makefile.homebrew, Makefile.linux, Makefile.mingw, Makefile.osx and Makefile.solaris.

make
ifneq (, $(findstring darwin, $(SYS)))
	SHARED_SUFFIX = dylib
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
	SHARED_SUFFIX = dll
else
	SHARED_SUFFIX = so
endif

The suffix test is string matching rather than platform detection. Any target whose dumpmachine output contains gnu also lands in the Linux branch, which is how the same string reaches Makefile.linux. Windows is the only branch that touches the source list, adding four files from the Win32 directory to the daemon sources before it includes Makefile.mingw. A further branch opens for FreeBSD and OpenBSD targets.

DEBUG defaults to yes, so a bare make keeps the symbol table

Four switches carry defaults, and each is declared so that an unset variable falls through to the second argument:

make
USE_STATIC      := $(or $(USE_STATIC),no)
USE_UPNP        := $(or $(USE_UPNP),no)
DEBUG           := $(or $(DEBUG),yes)
TORRENTS        := $(or $(TORRENTS),yes)

DEBUG is the one that catches people out, because its default is yes. With DEBUG=yes the compiler flag is -g and the linker keeps every symbol; with DEBUG=no the compiler flag becomes -Os and the linker adds -s to strip. A bare make on a fresh clone therefore produces an unstripped binary with a full symbol table, which is what you want while reading the code and not what you want in a package. UPnP defaults to no, so router port mapping stays off unless it is asked for. TORRENTS defaults to yes. USE_STATIC also defaults to no, and the root Makefile does not say what that one turns on.

A fifth switch exists only for the version string. USE_GIT_VERSION defaults to no, and the comment above it ties it to debugging: it is for trunk builds that need the commit hash inside the i2pd version string.

On macOS, HOMEBREW has to be exactly 1

The darwin branch asks a second question before it includes anything, and the comparison is exact rather than a truth test:

make
ifneq (, $(findstring darwin, $(SYS)))
	ifeq ($(HOMEBREW),1)
		include Makefile.homebrew
	else
		include Makefile.osx
	endif

HOMEBREW defaults to 0, and the comment above the assignment says the value is expected to be "1", not "yes". Ask for the Homebrew build with yes on a Mac and you take the else branch, building through Makefile.osx with nothing printed to warn you; only the literal 1 reaches Makefile.homebrew. Those two files are separate, and what prefixes and link flags each one sets is not visible from the root file.

The habit worth taking from this file is small: pass the exact token that the comparison spells out, and check which platform makefile your run actually included.

filelist.mk lists the sources, not the Makefile you read

The root Makefile names five source directories and then defers to a separate file for the actual enumeration:

make
# import source files lists
include filelist.mk

The directories it does declare are libi2pd for the core library, libi2pd_client for the client library, libi2pd_wrapper for the wrapper, i18n for translations and daemon for the daemon. Everything else that gets compiled is enumerated in filelist.mk, which means the file a reader opens first says nothing about how many translation units are involved. The tree puts tests, build, contrib, docs, debian and Win32 beside those five directories.

One exception is worth knowing when a file you expected to find is missing from the list: the Windows branch appends to DAEMON_SRC after that include, so Win32/DaemonWin32.cpp, Win32App.cpp, Win32Service.cpp and Win32NetState.cpp are added by the root Makefile itself rather than by filelist.mk.

Eight library files come out of the same invocation

This is not a single daemon build. Four libraries are defined, each in a shared and a static flavour, plus the binary itself:

make
SHLIB := libi2pd.$(SHARED_SUFFIX)
ARLIB := libi2pd.a
SHLIB_LANG := libi2pdlang.$(SHARED_SUFFIX)
ARLIB_LANG := libi2pdlang.a
SHLIB_CLIENT := libi2pdclient.$(SHARED_SUFFIX)
ARLIB_CLIENT := libi2pdclient.a
SHLIB_WRAP := libi2pdwrapper.$(SHARED_SUFFIX)
ARLIB_WRAP := libi2pdwrapper.a
I2PD := i2pd

Only the shared names vary by platform, so the same variable turns into libi2pd.dylib on macOS, libi2pd.so on Linux and libi2pd.dll on Windows, while the static names stay fixed everywhere. That set is worth holding next to the feature list, which advertises a small footprint and simple dependencies while the build also ships an embedding surface for other applications.

The graphical side lives in other repositories. i2pd sends Android users to i2pd-android, Qt users to i2pd-qt, and macOS users to a gui-i2pd repository under the MetanoicArmor account, so none of those front ends is part of this tree.

The install section is documentation links and no command

Nothing in the README can be pasted into a shell. The Installing section says the easiest route is precompiled packages and binaries, points at the releases page for most of them, and hands everything else to a documentation site. Building is delegated the same way, with separate pages for unix, windows, iOS and android. The supported systems list names ten targets and, for most of them, links a build workflow: GNU/Linux with Debian and Ubuntu named, CentOS/Fedora/Mageia through a COPR package, Alpine/ArchLinux/openSUSE/Gentoo, Windows, Mac OS, a Docker image, Snap, FreeBSD, Android and iOS.

Two facts a first time builder has to find somewhere else. The default branch is openssl, so a plain clone is the OpenSSL variant. And configuration is not in the README either: the run documentation and an example config file are linked from the Using i2pd section, with the example living at contrib/i2pd.conf in the repository. Installing the Docker image or the Snap also means taking a packaging and a configuration that this tree does not describe.

Anonymity is asserted in four sentences and specified nowhere

The security model here is stated rather than shown. The README says all communications over I2P are anonymous and end-to-end encrypted, that participants do not reveal their real IP addresses, and that I2P is a universal anonymous network layer used for anonymous peer-to-peer applications such as filesharing and cryptocurrencies and for anonymous client-server applications such as websites, instant messengers and chat servers. i2pd itself is called a full-featured C++ implementation of an I2P client.

What sits next to those claims is what is absent. There is no threat model, nothing about what a single malicious peer inside the network can observe, no key management section, no reference to an audit, and no upgrade or rollback procedure. Specifications are handed to a separate site, and the wiki and the issue tracker carry the rest. So the anonymity statements in this repository are self description, and the code implementing them is here while the argument about them is not.

One dated fact does anchor the release side: the newest tag is 3.0.0 from 2026-10-20, and the openssl default branch was pushed on 2026-11-01, so the branch has moved past the last tag.

Translations run on Crowdin, and generated contributions are refused

Two policy lines are worth knowing before opening a pull request. Translation is handled on Crowdin rather than in the repository, and new languages are requested on that platform's discussion page for the project. Then there is a section stating that no LLM or AI generated code is accepted for pull requests and no LLM or AI generated text is accepted for issues. That is a rule about what may be contributed. It is not a statement about how code is reviewed, and nothing in the tree connects it to an audit.

The donations block is the only place in the README where literal values appear: an email address and eight chain addresses, for BTC, LTC, ETH, GST, DASH, ZEC, ANC and XMR, each written with the chain name in front of the value.

Editorial conclusion

Read the build system rather than the anonymity paragraph when judging this project. Everything a first time builder needs is visible in the tree: seven platform makefiles, a filelist.mk that holds the actual source list, DEBUG defaulting to yes, UPnP defaulting to no, and a macOS branch that only reaches Makefile.homebrew for the exact value 1. The anonymity claims are not checkable from this repository, because it publishes no threat model and no audit. Before building, decide whether the openssl default branch is what you want, pass DEBUG=no for anything you intend to distribute, and work out whether the client and wrapper libraries are needed at all. If the anonymity property matters more to you than the daemon itself, the specifications and the wiki linked from the README are where that argument lives.

Frequently asked questions

Is i2pd a darknet, or just one client for I2P?

i2pd describes itself as a full-featured C++ implementation of an I2P client, the I2P Daemon, released under the BSD 3-clause license with LICENSE in the repository root. The README calls I2P a universal anonymous network layer and does not use the word darknet.

Can i2pd traffic be tracked?

The README states that all communications over I2P are anonymous and end-to-end encrypted and that participants do not reveal their real IP addresses. It publishes no threat model and names no audit, so the repository offers nothing to check that claim against.

Is i2pd free software?

Under BSD 3-clause, with the LICENSE file in the root of the source tree. Money is collected by email address and in eight cryptocurrencies rather than by licence, and the newest tag is 3.0.0 from 2026-10-20.

Where do the i2pd Android and GUI builds live?

In three separate repositories: i2pd-android for Android, i2pd-qt for a Qt interface, and gui-i2pd under the MetanoicArmor account for macOS. The i2pd tree itself carries a debian directory and links a Docker image and a Snap package.

How do I build i2pd on macOS?

The default branch is openssl. On a darwin target the root Makefile includes Makefile.osx unless HOMEBREW is set to exactly 1, in which case it includes Makefile.homebrew, and DEBUG defaults to yes so the binary keeps its symbol table unless you pass DEBUG=no.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/purplei2p-i2pd.svg)](https://hysenlabs.com/projects/purplei2p-i2pd)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/purplei2p-i2pd.svg)](https://hysenlabs.com/projects/purplei2p-i2pd)

Was this useful?