THIS IS STILL A WORK IN PROGRESS
THIS POST IS FOR INFORMATIONAL PURPOSES ONLY AND IS STILL BEING UPDATED.
I WILL REMOVE THIS NOTE WHEN THE POST IS FINISHED.
I’VE ONLY HAD A FEW HOURS TO WORK ON THIS AND STILL NEED TIME TO WRAP EVERYTHING UP. SEE TO-DO LIST AT BOTTOM.
Introduction
I put together some step by step instructions and notes on the setup process for Darknet Lantern using Docker.
Relevant Links:
Installation Tutorial
Git Repo
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/darknet-lantern
Lantern Server
http://hb6dzgsmzmu3dmiflhvhe5yreknxtjvvatodgsmunxqgdhyqcro7ztid.onion/
Multistage Dockerfile Build
# Stage 1: builder stage to clone the Darknet Lantern repository via its onion link.
FROM debian:bookworm-slim AS builder
LABEL stage="builder"
ENV DEBIAN_FRONTEND=noninteractive
# Install git, tor, torsocks, and other utilities to perform the git clone.
RUN apt-get update && \
apt-get install -y tor git torsocks curl && \
rm -rf /var/lib/apt/lists/*
# Create directory for cloning.
WORKDIR /src
# Build-time ARG for the onion repository URL.
ARG LANTERN_REPO="http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/darknet-lantern.git"
# Start tor in the background, wait for it to bootstrap, then use torsocks to clone.
RUN set -ex && \
tor & \
TOR_PID=$! && \
sleep 10 && \
torsocks git clone -v ${LANTERN_REPO} darknet-lantern && \
kill ${TOR_PID}
# Stage 2: final image for Darknet Lantern (without tor/torsocks)
FROM debian:bookworm-slim
LABEL maintainer="c0mmando@hackliberty.org"
ENV DEBIAN_FRONTEND=noninteractive
# Install runtime dependencies and socat
RUN apt-get update && \
apt-get install -y nginx php8.2-fpm python3 python3-pip curl socat && \
apt-get install -y python3-pandas python3-requests python3-socks && \
rm -rf /var/lib/apt/lists/*
# Copy the Darknet Lantern source from the builder stage.
RUN mkdir -p /srv/darknet-lantern
COPY --from=builder /src/darknet-lantern/ /srv/darknet-lantern/
# Configure nginx: copy your pre-made configuration.
COPY ./lantern_nginx_conf/lantern.conf /etc/nginx/sites-available/lantern.conf
RUN ln -sf /etc/nginx/sites-available/lantern.conf /etc/nginx/sites-enabled/ && \
rm -f /etc/nginx/sites-enabled/default
# Expose the internal web service port (adjust as necessary).
EXPOSE 80 #NEED TO DOUBLE CHECK THIS
# Create an updated docker-entrypoint.sh that starts socat in the background.
RUN echo '#!/bin/bash' > /usr/local/bin/docker-entrypoint.sh && \
echo 'set -e' >> /usr/local/bin/docker-entrypoint.sh && \
echo '' >> /usr/local/bin/docker-entrypoint.sh && \
echo '# Start socat to forward 127.0.0.1:9050 to tor-proxy:9050' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'echo "Starting socat to forward traffic from 127.0.0.1:9050 to tor-proxy:9050..."' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'socat TCP-LISTEN:9050,reuseaddr,fork TCP:tor-proxy:9050 &' >> /usr/local/bin/docker-entrypoint.sh && \
echo '' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'echo "Starting php8.2-fpm..."' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'service php8.2-fpm start' >> /usr/local/bin/docker-entrypoint.sh && \
echo '' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'echo "Starting nginx..."' >> /usr/local/bin/docker-entrypoint.sh && \
echo 'nginx -g "daemon off;"' >> /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
WORKDIR /srv/darknet-lantern
ENTRYPOINT [ "/usr/local/bin/docker-entrypoint.sh" ]
- docker‑compose Configuration
- Three services are defined:
- darknet-lantern: Built from our updated Dockerfile, it exposes its internal port (80) to be used by SWAG via the shared networks.
- tor: Runs the separate Tor container using the
osminogin/tor-simple
image. - tor-proxy: Runs a seperate Tor container using the
osminogin/tor-simple
image with an open Tor proxy for proxying lantern requests over Tor. swag: Runs the SWAG container (from theghcr.io/linuxserver/swag
image), acting as a reverse proxy and TLS terminator.
Two networks (tor
andswag
) are created so that SWAG can proxy traffic to the Darknet Lantern container and, if necessary, containers can communicate with the Tor container.
- Three services are defined:
networks:
tor:
lantern:
services:
darknet-lantern:
build: .
container_name: darknet-lantern
volumes:
- ./lantern_data:/srv/darknet-lantern/www/participants # Persist Darknet Lantern application data if needed.
- ./lantern_nginx_conf:/etc/nginx/sites-enabled # persist your nginx configuration.
networks:
- tor
- lantern
restart: unless-stopped
tor:
image: osminogin/tor-simple
container_name: tor
volumes:
- ./tor-data:/var/lib/tor
- ./tor-data/torrc:/etc/tor/torrc
networks:
- tor
restart: unless-stopped
tor-proxy:
image: osminogin/tor-simple
container_name: tor-proxy
volumes:
- ./tor-proxy:/var/lib/tor
- ./tor-proxy/torrc:/etc/tor
networks:
- tor
- Create Volume Folders and Create nginx conf
mkdir lantern_data && mkdir lantern_nginx_conf
cd lantern_nginx_conf
nano lantern.conf
(enter default conf for now)
server {
listen 4443;
listen [::]:4443;
server_name lantern.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion;
root /srv/darknet-lantern/www/;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
index index.php;
# optional read-only static php file without the searchbar, to display all links by default :
# index static.php;
}
-
Building & Running
- To build and run the complete multi‑container setup, run:
docker-compose up --build
- To build and run the complete multi‑container setup, run:
-
Create Onions
- Create folders in the tor-data volume associated with your tor-simple container if you have not already and create the darknet lantern folder
sudo mkdir -p $HOME/tor-data/torrc && sudo mkdir -p $HOME/tor-data/darknet-lantern
-
Set Permissions
sudo chmod 700 $HOME/tor-data/darknet-lantern && sudo chown 100:65533 $HOME/tor-data/darknet-lantern
-
create tor-proxy folders
a.sudo mkdir -p $HOME/tor-proxy/torrc && sudo chown -R 100:65533 $HOME/tor-proxy/ && sudo chmod -R 700 $HOME/tor-proxy/
-
Add Firewall Rules
a.sudo ufw allow 4443/tcp
b.sudo ufw reload
-
Add the following to torrc
a.sudo nano $HOME/tor-data/torrc/torrc
HiddenServiceDir /var/lib/tor/darknet-lantern
HiddenServicePort 80 darknet-lantern:4443
- Update your lantern.conf file to include Tor hostname
a.sudo cat $HOME/tor-data/darknet-lantern/hostname
b.nano $HOME/lantern_nginx_conf/lantern.conf
server {
listen 4443;
listen [::]:4443;
server_name UPDATEME.onion;
root /srv/darknet-lantern/www/;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
index index.php;
# optional read-only static php file without the searchbar, to display all lin>
# index static.php;
}
- Configure Tor Proxy
- create torrc
Do not use0.0.0.0
unless your configuration requires it. For the purpose of this specific configuration, it is acceptable because docker container will only be accessible over tor docker network
a.sudo echo "SocksPort 0.0.0.0:9050" > $HOME/tor-proxy/torrc/torrc
- launch tor-proxy and check logs
a.sudo docker compose up -d
b.sudo docker logs tor-proxy
should look something like
[..]
[notice] Read configuration file "/etc/tor/torrc"
[warn] You specified a public address '0.0.0.0:9050' for SocksPort. Other people on the Internet might find your computer and use it as an open proxy. Please dont allow this unless you have a good reason.
[notice] Opening Socks listener on 0.0.0.0:9050
[notice] Opened Socks listener connection (ready) on 0.0.0.0:9050
[..]
- Modified Dockerfile (reflected above already)
-
Installed socat:
Added socat in the final image to forward connections from 127.0.0.1:9050 to the tor-proxy container. -
Updated ENTRYPOINT:
Modified docker-entrypoint.sh to run:
socat TCP-LISTEN:9050,reuseaddr,fork TCP:tor-proxy:9050 &
This ensures that the application’s hardcoded proxy (127.0.0.1:9050) is forwarded to tor-proxy:9050. -
Network Configuration:
Requires both containers to be on the same Docker network so that the hostname tor-proxy resolves correctly. (already in docker compose)
-
Initialize Darknet Lantern
a.sudo docker exec -it darknet-lantern python3 /scripts/lantern.py
b.enter your onion hostname
c. is this your instance domain?yes
-
Add Webring Participants
We need to populate the webring participant folder because our bind mount volume is set to participants and it is currently empty.
a. Visit http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/darknet-lantern/src/branch/main/www/participants
b. Add all the listed webring participants
c.sudo docker exec -it darknet-lantern python3 /scripts/lantern.py
d. Select Option 5 “Add a new webring participant”
e. Select Option 4 “Synchronize new links” -
Browse to your onion URL and confirm website is being served
BONUS: Host Lantern on Clearnet using SWAG Reverse Proxy
- Add SWAG to docker-compose, this is what mine looks like:
swag:
image: ghcr.io/linuxserver/swag
restart: unless-stopped
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1000
- PGID=1000
- URL=${SWAG_URL}
- SUBDOMAINS=${SWAG_SUBDOMAINS}
- VALIDATION=http
- EMAIL=${SWAG_EMAIL}
- ONLY_SUBDOMAINS=false
volumes:
- ./swag:/config:Z
- /etc/localtime:/etc/localtime:ro
ports:
- 443:443
- 80:80
networks:
- tor
- lantern
security_opt:
- no-new-privileges:true
-
Create the DNS Record for Lantern
a. TYPE:A
b. NAME:lantern.hackliberty.org
c. IPV4:93.95.228.245
-
Add the subdomain to swag environment file (.env)
a.SWAG_SUBDOMAINS=git, paste, ots, write, simplex, blog, www, lantern
-
Add Nginx Lantern Site to Proxy connections to upstream container
a.cd /swag/nginx/site-confs/
b.nano lantern.conf
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name lantern.*;
include /config/nginx/ssl.conf;
location / {
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
add_header Onion-Location http://hb6dzgsmzmu3dmiflhvhe5yreknxtjvvatodgsmunxqgdhyqcro7ztid.onion$request_uri;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
set $upstream_app darknet-lantern;
set $upstream_port 4443;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}
-
Restart Docker Compose to Pull LetsEncrypt Certs
a.sudo docker compose up -d
-
Check your instance is hosted over clearnet
https://lantern.hackliberty.org
To-Do List
Implement optional clearnet sectiondone- Create a user for limited permissions
Remove server name in lantern.conf if unnecessaryleave it, its necessaryDouble check port 80 expose in Dockerfile – remove if unnecessaryremovedDouble check port 4443 expose in docker-compose file – remove if unnecessaryremovedClean up docker compose file – remove swag – add to optional sectiondone- Security hardening and explore alpine as container image
- Check website html for proper SEO meta tagging (oEmbed, OpenGraph)
- Setup or check for cron job – add it to Dockerfile if necessary
- Setup webring, banner, and explore themes
- Add verified and unverified links