Tor Hidden Services (Onion Services) provide end-to-end encrypted, anonymized web services accessible exclusively through the Tor network. This comprehensive guide covers secure deployment, hardening practices, monitoring strategies, and enterprise operational considerations for running production Hidden Services on Linux systems.

Understanding Tor Hidden Services

Architecture and Security Model

Tor Hidden Services implement a sophisticated cryptographic architecture providing:

Core Security Features

  • End-to-End Encryption: All traffic encrypted between client and service
  • Location Privacy: Server IP addresses remain hidden from clients
  • Censorship Resistance: Accessible even when normal internet connectivity is blocked
  • Authentication: Optional client authentication for restricted access
  • Perfect Forward Secrecy: Session keys prevent historical traffic decryption

Network Architecture

┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│ Tor Client  │────│ Guard Relay │────│Middle Relay │────│ Exit Relay  │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
       │                                                        │
       │            ┌─────────────┐    ┌─────────────┐         │
       └────────────│Intro Point  │────│Rendezvous   │─────────┘
                    │             │    │Point        │
                    └─────────────┘    └─────────────┘
                           │                  │
                           │    ┌─────────────┐
                           └────│Hidden Service│
                                │   Server    │
                                └─────────────┘

Hosting Provider Compliance

  • Most providers allow Hidden Services (non-exit nodes)
  • Exit nodes may violate terms of service
  • Hidden Services generate minimal external traffic
  • No special port forwarding requirements

Traffic Analysis Protection

  • Client traffic appears as 127.0.0.1 in web server logs
  • Host header contains .onion address
  • Request timing patterns may leak information
  • Consider additional anonymization layers

Secure Installation and Configuration

System Preparation and Hardening

Initial System Security

# Update system packages
apt update && apt upgrade -y

# Install essential security tools
apt install -y ufw fail2ban apparmor-utils auditd

# Configure automatic security updates
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

# Enable and configure firewall
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

User and Permission Hardening

# Create dedicated tor service user
useradd --system --home /var/lib/tor --shell /bin/false tor-service

# Set strict permissions on tor directories
chmod 700 /var/lib/tor
chown -R debian-tor:debian-tor /var/lib/tor

# Create dedicated web service user
useradd --system --home /var/www --shell /bin/false www-hidden

# Configure sudo restrictions
cat > /etc/sudoers.d/tor-restrictions << 'EOF'
# Tor service management restrictions
%tor-admin ALL=(root) NOPASSWD: /bin/systemctl restart tor
%tor-admin ALL=(root) NOPASSWD: /bin/systemctl status tor
%tor-admin ALL=(root) NOPASSWD: /bin/systemctl reload tor
EOF

Tor Installation and Configuration

Official Tor Repository Setup

# Install prerequisite packages
apt install -y apt-transport-https gpg software-properties-common curl

# Import Tor Project GPG key with verification
curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | \
    gpg --dearmor -o /usr/share/keyrings/tor-archive-keyring.gpg

# Add Tor Project repository
echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org $(lsb_release -cs) main" > \
    /etc/apt/sources.list.d/tor.list

# Install Tor with verification
apt update
apt install -y tor deb.torproject.org-keyring

# Verify installation
tor --version
systemctl status tor

Advanced Tor Configuration

# Create comprehensive torrc configuration
cat > /etc/tor/torrc << 'EOF'
# Basic configuration
User debian-tor
DataDirectory /var/lib/tor
ControlPort 9051
HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C

# Security enhancements
DisableDebuggerAttachment 1
SafeLogging 1
Log notice file /var/log/tor/notices.log
Log warn file /var/log/tor/warnings.log

# Hidden service configuration
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:8080
HiddenServicePort 443 127.0.0.1:8443

# Advanced security options
HiddenServiceMaxStreams 10
HiddenServiceMaxStreamsCloseCircuit 1
HiddenServiceNumIntroductionPoints 3

# Performance optimization
NumEntryGuards 8
NewCircuitPeriod 30
MaxCircuitDirtiness 600

# Additional security
ExitPolicy reject *:*
PublishServerDescriptor 0
EOF

# Set proper permissions
chmod 644 /etc/tor/torrc
chown root:root /etc/tor/torrc

# Create log directory
mkdir -p /var/log/tor
chown debian-tor:debian-tor /var/log/tor
chmod 750 /var/log/tor

Enhanced Hidden Service Configuration

# Create multiple hidden services for redundancy
cat >> /etc/tor/torrc << 'EOF'
# Primary web service
HiddenServiceDir /var/lib/tor/web_service/
HiddenServicePort 80 127.0.0.1:8080
HiddenServicePort 443 127.0.0.1:8443
HiddenServiceVersion 3

