Tor hidden services (also called onion services) allow you to host websites, APIs, or any network service that is accessible exclusively through the Tor network. Unlike conventional servers that expose your IP address to the internet, hidden services route all traffic through Tor’s onion routing, concealing both your location and the identity of your users. This guide walks you through setting up a basic hidden service, configuring it securely, and integrating it into your development workflow.
Prerequisites
Before you begin, ensure you have access to a Linux server (Debian, Ubuntu, or Fedora are all well-supported) and the Tor software. You will need root or sudo access to configure the service. This guide assumes you are comfortable working from the command line and understand basic networking concepts.
Installing Tor
Most Linux distributions include Tor in their default repositories. On Ubuntu or Debian:
sudo apt update
sudo apt install tor
On Fedora or RHEL-based systems:
sudo dnf install tor
Verify the installation by checking the Tor version:
tor --version
You should see output indicating Tor is installed. If you need a newer version, consider using the Tor Project’s official repository.
Configuring Your First Hidden Service
The Tor configuration file is located at /etc/tor/torrc on most Linux systems. Open this file with your preferred text editor:
sudo nano /etc/tor/torrc
Scroll down to the section labeled ## This section is for onion services. You will find commented-out examples. Add the following configuration to create a basic hidden service:
HiddenServiceDir /var/lib/tor/my_hidden_service
HiddenServicePort 80 127.0.0.1:8080
Breaking this down:
HiddenServiceDirspecifies where Tor will store your service’s private key and hostnameHiddenServicePort 80 127.0.0.1:8080tells Tor to forward incoming requests on port 80 (the standard HTTP port) to your local web server running on port 8080
Save the file and restart Tor:
sudo systemctl restart tor
Retrieving Your Onion Address
After Tor restarts, check the hidden service directory for the generated hostname:
sudo cat /var/lib/tor/my_hidden_service/hostname
This command returns a string ending in .onion — your service’s public address. Share this address with users who have Tor Browser installed. They can access your service by entering the .onion address directly in the Tor Browser address bar.
Running a Web Server for Your Hidden Service
Your hidden service needs a local web server to serve content. A simple Python HTTP server works well for testing:
# Run on port 8080 to match our Tor configuration
python3 -m http.server 8080 --directory /var/www/html
For production deployments, consider using nginx or Apache. Configure your web server to listen only on localhost (127.0.0.1) to prevent accidental exposure of your content outside the Tor network.
Security Hardening for Hidden Services
Running a hidden service requires additional security considerations beyond a standard web server.
Disable Directory Information Leakage
By default, Tor nodes can learn about your hidden service through directory requests. Add the following to your torrc to reduce this exposure:
HiddenServiceDir /var/lib/tor/my_hidden_service
HiddenServicePort 80 127.0.0.1:8080
HiddenServiceVersion 3
Using version 3 onion addresses provides improved cryptography and better resistance to enumeration attacks compared to version 2 addresses.
Restrict Access by Client Authorization
For private services accessible only to authorized users, configure client authentication:
HiddenServiceDir /var/lib/tor/private_service
HiddenServicePort 80 127.0.0.1:8081
HiddenServiceVersion 3
HiddenServiceAuthorizeClient stealth myapp
This configuration creates a stealth authorization scheme named “myapp”. After restarting Tor, retrieve the client authentication line from the hostname file:
sudo cat /var/lib/tor/private_service/hostname
The output includes an authentication string that authorized clients add to their Tor configuration. Users must configure this in their torrc:
ClientOnionAuthDir /var/lib/tor/authdir
Place the authentication file in the specified directory with the format hostname:port=key. This ensures only authorized clients can reach your service.
Run Tor in a Container
For isolated deployments, run Tor inside a Docker container:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y tor && rm -rf /var/lib/apt/lists/*
COPY torrc /etc/tor/torrc
RUN mkdir -p /var/lib/tor/hidden_service
RUN chown -R debian-tor:debian-tor /var/lib/tor
USER debian-tor
CMD ["tor"]
Build and run the container:
docker build -t tor-hidden-service .
docker run -d -p 127.0.0.1:9050:9050 --name my-tor-service tor-hidden-service
This approach keeps your Tor installation isolated from your host system.
Automating Deployment with Systemd
Create a systemd service to manage your web application alongside Tor:
[Unit]
Description=My Hidden Service Web App
After=network.target tor.service
Requires=tor.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
This ensures your application starts after Tor is ready. Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
Testing Your Hidden Service
From your local machine, install Tor Browser and navigate to your .onion address. Verify that:
- The page loads without errors
- Your server logs show the request
- No IP addresses outside the Tor network appear in your logs
You can also test from the command line using torsocks:
torsocks curl http://your-onion-address.onion
This confirms your service works for users connecting through Tor.
Performance Considerations
Hidden services introduce latency because traffic bounces through multiple Tor nodes. To optimize:
- Keep your payloads small
- Enable HTTP keep-alive connections
- Consider static site generation over dynamic server-side rendering
- Monitor circuit build times and rotate to faster relays if needed
Summary
Setting up a Tor hidden service involves installing Tor, configuring your torrc file, and ensuring your local web server is properly secured. For developers, the key steps are using version 3 onion addresses, restricting access through client authorization when needed, and running services in isolated environments. With your hidden service running, you can offer access to your application without revealing your server’s location or exposing it to the broader internet.
Built by theluckystrike — More at zovo.one