Create your own Onion site accessible via Tor

This guide explains how to host your local website (e.g., a Dockerized Next.js app as an Onion Service in the Tor network accessible via an .onion-address.
How it works:
Your server builds a tunnel from the inside out. This means you don’t need a public IP, and you don’t need to touch
your router’s firewall (No Port Forwarding or anything else required).
Tor connects to “Introduction Points” in the network. Users meet your server at a “Rendezvous Point” so both stay anonymous.
Prerequisites
- A running website
Install Tor
Install the Tor service on your Linux machine.
# Debian
sudo apt install tor -y
# Arch
sudo pacman -S torConfigure the Tor Onion Service
Next step is opening the config file of Tor (torrc) and doing the appropriate configurations to setup an Onion Service.
Open the file with root privileges:
sudo nano /etc/tor/torrcYou will need to add the following two lines to your torrc file:
HiddenServiceDir /var/lib/tor/my_website/
HiddenServicePort 80 127.0.0.1:3000- The
HiddenServiceDirline specifies the directory which should contain information and cryptographic keys for your Onion Service. - The
HiddenServicePortline specifies a virtual port (that is, the port that people visiting your Onion Service will be using). In the above case, it says that any traffic incoming to port 80 of your Onion Service should be redirected to127.0.0.1:3000(which is where your Next.js app or Docker container is listening).
Why Port 80 and no SSL/HTTPS i asked myself
The traffic between the user’s Tor browser and your server is inherently end-to-end encrypted by the Tor protocol itself.
The .onion address acts as the cryptographic public key. Therefore, an additional SSL certificate would be redundant.
The connection is secure, even though it routes to local HTTP.
Secure your Docker Container / Localhost rule
When running deploying website via Docker on a vServer, make sure your container is only accessible locally.
If you bind it to 0.0.0.0, anyone could access your site via your server’s public IP, destroying the idea of your Tor Service and your anonymity.
Correct Binding:
# In your deploy script or docker run command
docker run -p 127.0.0.1:3000:3000 ...Update Next.js Middleware
Since your site is now accessed via an .onion domain, you must update your middleware.ts (when hosting Next.js sites) to allow this host, otherwise,
Next.js will block the request with a “Bad Host Header” error.
// Inside your middleware security check:
const allowedDomains = [
'<domain1>',
'localhost',
'<subdomain1>.localhost'
];
const isAllowedHost =
allowedDomains.includes(currentHost) ||
currentHost.endsWith('.<domain1>') ||
currentHost.endsWith('.onion'); // <-- Allow all .onion addresses
if (!isAllowedHost) {
return new NextResponse('Bad Host Header', { status: 400 });
}Restart Tor and get your Onion Address
Restart Tor to apply the configuration. Tor will automatically generate the directory and your keys.
sudo systemctl restart torNow, retrieve your newly generated Onion address:
sudo cat /var/lib/tor/my_website/hostnameCopy this address into your Tor Browser to test your live website. It might take 1-2 minutes for the network to fully propagate your new address.
Backup your Secret Key!
Inside /var/lib/tor/my_website/, you will find a file named hs_ed25519_secret_key. This is your private key. If you lose this file, or your server is wiped, your .onion address is gone forever. Keep it safe and never share it!
Taking the site offline
If you want to unpublish your site, you have two options depending on your needs:
- Temporary: Stop the Tor service. The tunnel collapses immediately.
Terminal
sudo systemctl stop tor - Permanent: Delete the lines in your
/etc/tor/torrcand completely delete the folder/var/lib/tor/my_website/. Your domain is now permanently deleted.
Created: 30.03.2026
Last Updated: 30.03.2026