# API service (separate onion address)
HiddenServiceDir /var/lib/tor/api_service/
HiddenServicePort 80 127.0.0.1:8081
HiddenServicePort 443 127.0.0.1:8444
HiddenServiceVersion 3

# Admin interface with client authentication
HiddenServiceDir /var/lib/tor/admin_service/
HiddenServicePort 443 127.0.0.1:8445
HiddenServiceVersion 3
HiddenServiceAuthorizeClient stealth admin_client
EOF

# Restart Tor to generate onion addresses
systemctl restart tor
sleep 10

# Display generated onion addresses
echo "=== Generated Onion Addresses ==="
echo "Web Service:"
cat /var/lib/tor/web_service/hostname
echo "API Service:"
cat /var/lib/tor/api_service/hostname
echo "Admin Service:"
cat /var/lib/tor/admin_service/hostname

Web Server Configuration

Nginx Advanced Configuration

Primary Nginx Configuration

# /etc/nginx/sites-available/hidden-service
server {
    listen 127.0.0.1:8080;
    listen 127.0.0.1:8443 ssl http2;
    
    # Server identification
    server_name your-onion-address.onion;
    
    # SSL configuration for internal encryption
    ssl_certificate /etc/ssl/certs/hidden-service.crt;
    ssl_certificate_key /etc/ssl/private/hidden-service.key;
    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" always;
    
    # Onion-Location header for clearnet sites
    add_header Onion-Location "http://your-onion-address.onion$request_uri" always;
    
    # Root directory and index files
    root /var/www/hidden-service;
    index index.html index.htm index.php;
    
    # Main location block
    location / {
        try_files $uri $uri/ =404;
        
        # Rate limiting for Tor
        limit_req zone=tor_limit burst=10 nodelay;
    }
    
    # API endpoint with additional security
    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
        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;
        
        # API-specific rate limiting
        limit_req zone=api_limit burst=5 nodelay;
    }
    
    # Security-sensitive locations
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    location ~ \.(log|txt|md)$ {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # Logging configuration
    access_log /var/log/nginx/hidden-service-access.log;
    error_log /var/log/nginx/hidden-service-error.log warn;
}

Nginx Rate Limiting and Security

# /etc/nginx/conf.d/tor-security.conf
# Rate limiting zones for Tor traffic
limit_req_zone $binary_remote_addr zone=tor_limit:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/m;

# Connection limiting
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# Map for detecting Tor traffic
map $remote_addr $is_tor {
    default 0;
    "127.0.0.1" 1;
    "0.0.0.0" 1;
}

# Custom log format for Tor
log_format tor_combined '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        'tor=$is_tor onion="$http_host"';

# Security configuration
server_tokens off;
client_max_body_size 1M;
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 5s 5s;
send_timeout 10s;

Apache Configuration

Apache Virtual Host for Hidden Services

# /etc/apache2/sites-available/hidden-service.conf
<VirtualHost 127.0.0.1:8080>
    ServerName your-onion-address.onion
    DocumentRoot /var/www/hidden-service
    
    # Logging
    LogLevel warn
    ErrorLog ${APACHE_LOG_DIR}/hidden-service-error.log
    CustomLog ${APACHE_LOG_DIR}/hidden-service-access.log combined
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Content-Security-Policy "default-src 'self'"
    
    # Onion-Location header
    Header always set Onion-Location "http://your-onion-address.onion%{REQUEST_URI}e"
    
    # Directory security
    <Directory /var/www/hidden-service>
        Options -Indexes -Includes -ExecCGI
        AllowOverride None
        Require all granted
        
        # Rate limiting with mod_evasive
        DOSHashTableSize    4096
        DOSPageCount        3
        DOSPageInterval     1
        DOSSiteCount        50
        DOSSiteInterval     1
        DOSBlockingPeriod   600
    </Directory>
    
    # Deny access to sensitive files
    <FilesMatch "\.(log|txt|md|conf)$">
        Require all denied
    </FilesMatch>
    
    # Hide .htaccess files
    <Files ~ "^\.">
        Require all denied
    </Files>
</VirtualHost>

<VirtualHost 127.0.0.1:8443>
    ServerName your-onion-address.onion
    DocumentRoot /var/www/hidden-service
    
    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/hidden-service.crt
    SSLCertificateKeyFile /etc/ssl/private/hidden-service.key
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder off
    
    # Include same configuration as HTTP vhost
    Include /etc/apache2/sites-available/hidden-service-common.conf
</VirtualHost>

Advanced Security Hardening

Client Authentication

Stealth Authentication Setup

# Generate client authentication keys
cd /var/lib/tor/admin_service
tor --hash-password "admin_secret_password" > auth_password

