Offering an onion address
On a monitored network (a workplace, a school), a visit to OpenWhistle can be seen even
though the report stays private. Tor Browser hides the visit too. Run a Tor hidden service
on the same host, aimed at the onion-only nginx entry on 127.0.0.1:8080. It is
published there only (the ports: entry in docker-compose.prod.yml).
# 1. Install tor on the host, then add to /etc/tor/torrc:
HiddenServiceDir /var/lib/tor/openwhistle/
HiddenServicePort 80 127.0.0.1:8080
# 2. Restart tor, then read the generated address:
$ systemctl restart tor
$ cat /var/lib/tor/openwhistle/hostname
abc...xyz.onion
# 3. Set ONION_LOCATION in .env and restart the app:
ONION_LOCATION=http://abc...xyz.onion
$ docker compose up -d app
With ONION_LOCATION set:
- Every HTML response carries an
Onion-Locationheader; Tor Browser offers to switch. - The submit page shows the address, except to a visitor already on the onion service.
- A request through the onion listener gets no HSTS and no
Securecookie flag. That connection was never TLS (Tor encrypts it), and a browser can refuse aSecurecookie over plain HTTP.
Never the Host header: any client on the HTTPS listener could send
Host: <anything>.onion. Instead the bundled nginx/nginx.conf
sets X-OW-Onion: 1 only in the onion (port 8080) server block and clears it in
the regular (443) one. It strips incoming IP-forwarding headers the same way.
So the app's own port (4009) must stay reachable only through this
nginx, as IP stripping already requires. A deployment that exposes the app
directly, or through another proxy, must set or clear X-OW-Onion itself.
Otherwise neither protection holds.
Without ONION_LOCATION the app ignores X-OW-Onion, so a path
that forwards it from the client, such as the Helm chart's ingress, is safe. With
ONION_LOCATION behind ingress-nginx, clear it there with the annotation
nginx.ingress.kubernetes.io/configuration-snippet: proxy_set_header X-OW-Onion "";
(the controller needs allow-snippet-annotations).
/var/lib/tor/openwhistle/ holds the address's private key
hs_ed25519_secret_key in that directory is the onion address. Lose it
and the address changes for good, breaking every link a reporter was given. Whoever holds
it can impersonate the service.
- Back the directory up before any host migration or volume change.
- Keep it root/tor-only: Tor sets
0700on creation, but a bind-mount or a backup step can widen that. Check it. - Never commit or publish it, least of all wherever this how-to is shared.
HiddenServicePort forwards every Tor visitor to nginx from
127.0.0.1, so per-IP limits cannot tell visitors apart. The onion server
block therefore has its own zone, sized for several concurrent reporters. Heavy
concurrent use still shares that one budget and can see a 429. If that happens, raise the
zone's rate/burst in nginx/nginx.conf.