Deploy Hidden Service Web in Linux: The Complete Guide (with Vanity .onion Domains)

Deploy Hidden Service Web in Linux: Complete Guide with Vanity .onion Domains
This guide walks you through deploying your web application as a Tor hidden service on Linux. Whether you're building something privacy-focused, testing anonymous deployments, or exploring how Tor works, this tutorial covers everything from basic hidden service deployment to creating custom vanity .onion addresses.
We'll cover hidden service configuration, Nginx reverse proxy setup, and generating memorable .onion domains using vanity generators.
What Are We Building?
Before diving into the technical details, let's understand the components:
Tor Hidden Services Explained
Tor Hidden Services (now called "Onion Services") allow you to host websites that are only accessible through the Tor network. Unlike regular websites that need domain registration and public IP addresses, hidden services:
- Generate unique
.onionaddresses automatically - Provide end-to-end encryption by default
- Hide both server and client locations
- Don't require traditional DNS or domain registration
Nginx Reverse Proxy in This Setup
Nginx acts as a middle layer between Tor and your web application:
Tor Browser → Tor Network → Your Server (Nginx) → Your Web App
Benefits of using Nginx:
- Load balancing for multiple app instances
- SSL termination (though Tor already encrypts)
- Caching for better performance
- Request filtering and security headers
Vanity .onion Domains
Regular .onion addresses look like random gibberish: 3g2upl4pq6kufc4m.onion
Vanity domains let you customize the prefix: webapp4pq6kufc4m.onion
This makes your hidden service more memorable and professional-looking.
Requirements & Package Installation
What You'll Need
- Linux server (Debian/Ubuntu recommended)
- Running web application on any port (we'll use port 4000 as example)
- Root or sudo access
- Patience (vanity generation can take time!)
Required Packages
# Essential packages for our hidden service setup
curl # Download and HTTP requests
nginx # Reverse proxy server
tor # The Tor daemon itself
autoconf # Build configuration tools
automake # Makefile generation
libtool # Library creation tools
make # Build compilation
gcc # C compiler
git # Version control
libsodium-dev # Cryptography library
build-essential # Essential build tools
Installation Command
sudo apt update && sudo apt upgrade -y
sudo apt install curl nginx tor autoconf automake libtool make gcc git libsodium-dev build-essential -y
What this does:
- Updates package lists and existing packages
- Installs all required dependencies in one command
- The
-yflag automatically confirms installation
Tutorial: Nginx Reverse Proxy Setup
Step 1: Verify Your Web App is Running
First, make sure your application is accessible locally:
curl http://127.0.0.1:4000
You should see your app's response. If not, start your application first!
Example for different frameworks:
# Next.js
npm run start # Usually runs on port 3000
# Express.js
node server.js # Check your server file for port
# Python Flask
python app.py # Usually runs on port 5000
# Laravel
php artisan serve # Usually runs on port 8000
Step 2: Create Nginx Configuration
Create a new nginx configuration file:
sudo nano /etc/nginx/sites-available/yourwebapp
Add this configuration:
server {
# Listen only on localhost port 8080
listen 127.0.0.1:8080;
# Local server name (not publicly accessible)
server_name yourwebapp.local;
# Proxy all requests to your web application
location / {
# Forward requests to your app running on port 4000
proxy_pass http://127.0.0.1:4000;
# Preserve original request headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Handle WebSocket connections (if needed)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
# Security headers for hidden services
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
}
Configuration breakdown:
listen 127.0.0.1:8080→ Only accept local connections on port 8080proxy_pass→ Forward requests to your actual web appproxy_set_header→ Preserve important request information- Security headers → Basic protection against common attacks
Step 3: Enable and Test Configuration
Enable the site and test configuration:
# Create symbolic link to enable the site
sudo ln -s /etc/nginx/sites-available/yourwebapp /etc/nginx/sites-enabled/
# Test nginx configuration for syntax errors
sudo nginx -t
# If test passes, restart nginx
sudo systemctl restart nginx
# Check nginx status
sudo systemctl status nginx
Verify the proxy works:
curl http://127.0.0.1:8080
You should see the same response as your original app!
Tutorial: Tor Hidden Service Deployment
Step 1: Configure Tor Hidden Service
Edit the Tor configuration file:
sudo nano /etc/tor/torrc
Add these lines at the bottom:
# Hidden Service Configuration
HiddenServiceDir /var/lib/tor/yourwebapp/
HiddenServicePort 80 127.0.0.1:8080
Configuration explanation:
HiddenServiceDir→ Directory where Tor stores keys and hostnameHiddenServicePort→ Maps external port 80 to your nginx proxy on port 8080
Step 2: Start Tor Service
Restart Tor to apply configuration:
# Restart tor service
sudo systemctl restart tor
# Check if tor is running properly
sudo systemctl status tor
# Check tor logs for any errors
sudo journalctl -u tor -f
Step 3: Get Your .onion Address
Retrieve your generated .onion domain:
sudo cat /var/lib/tor/yourwebapp/hostname
You'll see something like:
abc123def456ghi789jkl.onion
What happened here:
- Tor generated a cryptographic key pair
- The .onion address is derived from the public key
- Private key is stored securely for your service
Step 4: Test Your Hidden Service
- Download Tor Browser from torproject.org
- Open Tor Browser and wait for connection
- Navigate to your .onion address
- Verify your web app loads correctly
Your hidden service is now live and accessible through Tor.
Tutorial: Creating Vanity .onion Domains
Regular .onion addresses are hard to remember. Creating a custom prefix makes your service more memorable.
Step 1: Understanding Vanity Domain Limitations
Character limitations:
- Only lowercase letters
a-zand digits2-7are allowed - No
0,1,8,9(these aren't in base32 encoding) - Maximum practical prefix length: 6-8 characters
Time estimation for generation:
1-2 characters: Instant (seconds)
3-4 characters: Minutes
5-6 characters: Hours to days
7-8 characters: Days to weeks
9+ characters: Months to years (not practical)
Step 2: Clone Vanity Generator
Download and build the mkp224o vanity generator:
# Clone the repository
git clone https://github.com/cathugger/mkp224o.git
cd mkp224o
Step 3: Build the Generator
Generate build configuration:
# Generate build scripts
./autogen.sh
# Configure the build system
./configure
# Compile the binary
make
What each command does:
autogen.sh→ Creates build configuration filesconfigure→ Checks dependencies and sets up compilationmake→ Compiles the source code into executable
Step 4: Generate Vanity .onion Address
Check your system's CPU cores and generate vanity address:
# Check CPU core count
nproc
# Generate vanity .onion with 2 threads (adjust based on your cores)
# Replace "webapp" with your desired prefix
./mkp224o -j 2 webapp
# For better performance, use more threads:
# ./mkp224o -j 4 webapp # For 4+ core systems
# ./mkp224o -j 8 webapp # For 8+ core systems
Command breakdown:
-j 2→ Use 2 CPU threads for generationwebapp→ Look for .onion addresses starting with "webapp"
Example output:
waiting for luck...
working with 2 threads, please wait...
webapp4d5e6f7g8h9i.onion
Step 5: Apply Vanity Domain
When the generator finds a match:
# Stop the generator (Ctrl+C)
# Copy the generated keys
sudo cp webapp4d5e6f7g8h9i.onion/hs_ed25519_secret_key /var/lib/tor/yourwebapp/
sudo cp webapp4d5e6f7g8h9i.onion/hostname /var/lib/tor/yourwebapp/
# Set correct permissions
sudo chown debian-tor:debian-tor /var/lib/tor/yourwebapp/*
sudo chmod 600 /var/lib/tor/yourwebapp/hs_ed25519_secret_key
# Restart tor to use new keys
sudo systemctl restart tor
# Verify new hostname
sudo cat /var/lib/tor/yourwebapp/hostname
Your vanity .onion domain is now active.
Advanced Configuration & Security
Enhanced Security Headers
Update your nginx configuration for better security:
server {
listen 127.0.0.1:8080;
server_name portfolio.local;
# Enhanced security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "no-referrer";
add_header Content-Security-Policy "default-src 'self'";
# Disable server tokens
server_tokens off;
location / {
proxy_pass http://127.0.0.1:4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Remove revealing headers
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
# Block common attack patterns
location ~ /\. {
deny all;
}
}
Multiple Services Configuration
Run multiple hidden services on one server:
# In /etc/tor/torrc
HiddenServiceDir /var/lib/tor/webapp1/
HiddenServicePort 80 127.0.0.1:8080
HiddenServiceDir /var/lib/tor/webapp2/
HiddenServicePort 80 127.0.0.1:8081
HiddenServiceDir /var/lib/tor/api/
HiddenServicePort 80 127.0.0.1:8082
Performance Optimization
Optimize for better performance:
# Add to nginx configuration
location / {
# Enable gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# Enable caching for static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
proxy_pass http://127.0.0.1:4000;
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 16 8k;
}
Troubleshooting Common Issues
Service Not Accessible
# Check if tor is running
sudo systemctl status tor
# Check nginx status
sudo systemctl status nginx
# Check tor logs
sudo journalctl -u tor -f
# Check nginx logs
sudo tail -f /var/log/nginx/error.log
# Verify port bindings
sudo netstat -tulpn | grep :8080
Vanity Generation Too Slow
# Use more CPU cores
./mkp224o -j $(nproc) webapp
# Try shorter prefixes
./mkp224o -j 4 web # Instead of "webapp"
# Check system load
htop
Permission Errors
# Fix tor directory permissions
sudo chown -R debian-tor:debian-tor /var/lib/tor/yourwebapp/
sudo chmod 700 /var/lib/tor/yourwebapp/
sudo chmod 600 /var/lib/tor/yourwebapp/*
Vanity Generation Time Estimates
Based on average hardware (4-core CPU):
| Prefix Length | Example | Estimated Time |
|---|---|---|
| 3 chars | app | 1-5 minutes |
| 4 chars | blog | 10-30 minutes |
| 5 chars | ghost | 2-8 hours |
| 6 chars | webapp | 1-3 days |
| 7 chars | mysite1 | 1-4 weeks |
| 8 chars | portfolio | 2-6 months |
Pro Tips for Faster Generation:
- Use common letters (
a,e,i,o) - Avoid rare combinations
- Consider shorter, memorable prefixes
- Use high-core-count servers for faster generation
Security Best Practices
Best Practices
- Keep your server updated regularly
- Use strong passwords for server access
- Monitor logs for suspicious activity
- Backup your private keys securely
- Use HTTPS within your application (defense in depth)
What to Avoid
- Don't share your private keys
- Don't log sensitive user information
- Don't use predictable file paths
- Don't ignore security updates
- Don't run unnecessary services
Additional Security Measures
# Enable firewall
sudo ufw enable
sudo ufw allow ssh
sudo ufw deny 8080 # Block direct access to nginx
# Fail2ban for SSH protection
sudo apt install fail2ban -y
# Regular security updates
sudo apt update && sudo apt upgrade -y
Summary
You've successfully deployed a Tor hidden service with:
- Nginx reverse proxy for professional routing
- Secure .onion domain accessible via Tor
- Custom vanity address for better branding
- Security best practices for safe operation
What's Next?
- Monitor your service with logs and analytics
- Optimize performance based on usage patterns
- Consider load balancing for high-traffic services
- Implement additional security layers as needed
- Share your .onion address through secure channels
Use Cases for Hidden Services
- Privacy-focused applications (secure messaging, anonymous feedback)
- Development testing (internal tools, staging environments)
- Censorship resistance (news sites, whistleblowing platforms)
- Personal projects (private blogs, family sharing)
Remember: With great privacy comes great responsibility. Use these tools ethically and follow your local laws.
Useful Resources:
TL;DR: Install packages → Configure nginx reverse proxy → Setup tor hidden service → Generate vanity .onion domain with mkp224o → Test and secure your deployment. Your web app is now accessible anonymously through the Tor network.