# Configure client authentication in torrc
cat >> /etc/tor/torrc << 'EOF'
# Client authentication for admin service
HiddenServiceDir /var/lib/tor/admin_service/
HiddenServicePort 443 127.0.0.1:8445
HiddenServiceAuthorizeClient stealth admin_client,backup_admin
EOF

# Client-side authentication configuration
echo "HidServAuth your-admin-onion.onion admin_client_key" >> /etc/tor/torrc

Advanced Authentication with Onion Client Auth v3

#!/usr/bin/env python3
"""
Tor v3 Client Authentication Key Generator
"""

import base64
import nacl.public
import nacl.encoding
import os
from pathlib import Path

class TorClientAuth:
    def __init__(self, service_dir="/var/lib/tor/authenticated_service"):
        self.service_dir = Path(service_dir)
        self.auth_dir = self.service_dir / "authorized_clients"
        
    def generate_client_keypair(self, client_name: str):
        """Generate client authentication keypair"""
        # Generate keypair
        private_key = nacl.public.PrivateKey.generate()
        public_key = private_key.public_key
        
        # Create authorized_clients directory
        self.auth_dir.mkdir(parents=True, exist_ok=True)
        
        # Server-side: public key file
        public_key_b32 = base64.b32encode(
            public_key.encode(encoder=nacl.encoding.RawEncoder)
        ).decode('ascii').strip('=').lower()
        
        auth_file = self.auth_dir / f"{client_name}.auth"
        auth_file.write_text(f"descriptor:x25519:{public_key_b32}")
        
        # Client-side: private key for torrc
        private_key_b32 = base64.b32encode(
            private_key.encode(encoder=nacl.encoding.RawEncoder)
        ).decode('ascii').strip('=').lower()
        
        return {
            'client_name': client_name,
            'private_key': private_key_b32,
            'public_key': public_key_b32,
            'torrc_line': f"ClientOnionAuthDir /etc/tor/onion_auth"
        }
    
    def setup_client_auth_service(self, service_name: str, port: int = 443, target_port: int = 8445):
        """Setup authenticated hidden service"""
        torrc_config = f"""
# Authenticated Hidden Service - {service_name}
HiddenServiceDir {self.service_dir}/
HiddenServicePort {port} 127.0.0.1:{target_port}
HiddenServiceVersion 3
"""
        
        print(f"Add this to /etc/tor/torrc:")
        print(torrc_config)
        
        # Set proper permissions
        os.chmod(self.service_dir, 0o700)
        os.chmod(self.auth_dir, 0o700)
        
        return torrc_config

# Generate client authentication
if __name__ == "__main__":
    auth_manager = TorClientAuth()
    
    # Generate keys for different clients
    clients = ["admin_user", "backup_admin", "monitoring_system"]
    
    for client in clients:
        auth_info = auth_manager.generate_client_keypair(client)
        
        print(f"\n=== Client: {client} ===")
        print(f"Private Key: {auth_info['private_key']}")
        print(f"Public Key: {auth_info['public_key']}")
        print(f"Torrc Config: {auth_info['torrc_line']}")
        
        # Create client-side auth file
        client_auth_dir = Path(f"/etc/tor/onion_auth")
        client_auth_dir.mkdir(parents=True, exist_ok=True)
        
        # Client auth file format for v3
        client_auth_file = client_auth_dir / f"{client}.auth_private"
        client_auth_file.write_text(f"{auth_info['private_key']}")
        os.chmod(client_auth_file, 0o600)

System-Level Security

AppArmor Profile for Tor

# Create AppArmor profile for enhanced Tor security
cat > /etc/apparmor.d/usr.bin.tor << 'EOF'
#include <tunables/global>

