~/blog/"How to host your own website on the darkweb"
2023-01-25
In my previous post, I explained how to set up a Raspberry Pi on your home network to act as an I2P router, allowing you to browse anonymous sites (and contribute to the network at the same time).
If you’re not familiar with I2P, or how to set up an I2P router. Please checkout my previous post, as this one starts where the other one left off.
I could give you the whole spiel about the importance of censorship resistant systems, freedom of information, decentralisation of the web, etc. But the truth is: I did it because I was bored, and this was fun. So, why not?
You certainly won’t get as much visibility when compared with a website on the clearnet. But you can always have a copy of your personal website on both the clearnet and I2P. However, be aware that speed that you get on I2P is really slow, so keep it light. Who needs anything more than HTML and CSS anyway?
This is the solution that I found to host it. Do let me know if you think it can be improved!
The first step is to make a website. Log into the Raspberry Pi, and create something simple.
cd ~/
echo "<h1>Hello World!</h1>" >> index.html
Now, you need to make it visible to anyone on your home network. For this part, you’ll want to have both docker and docker-compose installed. Also, make sure that you follow the post-installation steps as well, so that you don’t have to run docker with sudo
, and that docker starts when the Raspberry Pi boots up.
To host the website, you’ll want to use a webserver like nginx
. But to make things easier, you can use it inside a docker container.
Start by creating a directory inside your home called nginx
and go into it (you can give it another name, as long as you keep things consistent).
mkdir ~/nginx
cd ~/nginx
Then, create a directory to keep the website in:
mkdir website
mv ~/index.html website/
Now that’s in place, you want to create a docker container running nginx
, and tell it where to find your website.
You could just use docker run
for this, but docker-compose also allows you to run multi-container applications. One could argue this is a bit overkill, but there is one little feature which I quite like.
Create a new file named docker-compose.yml
inside ~/nginx
, and paste the following inside:
version: '3'
services:
app:
image: 'nginx:latest'
restart: always
ports:
- '80:80'
volumes:
- ~/nginx/website:/usr/share/nginx/html
watchtower:
image: containrrr/watchtower
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock
This will tell docker-compose to launch a multi-container application with 2 containers. The first one (app
), will be a webserver with the following characteristics:
nginx
image80
in the host (the Raspberry Pi), to port 80
in the container~/nginx/website
in the Raspberry Pi, to the the default path used by nginx
to read the website from (/usr/share/nginx/html
).That last point is important. It means that whatever you put inside ~/nginx/website/
will be read by the docker container running nginx
, and will be served as your website. Therefore, if you want to update it, you just need to change the files inside ~/nginx/website/
.
OK that’s pretty obvious, but what’s watchtower?
This is neat little solution that automatically updates app
every time a new version of nginx:latest
is pushed to Docker Hub. In other words, if a newer version is available, watchtower pulls the latest version, shuts-down the currently running container (i.e. app
), and launches a new one running the latest version. Have a look at the documentation for more details.
Once the docker-compose.yml
file is saved, all you have to do is launch it:
cd ~/nginx/
docker compose up -d
You can now open a browser from another machine on your network, and give it the internal IP address of the Raspberry Pi.
firefox <raspberry-pi-internal-ip-address>
You should be able to see your website. If this does not work, something went wrong with the webserver. Try to pinpoint the problem before proceeding.
Wait, how do I find this address?
From your Raspberry Pi, you can run the command below to get the address of the interfaces (e.g. if the Raspberry Pi is using the wifi, look at the inet
field under the wlan0
section):
ifconfig -a
If you want to find it from the machine where you’re opening the browser, you can scan your network to find it:
sudo nmap -sn 192.168.1.0/24
I won’t go into detail on how nmap
works, as it’s outside of the scope of this tutorial.
As mentioned in the introduction, at this point, you should have i2pd
configured in the same way as described in my previous post. I’m assuming that’s the case for you.
Now that you can see the site from a different machine on your network, it’s time to make it visible on i2p. For that, you’re going to need to change the tunnels.conf
file. It’s usually on ~/.i2pd/tunnels.conf
, but that might not be the case for you.
If you access the i2pd webconsole (http://127.0.0.1:7070/
), you should see a Data path
field on the main page (in my case, it says /var/lib/i2pd
). That’s the directory where you can find the tunnels.conf
file. Open that file (you might need to use sudo
), and add the following to the bottom:
[anon-website]
type = http
host = 127.0.0.1
port = 80
keys = anon-website.dat
Restart i2pd:
sudo systemctl restart i2pd.service
Open the webconsole, and go to the tunnels page (http://127.0.0.1:7070/?page=i2p_tunnels
), you should see a subheading saying anon-website
followed by a long string with *.b32.i2p:80
at the end. That’s the address to the website (you should be able to open it in the browser after a while).
Congratulations! You are now hosting your own website on the darkweb.
But that long string is rather ugly, wouldn’t it be nice to have a nice human-readable address?
To do that, go into the webconsole > I2P tunnels > anon-website. On this page, click on “Address registration line” and fill out which domain you’d like. If the generation is successful, it should take you to another page, asking to add a small description. Submit it, and wait a bit until the new address works (it could be a couple of days, so don’t stand there refreshing in despair).
You shouldn’t need anything else. But if at any point you need to generate an authentication string, you’ll need to use i2pd-tools, in particular readdr:
./regaddr anon-website.dat <your-domain>.i2p > auth_string.txt
cat auth_string.txt
The anon-website.dat
file can be found in the same directory as the tunnels.conf
file. Follow the instructions on the project’s repo on how to compile i2pd-tools.
After a few days, you should be able to see the website being announced on planet.i2p
and identiguy.i2p
.
And that’s it! Enjoy your own piece of virtual real estate on the darkweb.