Self-Hosting

Configure Tor Hidden Service

How to make your relay reachable only via a .onion address. Nobody sees the server's IP — not the user, not their ISP, not the platform they use to share the link.

Configure Tor Hidden Service

When your relay runs as a Tor hidden service, the server's IP address is never revealed to anyone who receives an invitation. The relay is reachable only at a .onion address.

This matters because:

  • Someone who intercepts the invitation link cannot find or block your server.
  • The server's location is not tied to you personally.
  • The person opening the link cannot accidentally reveal the server's IP to their ISP.

How this is set up

The docker-compose.yml in infra/relay includes a tor service. When started, it:

  1. Generates a unique .onion key and address (stored in a Docker volume so it persists across restarts).
  2. Creates a hidden service that forwards .onion:80 traffic to the relay container on port 3000.
  3. Binds no host ports — the relay is unreachable from the public internet except through Tor.

Start with Tor

docker compose up -d tor relay

Wait about 30 seconds for Tor to bootstrap. Then read the .onion address:

docker exec relay_tor_1 cat /var/lib/tor/hidden_service/hostname

You will see something like:

abc123xyz789....onion

Copy this address. Update your .env:

RELAY_BASE_URL=http://abc123xyz789....onion

Restart the relay:

docker compose restart relay

Test the hidden service

From a machine with Tor installed (or using Tor Browser):

curl --socks5-hostname 127.0.0.1:9050 http://abc123...onion/health

Expected:

{ "status": "ok" }

If you get a connection error, wait another 30 seconds. Tor hidden services take a moment to propagate.

A .onion link looks like this:

http://abc123xyz789....onion/i/TOKEN

When a user taps this link, their device needs to be able to connect to the Tor network. The iwacu app handles this automatically — it routes .onion addresses through its built-in Tor client.

Users who do not have iwacu installed will see the landing page via Tor Browser, or get a fallback message asking them to install the app first.

You can share .onion links over WhatsApp, SMS, or any messaging platform. The link is meaningless to anyone without iwacu or a Tor-capable browser. The platform cannot see what the link leads to.

Keeping your .onion address

The .onion address is derived from a cryptographic key stored in the tor-data Docker volume. As long as this volume persists, your address stays the same.

docker volume ls | grep tor

Do not delete this volume. If you lose it, your .onion address is gone permanently and you will need to redistribute a new address to everyone who has the old one.

Back up the volume data:

docker run --rm -v relay_tor-data:/data -v $(pwd):/backup alpine \
  tar czf /backup/tor-data-backup.tar.gz /data

Store this backup off the server. A server failure without a backup means starting over with a new address.