How to host a DokuWiki as an I2P Site, using Docker and Java I2P. Writing with a slightly different tone than my other guides, today I want to talk a little more about “why” and it’s going to give us a different take on “how.” This is not going to be my most “Professional” article ever, today we’re in this together and I’m making a case for my plan.
Docker isn’t just for systems administrators. If you let your computer run any programs while you’re not sitting there watching it, then Docker can probably offer you something worthwhile. Besides “containing” your applications within a stable, predictable, environment, which you can rebuild without interfering with the environment in a running container, Docker provides a general way of managing the lifecycle of your applications and dealing with crashes, sets up containers on a network Bridge where they do not share the localhost address of the host machine, and can manage data by attaching directories on the host to directories within the container. Learning some basic Docker usage will help you if it’s your job(or hobby, whatever) to host a bunch of hidden services. Besides that, if you’re the type to share your hidden service setup instructions with the community, it means that anyone on any OS can use them, as long as they can install Docker. Oh also there’s a freaking enormous community, every question you ever had has probably already been asked and answered on some(probably the wrong) StackExchange-adjacent site already.
So it pays to learn Docker. Or don’t, its your life. But I would.
Highlights of Docker include:
--restart=always
docker run
--volume
and
--mount
flags
-p
flag.
Docker is really just another application, on most levels. Once you’ve used
it a few times it ceases to be confusing, you’ll be passing pretty similar flags
to every single container you ever build or run, and only very rarely does it
ever get any more complex than the stuff you learn your first few weeks. It’s like
git
, it has lots of stuff to work with, but you end up using about the same six
options every time.
Dockerhub could be considered a sort of Man in the Middle. Most of the
containers are build automatically on Docker’s infrastructure, which means
that Dockerhub could in theory serve you up a bad image. This is pretty
unlikely, though, and not at all the biggest risk. The biggest risk is
that anybody can create a namespace and push an image to this infrastructure.
That namespace can’t be racist, and it can’t be occupied by another user
already, and I’m like, 85% sure it can’t contain your typical “lookalike”
characters(Cyrillic O’s and whatnot). Nothing stops anyone from registering
the namespace
mozzilla
though, or
mozil1a
or other legal characters that
resemble eachother.
The part of dockerhub which is undeniably useful, though, is the statistics
it generates on image usage, and its search capabilities. These are accessible
via the
docker search
command.
Here’s a
docker search
example:
docker search dokuwiki
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mprasil/dokuwiki Container running DokuWiki with nice URLs an… 97 [OK]
linuxserver/dokuwiki 59
istepanov/dokuwiki Docker image with dokuwiki and nginx. Suppor… 43 [OK]
vimagick/dokuwiki A wiki application licensed under GPL 2 and … 14 [OK]
bambucha/dokuwiki Alpine DokuWiki Docker Container 8 [OK]
crazymax/dokuwiki DokuWiki image based on Alpine Linux 7
plaguedr/dokuwiki DokuWiki is a wiki application licensed unde… 2
dtwardow/dokuwiki DokuWiki Docker Container 1 [OK]
To avoid the risk of using a compromised upstream container, research the
source of the docker image. Pay attention to the
FROM
line of the
Dockerfile
, and
make sure that it corresponds to an “Official” signed base image from
a distro like Ubuntu, Debian, or Alpine Linux, or that it is from
SCRATCH
.
If it does not, find the source of the parent image, and repeat this process
until the whole stack of images is analyzed. In practice, this is rarely more
than one image.
To avoid the risk of using an out-of-date upstream container, build your image locally, and all of the parent images as well, unless you are confident in the upstream image being consistently maintained.
Choosing software which is easy to maintain an instance of is setting yourself up for success. Many hidden services are run by one person, if one is lucky one has a backup or possibly a skeleton crew. Only a handful of well-organized, mostly non-anonymous organizations have really reliable teams of people to operate and maintain their sites and the hardware that runs them.
This isn’t wrong, and it doesn’t have to be dangerous. It’s also true that many hidden services are operated by hobbyists, researchers, and enthusiasts who simply want to host their services in a way which transparently evades NAT difficulties. Many of them have small audiences and even smaller numbers of contributors. It’s not really my business to know why they want to use the I2P network, my business it to show them why it’s a good option(Which it is). As long as the software you are hosting is something you can keep up-to-date without breaking your back or losing your job, then it’s perfectly reasonable for just one person to manage and host a hidden service, even on a residential connection.
This is the chief advantage of DokuWiki, especially combined with
Docker. There are no databases to set up, you can pre-configure the
administrative user and password, it honors the
http_proxy
environment
variable. There has never been a situation in which I had to lost
data stored in a DokuWiki to an update.
Let’s return to the
docker search
output from earlier for a moment,
because that’s where we’re going to start.
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mprasil/dokuwiki Container running DokuWiki with nice URLs an… 97 [OK]
linuxserver/dokuwiki 59
istepanov/dokuwiki Docker image with dokuwiki and nginx. Suppor… 43 [OK]
vimagick/dokuwiki A wiki application licensed under GPL 2 and … 14 [OK]
bambucha/dokuwiki Alpine DokuWiki Docker Container 8 [OK]
So what is this telling us, and what conclusions should we be drawing from it?
[Name]
This is just the name of the image, in the form
[namespace]/[name]
.
Often, this will be identical to the github or bitbucket namespace where the
image source is available. The namespace tends to reveal if the image is
maintained by an organization or by an individual. Obviously there are
advantages to choosing an image maintained by an organization.
[Description]
The description of the image contains information additional
to the name. It’s usually not the most interesting part of the
docker search
output.
[Stars]
As a rule, if only one person is using an image, it’s probably
not up to date. Prioritize images with more users for research, stars will
be positively correlated to users, and users will be positively correlated
to eyes on the image, so prioritize images with the most stars.
[Official]
Docker only has a handful of “official” images which are provided
by upstream distributions and software packages. Ubuntu, for instance, has an
official image:
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 12481 [OK]
[Automated]
This means that the image was built on Docker’s automated build
system, and not built on the developer’s machine and pushed up to Dockerhub.
So, what images will we evaluate? The two that look the most promising are
mprasil/dokuwiki
, and
linuxserver/dokuwiki
.
mprasil/dokuwiki
has a
docker hub page here
. At the top
it says “Updated a year ago” which is maybe not the best sign ever. On the other
hand,
linuxserver/dokuwiki
was
updated less than a week ago. That’s the one we need.
Before we continue, let’s look at the
Dockerfile
s that describe the containers
which we will be running. First, the docker-dokuwiki
Dockerfile
:
Uh-oh, looks like it’s
not
from an official image or a
SCRATCH
image as we
recommended earlier. Instead, it modifies another image, the name suggests
that it combines
Alpine Linux
with an
nginx
web server. Let’s look one level
deeper at the parent
Dockerfile
.
Examining this
Dockerfile
confirms the suspicion that it combines Alpine linux witn
nginx and some modules. But we still haven’t reached the base image, that’s another level
down.
At last we’re here, and indeed each of the
Dockerfiles
looks non-malicious.
Setting up DokuWiki in a Docker container can be done in a couple simple steps. The quickest way to get started is to just run a modified version of the command from the linuxserver.io readme:
docker run -d \
--name=dokuwiki \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/London \
-p 127.0.0.1:8080:80 \
-v $HOME/.config/dokuwiki:/config \
--restart always \
ghcr.io/linuxserver/dokuwiki
In this command, we remove the HTTPS port forward since it won’t work over I2P
(for now) and we explicitly specifiy that we want to
only
listen on the localhost
with the HTTP port. This will allow us to safely listen locally without exposing our
service to devices on the LAN or on the Internet. It also specifies that the container
should always restart if it crashes, which will also cause it to start with the docker
daemon, and places the config directory in your
$HOME/.config/
directory.
But let’s suppose that you want to re-build the whole stack of containers locally. In
order to do this, clone each individual parent container and re-build it with the same
name as it has on
ghcr.io
.
Start with the base image:
#! /bin/sh
WD=$(pwd)
git clone https://github.com/linuxserver/docker-baseimage-alpine
cd docker-baseimage-alpine
docker build -t ghcr.io/linuxserver/baseimage-alpine:3.14 .
cd "$WD"
Then the parent image:
#! /bin/sh
WD=$(pwd)
git clone https://github.com/linuxserver/docker-baseimage-alpine-nginx
cd docker-baseimage-alpine-nginx
docker build -t ghcr.io/linuxserver/baseimage-alpine-nginx:3.13 .
cd "$WD"
Finally, you can build the application image:
#! /bin/sh
WD=$(pwd)
git clone https://github.com/linuxserver/docker-dokuwiki
cd docker-dokuwiki
docker build -t ghcr.io/linuxserver/dokuwiki
cd "$WD"
And the run command will be identical to the one shown above. Once your container is running, wait a few seconds and visit the http://127.0.0.1:8080/install.php to continue setting up your DokuWiki. Finalizing the installation requires you to fill out one page with information:
Be sure to disable reporting anonymous usage information. It’s probably not anonymous enough, and we don’t want to phone home to anywhere.
Now that you’ve got DokuWiki configured locally, you can add an I2P Tunnel to connect it to the I2P network. DokuWiki is an HTTP Service, so we’ll use an I2P HTTP Tunnel to create our I2P Site. Navigate to the Hidden Services Manager to get started configuring the I2P Tunnel. I2P has extensive tools in place for helping set up different types of hidden services interactively.
The tool for configuring I2P Tunnels is the Hidden Services Manager, which is an I2P Application you can access by visiting the URL http://127.0.0.1:7657/i2ptunnelmgr in a web browser. Because DokuWiki is a regular HTTP service, with no federation or anything like that to worry about, you probably won’t need to change any of the defaults to effectively run your DokuWiki service. So, start the Setup Wizard to begin the process of tunnel configuration.
After these basic steps, your hidden service will become available in a few seconds. You can find the address by returning to http://127.0.0.1:7657/i2ptunnelmgr and finding the tunnel in the top section, labeled “I2P Hidden Services.”
Copy-and-Paste the line ending with
.b32.i2p
into your I2P browser, or click
the “Preview” button to visit your DokuWiki server using I2P. You can share
this “Base32 Address” with other I2P users to allow them to access your
DokuWiki.
I2P has a flexible system for sharing human-readable addresses built-in. The Address Book is available to every I2P application that wants it. In order to share a site with a human-readable hostname, you’ll need to generate an “Address Helper” link and share it with your peers. The Hidden Services Manager can help you with this. Return to http://127.0.0.1:7657/i2ptunnelmgr and click the link to your DokuWiki tunnel’s Configuration Page. You’ll see something that looks like this:
Once you have saved the settings, you will be returned to the Hidden Services Manager home page. A new element will be visible on the DokuWiki section of the Hidden Services listing:
When you share a link like this, the recipient is prompted to add the address to their Address Book, making it accessible at the human-readable URL.
If you want to register a hostname, and thus propagate it out to the various hostname subscription providers, the best place to do that right now is stats.i2p . Registries are run by peers in the I2P network, in this case a prominent, long-time I2P developer who has earned immense trust in the community.
In order to carry out your registration, you will need to copy an “Authentication string” from within the Hidden Service Manager. Go to the DokuWiki tunnel configuration page in the Hidden Service Manager and click the button that says “Registration Authentication.” This will reveal the required authentication strings.
Once you have your authentication string, add it to the form on stats.i2p:
* It is not recommended to use Registered Hostnames in combination with Encrypted LeaseSets.
I2P has several features which appeal to certain use-cases and niches, in particular it has options for imposing cryptographic requirements on the ability to discover a tunnel endpoint and connect to it, and the ability to accept as input packaged configuration files(And applications, but that’s a discussion for another day).
Blinded LeaseSets are roughly equivalent to blinding in Tor’s onionv3 services, but for I2P. It’s used to prevent Floodfills which distribute information about I2P destinations in the NetDB from being able to discover a hidden service in floodfill data. If you don’t want other people to be able to know your site exists without you telling them, blinded LeaseSets would likely be a necessary part of this strategy.
Encrypted LeaseSets are LeaseSets which are published to the NetDB encrypted, so that only a person who is in possession of the correct keys can decrypt the LeaseSet and discover the information required to connect to a site. If you want to have access-controls on your site which prevent unauthorized users from discovering how to connect to your I2P Site, use Encrypted LeaseSets.
Once you have a Hidden Service set up, the nice thing to do is to document your configuration and share it with the rest of the world. One thing you can do which makes this easier for people who are reviewing, modifying, or reproducing your service is to look in your i2ptunnel.config.d directory and find the file that configures the hidden service tunnel, remove any superfluous or sensitive information, and publish it somewhere anyone can use it. Here is such a config file for the DokuWiki service which we just set up.
description=Serves a DokuWiki, perhaps for your project
name=DokuWiki Server
option.enableUniqueLocal=false
option.i2cp.destination.sigType=7
option.i2cp.leaseSetEncType=4,0
option.i2cp.reduceIdleTime=1200000
option.i2cp.reduceOnIdle=false
option.i2cp.reduceQuantity=1
option.inbound.backupQuantity=0
option.inbound.length=3
option.inbound.lengthVariance=0
option.inbound.nickname=DokuWiki Server
option.inbound.quantity=2
option.outbound.backupQuantity=0
option.outbound.length=3
option.outbound.lengthVariance=0
option.outbound.nickname=DokuWiki Server
option.outbound.quantity=2
option.rejectInproxy=false
option.rejectReferer=false
option.rejectUserAgents=false
option.shouldBundleReplyInfo=false
option.useSSL=false
privKeyFile=i2ptunnel17-privKeys.dat
spoofedHost=wiki.idk.i2p
startOnLoad=true
targetHost=127.0.0.1
targetPort=8080
type=httpserver
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
Hide license