This page is about bundling the entire I2P router binary with your application. It is not about writing an application to work with I2P (either bundled or external).
Lots of projects are bundling, or talking about bundling, I2P. That's great if done right. If done wrong, it could cause real harm to our network. The I2P router is complex, and it can be a challenge to hide all the complexity from your users. This page discusses some general guidelines.
Start a dialog. We're here to help. Applications that embed I2P are the most promising - and exciting - opportunities for us to grow the network and improve anonymity for everyone.
Choose your router wisely
If your application is in Java or Scala, it's an easy choice - use the Java router. If in C/C++, we recommend i2pd. The development of i2pcpp has stopped. For apps in other languages, best to use SAM or BOB or SOCKS and bundle the Java router as a separate process. Some of the following only applies to the Java router.
Ensure you meet the license requirements of the software you are bundling.
Verify default configuration
A correct default configuration is crucial. Most users will not change the defaults. The defaults for your application may need to be different than the defaults for the router you are bundling. Override the router defaults if necessary.
Some important defaults to review: Max bandwidth, tunnel quantity and length, max participating tunnels. A lot of this depends on the expected bandwidth and usage patterns of your app.
Configure enough bandwidth and tunnels to allow your users to contribute to the network. Consider disabling external I2CP, as you probably don't need it and it would conflict with any other running I2P instance. Also look at the configs for disabling killing of the JVM on exit, for example.
Participating Traffic Considerations
It may be tempting for you to disable participating traffic. There's several ways to do this (hidden mode, setting max tunnels to 0, setting shared bandwidth below 12 KBytes/sec). Without participating traffic, you don't have to worry about graceful shutdown, your users don't see bandwidth usage not generated by them, etc. However, there's lots of reasons why you should allow participating tunnels.
First of all, the router doesn't work that well if it doesn't have a chance to "integrate" with the network, which is helped tremendously by others building tunnels through you.
Secondly, over 90% of the routers in the current network allow participating traffic. It's the default in the Java router. If your application doesn't route for others and it gets really popular, then it's a leech on the network, and it upsets the balance we have now. If it gets really big, then we become Tor, and spend our time begging for people to enable relaying.
Thirdly, participating traffic is cover traffic that helps your users' anonymity.
We strongly discourage you from disabling participating traffic by default. If you do this and your application gets hugely popular, it could break the network.
You must save the router's data (netdb, configuration, etc.) between runs of the router. I2P does not work well if you must reseed each startup, and that's a huge load on our reseed servers, and not very good for anonymity either. Even if you bundle router infos, I2P needs saved profile data for best performance.
Give your users a way to change the configuration of the important settings. We understand that you will probably want to hide most of I2P's complexity, but it's important to show some basic settings. In addition to the defaults above, some network settings such as UPnP, IP/port may be helpful.
Above a certain bandwidth setting, and meeting other health criteria, your router will become floodfill, which may cause a large increase in connections and memory usage (at least with the Java router). Think about whether that's OK. You can disable floodfill, but then your fastest users aren't contributing what they could. It also depends on the typical uptime for your application.
Decide if you are bundling router infos or using our reseed hosts. The Java reseed host list is in the source code, so if you keep your source up to date, the host list will be also. Be aware of possible blocking by hostile governments.
Consider setting your application tunnels to delay-open, reduce-on-idle and/or close-on-idle. This is straightforward if using i2ptunnel but you'll have to implement some of it yourself if using I2CP directly. See i2psnark for code that reduces tunnel count and then closes the tunnel, even in the presence of some background DHT activity.
Have an auto-update feature if at all possible, or at least auto-notification of a new version. Our biggest fear is a huge number of routers out there that can't be updated. We have about 6-8 releases a year of the Java router, and it's critical to the health of the network that the users keep up. We usually have over 80% of the network on the latest release within 6 weeks after the release, and we'd like to keep it that way. You don't need to worry about disabling the router's built-in auto-update function, as that code is in the router console, which you presumably are not bundling.
Have a gradual rollout plan. Don't overwhelm the network all at once. We currently have approximately 25K unique users per day and 40K uniques per month. We are probably able to handle growth of 2-3X per year without too much issue. If you anticipate a faster rampup than that, OR the bandwidth distribution (or uptime distribution, or any other significant characteristic) of your userbase is significantly different from our current userbase, we really need to have a discussion. The bigger your growth plans, the more important everthing else in this checklist is.
Design for and Encourage Long Uptimes
Tell your users that I2P works best if it keeps running. It may be several minutes after startup before it works well, and even more after first install. If your average uptime is less than an hour, I2P is probably the wrong solution.
Provide some indication to the user that the application tunnels are ready. Encourage patience.
If possible, delay the shutdown until your participating tunnels expire. Don't let your users break tunnels easily, or at least ask them to confirm.
It would be nice if you give your users links to learn more about I2P and to donate.
External Router Option
Depending on your user base and application, it may be helpful to provide an option or a separate package to use an external router.
Use of other Common Services
If you plan to use or link to other common I2P services (news feeds, hosts.txt subscriptions, trackers, outproxies, etc.), make sure you aren't overloading them, and talk to the people who are running them to make sure it's ok.
Time / NTP Issues
I2P includes an SNTP client. I2P requires correct time to operate. It will compensate for a skewed system clock but this may delay startup. You may disable I2P's SNTP queries, but this isn't advised unless your application makes sure the system clock is correct.
Choose What and How you Bundle
At a minimum you will need i2p.jar, router.jar, streaming.jar, and mstreaming.jar. You may omit the two streaming jars for a datagram-only app. Some apps may need more, e.g. i2ptunnel.jar or addressbook.jar. Don't forget jbigi.jar, or a subset of it for the platforms you support, to make the crypto much faster. Java 7 or higher is required to build. If you're building Debian / Ubuntu packages, you should require the I2P package from our PPA instead of bundling it. You almost certainly do not need susimail, susidns, the router console, and i2psnark, for example.
The following files should be included in the I2P installation directory, specified with the "i2p.dir.base" property. Don't forget the certificates/ directory, which is required for reseeding, and blocklist.txt for IP validation. The geoip directory is optional, but recommended so the router can make decisions based on location. If including geoip, be sure to put the file GeoLite2-Country.mmdb in that directory (gunzip it from installer/resources/GeoLite2-Country.mmdb.gz). The hosts.txt file may be necessary, you may modify it to include any hosts your application uses. You may add a router.config file to the base directory to override initial defaults. Review and edit or remove the clients.config and i2ptunnel.config files.
License requirements may require you to include the LICENSES.txt file and the licenses directory.
- You may also wish to bundle a hosts.txt file.
- Be sure to specify a Java 7 bootclasspath if compiling with Java 8.
Our Android router app may be shared by multiple clients. If it is not installed, the user will be prompted when he starts a client app.
Some developers have expressed concern that this is a poor user experience, and they wish to embed the router in their app. We do have an Android router service library on our roadmap, which could make embedding easier. More information needed.
If you require assistance, please contact us.
We have a limited number of our jars on Maven Central. There are numerous trac tickets for us to address that will improve and expand the released jars on Maven Central.
If you require assistance, please contact us.
Datagram (DHT) considerations
If your application is using I2P datagrams, e.g. for a DHT, there's lots of advanced options available to reduce overhead and increase reliability. This may take some time and experimentation to get working well. Be aware of size/reliability tradeoffs. Talk to us for help. It is possible - and recommended - to use Datagrams and Streaming on the same Destination. Don't create separate Destinations for this. Don't try to store your unrelated data in the existing network DHTs (iMule, bote, bittorrent, and router). Build your own. If you are hardcoding seed nodes, we recommend that you have several.
Let's work together. Don't wait until it's done. Give us your Twitter handle and start tweeting about it, we will return the favor.
Please don't use I2P for evil. It could cause great harm both to our network and our reputation.
This may be obvious, but join the community. Run I2P 24/7. Start an eepsite about your project. Hang out in IRC #i2p-dev. Post on the forums. Spread the word. We can help get you users, testers, translators, or even coders.
You may wish to install and play with the I2P Android app, and look at its code, for an example of an application that bundles the router. See what we expose to the user and what we hide. Look at the state machine we use to start and stop the router. Other examples are: Vuze, the Nightweb Android app, iMule, TAILS, iCloak, and Monero.
None of the above actually tells you how to write your code to bundle the Java router, so following is a brief example.
import java.util.Properties; import net.i2p.router.Router; Properties p = new Properties(); // add your configuration settings, directories, etc. // where to find the I2P installation files p.addProperty("i2p.dir.base", baseDir); // where to find the I2P data files p.addProperty("i2p.dir.config", configDir); // bandwidth limits in K bytes per second p.addProperty("i2np.inboundKBytesPerSecond", "50"); p.addProperty("i2np.outboundKBytesPerSecond", "50"); p.addProperty("router.sharePercentage", "80"); p.addProperty("foo", "bar"); Router r = new Router(p); // don't call exit() when the router stops r.setKillVMOnEnd(false); r.runRouter(); ... r.shutdownGracefully(); // will shutdown in 11 minutes or less
This code is for the case where your application starts the router, as in our Android app. You could also have the router start the application via the clients.config and i2ptunnel.config files, together with Jetty webapps, as is done in our Java packages. As always, state management is the difficult part.
See also: the Router javadocs.