/usr/bin/tor {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/openssl>

  capability setuid,
  capability setgid,
  capability sys_resource,

  # Tor executable
  /usr/bin/tor mr,

  # Configuration files
  /etc/tor/ r,
  /etc/tor/** r,
  /usr/share/tor/** r,

  # Data directory
  /var/lib/tor/ rw,
  /var/lib/tor/** rw,

  # Log files
  /var/log/tor/ rw,
  /var/log/tor/** rw,

  # Network access
  network inet stream,
  network inet dgram,

  # Proc filesystem
  @{PROC}/sys/kernel/random/uuid r,
  @{PROC}/sys/net/core/somaxconn r,

  # Deny everything else
  deny /home/** rw,
  deny /root/** rw,
  deny /tmp/** rw,
  deny /var/tmp/** rw,
}
EOF

# Enable AppArmor profile
apparmor_parser -r /etc/apparmor.d/usr.bin.tor
systemctl restart tor

Systemd Security Hardening

# /etc/systemd/system/tor.service.d/security.conf
[Service]
# Security restrictions
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/tor /var/log/tor
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM

# Resource limits
LimitNOFILE=32768
LimitNPROC=64

# User/Group isolation
User=debian-tor
Group=debian-tor
SupplementaryGroups=

# Working directory
WorkingDirectory=/var/lib/tor

Monitoring and Operations

Comprehensive Monitoring System

Tor Metrics Collection

#!/usr/bin/env python3
"""
Tor Hidden Service Monitoring System
"""

import subprocess
import json
import time
import requests
import socket
from datetime import datetime
from pathlib import Path
import logging

class TorMonitor:
    def __init__(self, control_port=9051, control_password=None):
        self.control_port = control_port
        self.control_password = control_password
        self.logger = logging.getLogger(__name__)
        
    def check_tor_service(self):
        """Check if Tor service is running"""
        try:
            result = subprocess.run(['systemctl', 'is-active', 'tor'], 
                                  capture_output=True, text=True)
            return result.stdout.strip() == 'active'
        except Exception as e:
            self.logger.error(f"Failed to check Tor service: {e}")
            return False
    
    def get_hidden_service_status(self, service_dir):
        """Check hidden service status"""
        service_path = Path(service_dir)
        hostname_file = service_path / "hostname"
        
        if not hostname_file.exists():
            return {"status": "not_configured", "onion_address": None}
        
        try:
            onion_address = hostname_file.read_text().strip()
            
            # Test connectivity to hidden service
            connectivity_status = self.test_hidden_service_connectivity(onion_address)
            
            return {
                "status": "active" if connectivity_status else "unreachable",
                "onion_address": onion_address,
                "service_dir": str(service_path),
                "connectivity": connectivity_status
            }
            
        except Exception as e:
            self.logger.error(f"Failed to get hidden service status: {e}")
            return {"status": "error", "error": str(e)}
    
    def test_hidden_service_connectivity(self, onion_address, port=80, timeout=30):
        """Test if hidden service is reachable"""
        try:
            # Use subprocess to test with torify
            result = subprocess.run([
                'timeout', str(timeout), 'torify', 'curl', '-s', '-o', '/dev/null',
                '-w', '%{http_code}', f'http://{onion_address}/'
            ], capture_output=True, text=True, timeout=timeout+5)
            
            http_code = result.stdout.strip()
            return http_code in ['200', '301', '302', '403']
            
        except Exception as e:
            self.logger.warning(f"Connectivity test failed for {onion_address}: {e}")
            return False
    
    def get_tor_metrics(self):
        """Collect comprehensive Tor metrics"""
        metrics = {
            "timestamp": datetime.now().isoformat(),
            "tor_service_active": self.check_tor_service(),
            "hidden_services": {},
            "circuit_info": self.get_circuit_info(),
            "bandwidth_usage": self.get_bandwidth_stats(),
            "log_analysis": self.analyze_tor_logs()
        }
        
        # Check all configured hidden services
        hidden_service_dirs = [
            "/var/lib/tor/web_service",
            "/var/lib/tor/api_service", 
            "/var/lib/tor/admin_service"
        ]
        
        for service_dir in hidden_service_dirs:
            service_name = Path(service_dir).name
            metrics["hidden_services"][service_name] = self.get_hidden_service_status(service_dir)
        
        return metrics
    
    def get_circuit_info(self):
        """Get Tor circuit information via control port"""
        try:
            # Connect to Tor control port
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect(('127.0.0.1', self.control_port))
            
            if self.control_password:
                auth_cmd = f'AUTHENTICATE "{self.control_password}"\r\n'
                sock.send(auth_cmd.encode())
                sock.recv(1024)
            
            # Get circuit information
            sock.send(b'GETINFO circuit-status\r\n')
            response = sock.recv(4096).decode()
            sock.close()
            
            circuits = []
            for line in response.split('\n'):
                if line.startswith('circuit-status='):
                    circuit_data = line.split('=', 1)[1]
                    circuits.append(circuit_data)
            
            return {"circuit_count": len(circuits), "circuits": circuits}
            
        except Exception as e:
            self.logger.error(f"Failed to get circuit info: {e}")
            return {"circuit_count": 0, "error": str(e)}
    
    def get_bandwidth_stats(self):
        """Get bandwidth usage statistics"""
        try:
            # Read from /proc/net/dev for interface statistics
            with open('/proc/net/dev', 'r') as f:
                content = f.read()
            
            # Parse for overall network stats (simplified)
            lines = content.strip().split('\n')[2:]  # Skip headers
            total_rx = 0
            total_tx = 0
            
            for line in lines:
                parts = line.split()
                if len(parts) >= 10:
                    total_rx += int(parts[1])  # RX bytes
                    total_tx += int(parts[9])  # TX bytes
            
            return {
                "total_rx_bytes": total_rx,
                "total_tx_bytes": total_tx,
                "total_bytes": total_rx + total_tx
            }
            
        except Exception as e:
            self.logger.error(f"Failed to get bandwidth stats: {e}")
            return {"error": str(e)}
    
    def analyze_tor_logs(self):
        """Analyze Tor logs for important events"""
        log_analysis = {
            "warnings": 0,
            "errors": 0,
            "circuit_build_failures": 0,
            "hidden_service_events": 0
        }
        
        try:
            # Analyze recent log entries
            log_files = ['/var/log/tor/notices.log', '/var/log/tor/warnings.log']
            
            for log_file in log_files:
                if Path(log_file).exists():
                    with open(log_file, 'r') as f:
                        # Read last 100 lines
                        lines = f.readlines()[-100:]
                        
                        for line in lines:
                            if '[warn]' in line.lower():
                                log_analysis["warnings"] += 1
                            elif '[err]' in line.lower():
                                log_analysis["errors"] += 1
                            elif 'circuit build' in line.lower() and 'failed' in line.lower():
                                log_analysis["circuit_build_failures"] += 1
                            elif 'hidden service' in line.lower():
                                log_analysis["hidden_service_events"] += 1
            
        except Exception as e:
            self.logger.error(f"Failed to analyze logs: {e}")
            log_analysis["error"] = str(e)
        
        return log_analysis
    
    def generate_status_report(self):
        """Generate comprehensive status report"""
        metrics = self.get_tor_metrics()
        
        # Create readable status report
        report = f"""
=== Tor Hidden Service Status Report ===
Generated: {metrics['timestamp']}

Tor Service Status: {'✓ Active' if metrics['tor_service_active'] else '✗ Inactive'}

Hidden Services:
"""
        
        for service_name, service_info in metrics['hidden_services'].items():
            status_icon = "✓" if service_info['status'] == 'active' else "✗"
            report += f"  {status_icon} {service_name}: {service_info['status']}\n"
            if service_info.get('onion_address'):
                report += f"    Address: {service_info['onion_address']}\n"
        
        report += f"""
Circuit Information:
  Active Circuits: {metrics['circuit_info'].get('circuit_count', 'Unknown')}

Bandwidth Usage:
  Total RX: {metrics['bandwidth_usage'].get('total_rx_bytes', 'Unknown')} bytes
  Total TX: {metrics['bandwidth_usage'].get('total_tx_bytes', 'Unknown')} bytes

Log Analysis:
  Warnings: {metrics['log_analysis']['warnings']}
  Errors: {metrics['log_analysis']['errors']}
  Circuit Build Failures: {metrics['log_analysis']['circuit_build_failures']}
  Hidden Service Events: {metrics['log_analysis']['hidden_service_events']}
"""
        
        return report

# Automated monitoring script
if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    
    monitor = TorMonitor()
    
    # Generate and display status report
    status_report = monitor.generate_status_report()
    print(status_report)
    
    # Save metrics to file
    metrics = monitor.get_tor_metrics()
    with open('/var/log/tor/metrics.json', 'w') as f:
        json.dump(metrics, f, indent=2)

Prometheus Integration

#!/usr/bin/env python3
"""
Tor Hidden Service Prometheus Exporter
"""

from prometheus_client import start_http_server, Gauge, Counter, Info
import time
import subprocess
from pathlib import Path

class TorPrometheusExporter:
    def __init__(self, port=9150):
        self.port = port
        
        # Define metrics
        self.tor_service_up = Gauge('tor_service_up', 'Tor service status')
        self.hidden_service_up = Gauge('tor_hidden_service_up', 
                                     'Hidden service status', ['service_name', 'onion_address'])
        self.tor_circuits = Gauge('tor_circuits_total', 'Number of active Tor circuits')
        self.tor_bandwidth_rx = Counter('tor_bandwidth_rx_bytes_total', 'Total RX bandwidth')
        self.tor_bandwidth_tx = Counter('tor_bandwidth_tx_bytes_total', 'Total TX bandwidth')
        self.tor_log_warnings = Counter('tor_log_warnings_total', 'Total log warnings')
        self.tor_log_errors = Counter('tor_log_errors_total', 'Total log errors')
        
        self.tor_info = Info('tor_info', 'Tor service information')
    
    def collect_metrics(self):
        """Collect all Tor metrics"""
        # Tor service status
        tor_active = self.check_tor_service()
        self.tor_service_up.set(1 if tor_active else 0)
        
        # Hidden service status
        self.collect_hidden_service_metrics()
        
        # Tor info
        self.collect_tor_info()
    
    def check_tor_service(self):
        """Check if Tor service is running"""
        try:
            result = subprocess.run(['systemctl', 'is-active', 'tor'], 
                                  capture_output=True, text=True)
            return result.stdout.strip() == 'active'
        except:
            return False
    
    def collect_hidden_service_metrics(self):
        """Collect hidden service metrics"""
        services = {
            'web': '/var/lib/tor/web_service',
            'api': '/var/lib/tor/api_service',
            'admin': '/var/lib/tor/admin_service'
        }
        
        for service_name, service_dir in services.items():
            hostname_file = Path(service_dir) / 'hostname'
            
            if hostname_file.exists():
                try:
                    onion_address = hostname_file.read_text().strip()
                    # Test connectivity (simplified check)
                    is_reachable = self.test_service_reachability(onion_address)
                    
                    self.hidden_service_up.labels(
                        service_name=service_name,
                        onion_address=onion_address
                    ).set(1 if is_reachable else 0)
                    
                except Exception:
                    self.hidden_service_up.labels(
                        service_name=service_name,
                        onion_address='unknown'
                    ).set(0)
    
    def test_service_reachability(self, onion_address):
        """Test if onion service is reachable"""
        try:
            # Simple reachability test
            result = subprocess.run([
                'timeout', '10', 'torify', 'curl', '-s', '-o', '/dev/null',
                '-w', '%{http_code}', f'http://{onion_address}/'
            ], capture_output=True, text=True, timeout=15)
            
            return result.stdout.strip() in ['200', '301', '302', '403']
        except:
            return False
    
    def collect_tor_info(self):
        """Collect Tor version and configuration info"""
        try:
            result = subprocess.run(['tor', '--version'], capture_output=True, text=True)
            version = result.stdout.split('\n')[0] if result.returncode == 0 else 'unknown'
            
            self.tor_info.info({
                'version': version,
                'config_file': '/etc/tor/torrc',
                'data_directory': '/var/lib/tor'
            })
        except:
            pass
    
    def start_server(self):
        """Start Prometheus metrics server"""
        start_http_server(self.port)
        print(f"Tor metrics server started on port {self.port}")
        
        while True:
            self.collect_metrics()
            time.sleep(30)

if __name__ == "__main__":
    exporter = TorPrometheusExporter()
    exporter.start_server()

Automated Backup and Recovery

Configuration Backup System

#!/bin/bash
# Tor Hidden Service Backup and Recovery System

BACKUP_DIR="/backup/tor-services"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30

backup_tor_configuration() {
    echo "Starting Tor configuration backup..."
    
    # Create backup directory
    mkdir -p "$BACKUP_DIR/$DATE"
    
    # Backup Tor configuration
    cp -p /etc/tor/torrc "$BACKUP_DIR/$DATE/"
    
    # Backup hidden service directories (keys and hostnames)
    if [ -d /var/lib/tor ]; then
        tar -czf "$BACKUP_DIR/$DATE/hidden_services.tar.gz" \
            -C /var/lib/tor \
            --exclude='cached-*' \
            --exclude='state' \
            --exclude='lock' \
            .
    fi
    
    # Backup web server configuration
    if [ -d /etc/nginx/sites-available ]; then
        cp -r /etc/nginx/sites-available "$BACKUP_DIR/$DATE/nginx-sites"
    fi
    
    if [ -d /etc/apache2/sites-available ]; then
        cp -r /etc/apache2/sites-available "$BACKUP_DIR/$DATE/apache-sites"
    fi
    
    # Create backup manifest
    cat > "$BACKUP_DIR/$DATE/manifest.txt" << EOF
Tor Hidden Service Backup
Date: $(date)
Hostname: $(hostname)
Tor Version: $(tor --version | head -1)
Backup Contents:
- torrc configuration
- Hidden service keys and hostnames
- Web server configurations
EOF
    
    # Set proper permissions
    chmod -R 600 "$BACKUP_DIR/$DATE"
    
    echo "Backup completed: $BACKUP_DIR/$DATE"
}

restore_tor_configuration() {
    local backup_date="$1"
    local backup_path="$BACKUP_DIR/$backup_date"
    
    if [[ -z "$backup_date" || ! -d "$backup_path" ]]; then
        echo "Usage: restore_tor_configuration <backup_date>"
        echo "Available backups:"
        ls -1 "$BACKUP_DIR" | head -10
        return 1
    fi
    
    echo "Restoring Tor configuration from $backup_date..."
    
    # Stop services
    systemctl stop tor nginx apache2 2>/dev/null
    
    # Restore torrc
    if [ -f "$backup_path/torrc" ]; then
        cp "$backup_path/torrc" /etc/tor/torrc
        echo "Restored torrc configuration"
    fi
    
    # Restore hidden service directories
    if [ -f "$backup_path/hidden_services.tar.gz" ]; then
        cd /var/lib/tor
        tar -xzf "$backup_path/hidden_services.tar.gz"
        chown -R debian-tor:debian-tor /var/lib/tor
        echo "Restored hidden service keys"
    fi
    
    # Restore web server configurations
    if [ -d "$backup_path/nginx-sites" ]; then
        cp -r "$backup_path/nginx-sites"/* /etc/nginx/sites-available/
        echo "Restored Nginx configurations"
    fi
    
    if [ -d "$backup_path/apache-sites" ]; then
        cp -r "$backup_path/apache-sites"/* /etc/apache2/sites-available/
        echo "Restored Apache configurations"
    fi
    
    # Restart services
    systemctl start tor
    sleep 5
    systemctl start nginx apache2 2>/dev/null
    
    echo "Restoration completed from backup: $backup_date"
}

cleanup_old_backups() {
    find "$BACKUP_DIR" -type d -name "20*" -mtime +$RETENTION_DAYS -exec rm -rf {} \;
    echo "Cleaned up backups older than $RETENTION_DAYS days"
}

# Main execution
case "${1:-backup}" in
    backup)
        backup_tor_configuration
        cleanup_old_backups
        ;;
    restore)
        restore_tor_configuration "$2"
        ;;
    cleanup)
        cleanup_old_backups
        ;;
    *)
        echo "Usage: $0 {backup|restore <date>|cleanup}"
        exit 1
        ;;
esac

Enterprise Deployment Considerations

High Availability Architecture

Load Balanced Hidden Services

#!/bin/bash
# Multi-server Hidden Service Load Balancing Setup

setup_ha_hidden_service() {
    local service_name="$1"
    local backend_servers=("$@")
    backend_servers=("${backend_servers[@]:1}")  # Remove first element (service_name)
    
    echo "Setting up HA Hidden Service: $service_name"
    echo "Backend servers: ${backend_servers[*]}"
    
    # Create shared hidden service directory
    mkdir -p "/var/lib/tor/ha_$service_name"
    
    # Generate hidden service configuration
    cat >> /etc/tor/torrc << EOF

# HA Hidden Service - $service_name
HiddenServiceDir /var/lib/tor/ha_$service_name/
HiddenServicePort 80 127.0.0.1:8080
HiddenServicePort 443 127.0.0.1:8443
HiddenServiceVersion 3
HiddenServiceMaxStreams 100
HiddenServiceMaxStreamsCloseCircuit 1
EOF
    
    # Setup HAProxy for load balancing
    cat > "/etc/haproxy/conf.d/$service_name.cfg" << EOF
# HA configuration for $service_name
frontend tor_frontend_$service_name
    bind 127.0.0.1:8080
    bind 127.0.0.1:8443 ssl crt /etc/ssl/certs/hidden-service.pem
    mode http
    default_backend tor_backend_$service_name

backend tor_backend_$service_name
    mode http
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
EOF
    
    # Add backend servers
    local server_id=1
    for server in "${backend_servers[@]}"; do
        echo "    server backend$server_id $server:80 check" >> "/etc/haproxy/conf.d/$service_name.cfg"
        ((server_id++))
    done
    
    # Restart services
    systemctl restart tor haproxy
    
    echo "HA Hidden Service setup completed for $service_name"
}

# Setup monitoring for HA service
setup_ha_monitoring() {
    cat > /usr/local/bin/tor-ha-monitor << 'EOF'
#!/bin/bash
# HA Hidden Service Health Monitor

check_backend_health() {
    local backend="$1"
    local timeout=10
    
    if timeout $timeout curl -s -o /dev/null -w "%{http_code}" "http://$backend/health" | grep -q "200"; then
        return 0
    else
        return 1
    fi
}

monitor_ha_service() {
    local service_name="$1"
    local config_file="/etc/haproxy/conf.d/$service_name.cfg"
    
    if [[ ! -f "$config_file" ]]; then
        echo "Configuration file not found: $config_file"
        return 1
    fi
    
    # Extract backend servers from HAProxy config
    local backends=$(grep "server backend" "$config_file" | awk '{print $3}' | cut -d: -f1)
    
    echo "Monitoring HA service: $service_name"
    
    for backend in $backends; do
        if check_backend_health "$backend"; then
            echo "✓ Backend $backend is healthy"
        else
            echo "✗ Backend $backend is unhealthy"
            # Could trigger alerts here
        fi
    done
}

# Monitor all configured services
for config in /etc/haproxy/conf.d/*.cfg; do
    if [[ -f "$config" ]]; then
        service_name=$(basename "$config" .cfg)
        monitor_ha_service "$service_name"
    fi
done
EOF
    
    chmod +x /usr/local/bin/tor-ha-monitor
    
    # Create systemd timer for monitoring
    cat > /etc/systemd/system/tor-ha-monitor.service << 'EOF'
[Unit]
Description=Tor HA Service Monitor
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/tor-ha-monitor
User=root
EOF
    
    cat > /etc/systemd/system/tor-ha-monitor.timer << 'EOF'
[Unit]
Description=Run Tor HA Monitor every 5 minutes
Requires=tor-ha-monitor.service

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target
EOF
    
    systemctl daemon-reload
    systemctl enable tor-ha-monitor.timer
    systemctl start tor-ha-monitor.timer
}

# Usage example
# setup_ha_hidden_service "webapp" "192.168.1.10" "192.168.1.11" "192.168.1.12"
# setup_ha_monitoring

Container Deployment

Docker Configuration

# Dockerfile for Tor Hidden Service
FROM debian:bullseye-slim

# Install dependencies
RUN apt-get update && apt-get install -y \
    tor \
    nginx \
    curl \
    gpg \
    apt-transport-https \
    && rm -rf /var/lib/apt/lists/*

# Create tor user and directories
RUN useradd --system --home /var/lib/tor --shell /bin/false debian-tor \
    && mkdir -p /var/lib/tor /var/log/tor \
    && chown -R debian-tor:debian-tor /var/lib/tor /var/log/tor \
    && chmod 700 /var/lib/tor

# Copy configurations
COPY torrc /etc/tor/torrc
COPY nginx.conf /etc/nginx/sites-available/default
COPY entrypoint.sh /entrypoint.sh

# Set permissions
RUN chmod +x /entrypoint.sh \
    && chmod 644 /etc/tor/torrc

# Expose ports (internal only)
EXPOSE 8080 8443

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# Run as non-root user
USER debian-tor

ENTRYPOINT ["/entrypoint.sh"]
#!/bin/bash
# entrypoint.sh for Tor Hidden Service container

set -e

# Initialize hidden service directories if they don't exist
if [ ! -f /var/lib/tor/hidden_service/hostname ]; then
    echo "Initializing hidden service..."
    tor --DataDirectory /var/lib/tor --RunAsDaemon 0 --quiet &
    TOR_PID=$!
    
    # Wait for hidden service to be created
    while [ ! -f /var/lib/tor/hidden_service/hostname ]; do
        sleep 1
    done
    
    echo "Hidden service initialized: $(cat /var/lib/tor/hidden_service/hostname)"
    kill $TOR_PID
    wait $TOR_PID 2>/dev/null || true
fi

# Start nginx in background
nginx -g "daemon off;" &
NGINX_PID=$!

# Start tor in foreground
exec tor --DataDirectory /var/lib/tor --RunAsDaemon 0

Kubernetes Deployment

# tor-hidden-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tor-hidden-service
  labels:
    app: tor-hidden-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: tor-hidden-service
  template:
    metadata:
      labels:
        app: tor-hidden-service
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 999
        fsGroup: 999
      containers:
      - name: tor-service
        image: tor-hidden-service:latest
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 8443
          name: https
        env:
        - name: TOR_HIDDEN_SERVICE_DIR
          value: "/var/lib/tor/hidden_service"
        volumeMounts:
        - name: tor-data
          mountPath: /var/lib/tor
        - name: tor-config
          mountPath: /etc/tor/torrc
          subPath: torrc
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
          readOnlyRootFilesystem: true
      volumes:
      - name: tor-data
        persistentVolumeClaim:
          claimName: tor-data-pvc
      - name: tor-config
        configMap:
          name: tor-config
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tor-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: tor-config
data:
  torrc: |
    User debian-tor
    DataDirectory /var/lib/tor
    Log notice file /var/log/tor/notices.log
    
    HiddenServiceDir /var/lib/tor/hidden_service/
    HiddenServicePort 80 127.0.0.1:8080
    HiddenServicePort 443 127.0.0.1:8443
    HiddenServiceVersion 3
    
    DisableDebuggerAttachment 1
    SafeLogging 1
---
apiVersion: v1
kind: Service
metadata:
  name: tor-hidden-service
spec:
  selector:
    app: tor-hidden-service
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: https
    port: 443
    targetPort: 8443
  type: ClusterIP

This comprehensive guide provides enterprise-grade Tor Hidden Service deployment capabilities, ensuring robust security, monitoring, and operational excellence for production environments. The combination of security hardening, automated monitoring, and high availability configurations enables reliable anonymous web services across diverse infrastructure requirements.