A hardened, production-ready Tor relay with built-in diagnostics and monitoring
Quick Start β’ Features β’ Documentation β’ FAQ β’ Architecture β’ Tools β’ Contributing
Tor Guard Relay is a production-ready, self-healing Tor relay container designed for privacy advocates who want to contribute to the Tor network securely and efficiently.
π Multi-Mode: guard, exit, and bridge with obfs4 transport. Configure via
TOR_RELAY_MODE.
- π‘οΈ Security-First - Hardened Alpine Linux, non-root operation
- πͺΆ Very light - Ultra-minimal 16.8 MB image
- π― Simple - One command to deploy, minimal configuration needed
- π Observable - 5 busybox-only diagnostic tools with JSON health API
- π Multi-Mode - Supports guard, exit, and bridge (obfs4) relays
- π Automated - Weekly security rebuilds, CI/CD ready
- π Documented - Comprehensive guides for deployment, monitoring, backup, and more
- ποΈ Multi-Arch - Native support for AMD64 and ARM64 (Raspberry Pi, AWS Graviton, etc.)
Port Exposure Policy
- 9001 ORPort, public
- 9030 DirPort, public for guard and exit
- 9002 obfs4 for bridge mode
Environment Variables
TOR_ORPORTdefault 9001TOR_DIRPORTdefault 9030TOR_OBFS4_PORTdefault 9002
Diagnostics are run only through docker exec, with no exposed monitoring ports.
Minimal surface area, roughly 16.8 MB.
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 1 core | 2+ cores |
| RAM | 512 MB | 1 GB+ |
| Disk | 10 GB | 20 GB+ SSD |
| Bandwidth | 10 Mbps | 100+ Mbps |
| Uptime | 95 percent | 99 percent |
| Docker | 20.10+ | Latest |
Supported Architectures: AMD64, ARM64
- Guard/Middle/Exit: Ports 9001 (ORPort) and 9030 (DirPort) should be publicly accessible
- Bridge: Ports 9001 (ORPort) and 9002 (obfs4) should be publicly accessible
- No monitoring ports - all diagnostics via
docker execcommands only - Use
--network hostfor best IPv6 support (Tor recommended practice)
π Try our interactive setup script:
# Download and run the quick-start script
curl -fsSL https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/scripts/quick-start.sh -o quick-start.sh
chmod +x quick-start.sh
sh ./quick-start.shThe script will:
- β Guide you through relay type selection (guard, exit, bridge)
- β Collect required information with validation
- β Generate deployment commands or docker-compose.yml
- β Provide next steps and monitoring guidance
Step 1: Create your relay configuration (or use our example):
mkdir -p ~/tor-relay && cd ~/tor-relay
curl -o relay.conf https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/refs/heads/main/examples/relay-guard.conf
nano relay.confdocker run -d \
--name tor-relay \
--restart unless-stopped \
--network host \
--security-opt no-new-privileges:true \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
r3bo0tbx1/onion-relay:latest# Check status
docker exec tor-relay status
# View fingerprint
docker exec tor-relay fingerprint
# Stream logs
docker logs -f tor-relayThat's it! Your relay will bootstrap in 10-30 minutes and appear on Tor Metrics within 1-2 hours.
π Need more? See our comprehensive Deployment Guide for Docker Compose, Cosmos Cloud, Portainer, and advanced setups.
We offer two build variants to match your risk tolerance and requirements:
Base: Alpine 3.23.0 | Recommended for: Production relays
- β Battle-tested Alpine stable release
- β Weekly automated rebuilds with latest security patches
- β Proven stability for long-running relays
- β Available on both Docker Hub and GHCR
# Pull from Docker Hub (easiest)
docker pull r3bo0tbx1/onion-relay:latest
docker pull r3bo0tbx1/onion-relay:1.1.3
# Pull from GHCR
docker pull ghcr.io/r3bo0tbx1/onion-relay:latest
docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.3Base: Alpine edge | Recommended for: Testing, security research
- β‘ Bleeding-edge Alpine packages (faster security updates)
- β‘ Latest Tor and obfs4 versions as soon as available
- β‘ More frequent rebuilds - Every 3 days + weekly (~2-3x faster updates than stable)
β οΈ NOT recommended for production - less stable, potential breaking changes- π¦ Available on both Docker Hub and GHCR
# Pull from Docker Hub
docker pull r3bo0tbx1/onion-relay:edge
# Pull from GHCR
docker pull ghcr.io/r3bo0tbx1/onion-relay:edge
docker pull ghcr.io/r3bo0tbx1/onion-relay:1.1.3-edgeWhen to use edge:
- π¬ Testing new Tor features before stable release
- π‘οΈ Security research requiring latest packages
- π§ͺ Non-production test environments
- π Early adopters willing to accept potential breakage
Stability comparison:
| Feature | Stable | Edge |
|---|---|---|
| Production ready | β Yes | β No |
| Breaking changes | β Rare | |
| Security updates | Weekly | Weekly (newer packages) |
| Package versions | Proven | Bleeding edge |
| Docker Hub | β Yes | β Yes |
| GHCR | β Yes | β Yes |
π‘ Our recommendation: Use stable for production relays, edge only for testing or when you specifically need the latest package versions.
Choose the method that fits your workflow.
| Method | Best For | Guide |
|---|---|---|
| π³ Docker CLI | Quick testing | Guide |
| π¦ Docker Compose | Production | Guide |
| βοΈ Cosmos Cloud | UI based deployment | Guide |
| ποΈ Portainer | Web UI | Guide |
New to Docker? Try Cosmos Cloud by azukaar - a gorgeous, self-hosted Docker management platform.
Running multiple relays? We have templates for that:
- Docker Compose: docker-compose-multi-relay.yml - 3 relays setup
- Cosmos Cloud: cosmos-compose-multi-relay.json - Multi-relay stack
See Deployment Guide for complete instructions.
Version >=v1.1.1 includes five busybox-only tools.
| Tool | Purpose | Usage |
|---|---|---|
| status | Full health report | docker exec tor-relay status |
| health | JSON health | docker exec tor-relay health |
| fingerprint | Show fingerprint | docker exec tor-relay fingerprint |
| bridge-line | obfs4 line | docker exec tor-relay bridge-line |
| gen-auth | Credentials for Nyx | docker exec tor-relay gen-auth |
# Full health report with emojis
docker exec tor-relay status
# JSON output for automation/monitoring
docker exec tor-relay healthExample JSON:
{
"status": "healthy",
"bootstrap": 100,
"reachable": true,
"fingerprint": "1234567890ABCDEF",
"nickname": "MyRelay",
"uptime_seconds": 3600
}π Complete reference: See Tools Documentation for all 5 tools with examples, JSON schema, and integration guides.
>=v1.1.2 supports both real-time CLI monitoring and external observability for minimal image size and maximum security.
You can connect Nyx (formerly arm) to your relay securely using the Control Port.
- Generate credentials: docker exec tor-relay gen-auth
- Add the hash to your config.
- Connect via local socket or TCP.
π Full Setup: See the Control Port Guide for step-by-step Nyx configuration.
The health tool provides JSON output for monitoring integration:
# Get health status (raw JSON)
docker exec tor-relay health
# Parse with jq (requires jq installed on HOST machine)
docker exec tor-relay health | jq .
# Example cron-based monitoring
*/5 * * * * docker exec tor-relay health | jq '.status' | grep -q 'healthy' || alertNote:
jqmust be installed on your HOST machine (apt install jq/brew install jq), NOT in the container.
Prometheus Node Exporter:
# Use textfile collector (requires jq on host)
docker exec tor-relay health | jq -r '
"tor_bootstrap_percent \(.bootstrap)",
"tor_reachable \(if .reachable then 1 else 0 end)"
' > /var/lib/node_exporter/tor.promNagios/Icinga:
#!/bin/bash
# Requires jq on host machine
HEALTH=$(docker exec tor-relay health)
STATUS=$(echo "$HEALTH" | jq -r '.status')
[ "$STATUS" = "healthy" ] && exit 0 || exit 2π Complete guide: See Monitoring Documentation for Prometheus, Grafana, alert integration, and observability setup.
- β
Non-root execution (runs as
toruser) - β Ultra-minimal Alpine Linux base (~16.8 MB)
- β Busybox-only tools (no bash/python dependencies)
- β Automatic permission healing on startup
- β Configuration validation before start
- β Tini init for proper signal handling
- β Graceful shutdown with cleanup
- β 5 busybox-only diagnostic tools (status, health, fingerprint, bridge-line, gen-auth)
- β JSON health API for monitoring integration
- β Multi-mode support (guard, exit, bridge with obfs4)
- β ENV-based config (TOR_RELAY_MODE, TOR_NICKNAME, etc.)
- β Multi-architecture builds (AMD64, ARM64)
- β Weekly security rebuilds via GitHub Actions
- β Docker Compose templates for single/multi-relay
- β Cosmos Cloud support with one-click deploy
- β Comprehensive documentation (8 guides)
- β Example configurations included
- β GitHub issue templates
- β Automated dependency updates (Dependabot)
- β CI/CD validation and testing
- β Multi-arch support (same command, any platform)
| Cosmos Cloud Dashboard | Docker Logs (Bootstrapping) |
|---|---|
![]() |
![]() |
| Relay Status Tool | Obfs4 Bridge Line |
![]() |
![]() |
>=v1.1.1 includes comprehensive documentation organized by topic:
- FAQ - β NEW! Frequently asked questions with factual answers
- Quick Start Script - β NEW! Interactive relay deployment wizard
- Migration Assistant - β NEW! Automated migration from thetorproject/obfs4-bridge
- Deployment Guide - β¨ UPDATED! Complete installation for Docker CLI, Compose, Cosmos Cloud, and Portainer
- Migration Guide - Upgrade to >=v1.1.1 or migrate from other Tor setups
- Architecture - β NEW! Technical architecture with Mermaid diagrams
- Tools Reference - β¨ UPDATED! Complete guide to all 5 diagnostic tools
- Monitoring Guide - β¨ UPDATED! External monitoring integration, JSON health API, alerts, and observability
- Control Port Guide - β NEW! Authentication setup and Nyx integration
- Backup Guide - Data persistence, recovery, and disaster planning
- Performance Guide - Optimization, tuning, and resource management
- Legal Considerations - β¨ UPDATED! Legal aspects of running a Tor relay
- Documentation Index - Complete documentation navigation
- Security Policy - Security practices and vulnerability reporting
- Contributing Guide - How to contribute to the project
- Code of Conduct - Community guidelines
- Changelog - Version history and changes
π‘ Tip: Start with the FAQ for quick answers or Documentation Index for complete navigation.
Nickname MyTorRelay
ContactInfo your-email@example.com
ORPort 9001
ORPort [::]:9001
DirPort 9030
ExitRelay 0
SocksPort 0
DataDirectory /var/lib/tor
Log notice file /var/log/tor/notices.logRelayBandwidthRate 50 MBytes
RelayBandwidthBurst 100 MBytes
NumCPUs 2
MaxMemInQueues 512 MB
ORPort [::]:9001Examples are found in the examples/ directory for complete, annotated configuration files:
- relay-guard.conf - Recommended production config
- Additional examples for specific use cases
π Configuration help: See Deployment Guide for complete reference.
# Quick status
docker exec tor-relay status
# JSON output for automation (raw)
docker exec tor-relay health
# Parse specific field with jq (requires jq on host)
docker exec tor-relay health | jq .bootstrap
```r exec tor-relay health | jq .bootstrapAfter 1-2 hours, find your relay:
Search by:
- Nickname (e.g., "MyTorRelay")
- Fingerprint (get with
docker exec tor-relay fingerprint) - IP address
| Milestone | Time | What to Expect |
|---|---|---|
| Bootstrap Complete | 10-30 min | Logs show "Bootstrapped 100%" |
| Appears on Metrics | 1-2 hours | Relay visible in search |
| First Statistics | 24-48 hours | Bandwidth graphs appear |
| Guard Flag | 8+ days | Trusted for entry connections |
π Detailed monitoring: See Monitoring Guide for complete observability setup with Prometheus and Grafana.
# Check overall status
docker exec tor-relay status
# Check JSON health (raw)
docker exec tor-relay health
# View fingerprint
docker exec tor-relay fingerprint
# For bridge mode: Get bridge line
docker exec tor-relay bridge-line
# Generate Control Port hash
docker exec tor-relay gen-auth| Problem | Quick Fix |
|---|---|
| Container won't start | Check logs: docker logs tor-relay |
| ORPort not reachable | Verify firewall: sudo ufw allow 9001/tcp |
| Not on Tor Metrics | Wait 24h, verify bootstrap complete |
| Low/no traffic | Normal for new relays (2-8 weeks to build reputation) |
π Full troubleshooting: See Tools Documentation for detailed diagnostic procedures.
π NEW: See the complete Architecture Documentation for detailed technical design with Mermaid diagrams covering:
- Container lifecycle and initialization flow (6 phases)
- ENV compatibility layer and configuration priority
- Config generation for guard/exit/bridge modes
- OBFS4V security validation (v1.1.1 fix)
- Diagnostic tools architecture
- Signal handling and graceful shutdown
flowchart TB
Start([π³ docker run]) --> Init
subgraph Init["βοΈ INITIALIZATION"]
direction TB
Check{"π Config File
at /etc/tor/torrc?"}
Check -->|β
Mounted| Mount["π Use Mounted Config
Full Tor Control"]
Check -->|β No File| Env{"π ENV Variables?
NICKNAME + CONTACT_INFO"}
Env -->|β
Set| Generate["βοΈ Auto-Generate torrc
from ENV Variables"]
Env -->|β Missing| Error["β ERROR
No Configuration Found"]
Mount --> Validate
Generate --> Validate
Validate["π§ͺ Validate Config
tor --verify-config"]
Validate -->|β Invalid| Error
end
Init -->|β
Valid Config| ModeSelect
subgraph ModeSelect["π― RELAY MODE SELECTION"]
direction LR
Mode{TOR_RELAY_MODE}
Mode -->|guard| Guard["π‘οΈ GUARD/MIDDLE
ββββββββββ
Routes Traffic
ExitRelay 0
DirPort Enabled"]
Mode -->|exit| Exit["πͺ EXIT RELAY
ββββββββββ
Last Hop to Internet
ExitRelay 1
Custom Exit Policy"]
Mode -->|bridge| Bridge["π BRIDGE + obfs4
ββββββββββ
Censorship Resistant
BridgeRelay 1
Lyrebird Transport"]
end
Guard --> Running
Exit --> Running
Bridge --> Running
Running(["π’ TOR RELAY RUNNING"])
Running --> Ops
subgraph Ops["π οΈ OPERATIONS"]
direction TB
Tools["π§ Diagnostic Tools
via docker exec"]
Tools --> Status["π status
ββββββββββ
Full Health Report
Bootstrap Progress
Reachability Status"]
Tools --> Health["π health
ββββββββββ
JSON Health API
For Monitoring Systems"]
Tools --> Finger["π fingerprint
ββββββββββ
Show Relay Identity
Tor Metrics URL"]
Tools --> BLine["π bridge-line
ββββββββββ
Get obfs4 Bridge Line
Share with Users"]
Tools --> GenAuth["π gen-auth
ββββββββββ
Generate Control
Port Auth Data"]
end
Running -->|docker stop SIGTERM| Shutdown
subgraph Shutdown["π§Ή GRACEFUL SHUTDOWN"]
direction TB
Graceful["Close Circuits Cleanly
Notify Directory Authorities
Save State to Disk
Exit Gracefully"]
end
Error --> End([β Container Exits])
Graceful --> End2([β
Clean Stop])
style Start fill:#4FC3F7,stroke:#0288D1,stroke-width:3px,color:#000
style Running fill:#66BB6A,stroke:#388E3C,stroke-width:3px,color:#fff
style Mount fill:#81C784,stroke:#388E3C,stroke-width:2px,color:#000
style Generate fill:#81C784,stroke:#388E3C,stroke-width:2px,color:#000
style Validate fill:#FFD54F,stroke:#F57C00,stroke-width:2px,color:#000
style Error fill:#E57373,stroke:#C62828,stroke-width:3px,color:#fff
style Guard fill:#64B5F6,stroke:#1976D2,stroke-width:2px,color:#000
style Exit fill:#F06292,stroke:#C2185B,stroke-width:2px,color:#fff
style Bridge fill:#BA68C8,stroke:#7B1FA2,stroke-width:2px,color:#fff
style Status fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000
style Health fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000
style Finger fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000
style BLine fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000
style GenAuth fill:#4DD0E1,stroke:#0097A7,stroke-width:2px,color:#000
style Graceful fill:#FFB74D,stroke:#F57C00,stroke-width:2px,color:#000
style End fill:#E57373,stroke:#C62828,stroke-width:2px,color:#fff
style End2 fill:#66BB6A,stroke:#388E3C,stroke-width:2px,color:#fff
style Init fill:#FFF9C4,stroke:#F9A825,stroke-width:2px
style ModeSelect fill:#E1BEE7,stroke:#8E24AA,stroke-width:2px
style Ops fill:#B2EBF2,stroke:#00ACC1,stroke-width:2px
style Shutdown fill:#FFCCBC,stroke:#E64A19,stroke-width:2px
This project uses --network host for important reasons:
- β IPv6 Support - Direct access to host's IPv6 stack
- β No NAT - Tor binds directly to ports without translation
- β Better Performance - Eliminates network overhead
- β Tor Recommended - Follows Tor Project best practices
Security: The container still runs as non-root with restricted permissions. Host networking is standard for Tor relays.
Docker automatically pulls the correct architecture:
# Same command works on:
# - x86_64 servers (pulls amd64)
# - Raspberry Pi (pulls arm64)
# - AWS Graviton (pulls arm64)
docker pull r3bo0tbx1/onion-relay:latestVerify what you got:
docker exec tor-relay cat /build-info.txt | grep ArchitectureContributions are welcome.
- π Report bugs via GitHub Issues
- π‘ Suggest features or improvements
- π Improve documentation (typos, clarity, examples)
- π§ Submit pull requests (code, configs, workflows)
- β Star the repository to show support
- π§ Run a relay and strengthen the network!
# Clone repository
git clone https://github.com/r3bo0tbx1/tor-guard-relay.git
cd tor-guard-relay
# Build locally
docker build -t tor-relay:dev .
# Test
docker run --rm tor-relay:dev statusSee Contributing Guide for detailed instructions.
All templates are in the templates/ directory:
- docker-compose.yml - Single relay
- docker-compose-multi-relay.yml - 3 relays + monitoring
- cosmos-compose.json - Single relay
- cosmos-compose-multi-relay.json - Multi-relay stack
See Monitoring Guide for external monitoring integration examples with Prometheus, Nagios, and other tools
See examples/ directory for relay configurations.
β
Store relay.conf with restricted permissions (chmod 600)
β
Never commit configs with sensitive info to Git
β
Use PGP key in ContactInfo for verification
β
Regularly update Docker image for security patches
β
Monitor logs for suspicious activity
β
Configure firewall properly
Found a vulnerability? See our Security Policy for responsible disclosure.
Images are automatically rebuilt on separate schedules to include security patches:
Stable Variant (:latest)
- Schedule: Every Sunday at 18:30 UTC
- Includes: Latest Tor + Alpine 3.23.0 updates
- Strategy: Overwrites last release version (e.g.,
:1.1.3) with updated packages - Tags Updated:
:latestand version tags (e.g.,:1.1.3)
Edge Variant (:edge)
- Schedule: Every 3 days at 12:00 UTC (independent schedule)
- Includes: Latest Tor + Alpine edge (bleeding-edge) updates
- Strategy: Overwrites last release version (e.g.,
:1.1.3-edge) with updated packages - Tags Updated:
:edgeand version tags (e.g.,:1.1.3-edge) - Frequency: ~2-3x more frequent updates than stable
All images auto-published to Docker Hub and GitHub Container Registry
- π Relay Setup Guide
- π¬ Relay Operators Forum
- π§ Mailing List
- π Tor Metrics
- π Documentation
- π Issue Tracker
- π¬ Discussions
- π¦ Container Registry
Current Version: v1.1.3 β’ Status: Production Ready
Image Size: 16.8 MB β’ Rebuild: Weekly
Registries: Docker Hub β’ GHCR
Project is licensed under the MIT License.
See License for full details.
- The Tor Project for maintaining the global privacy network
- Alpine Linux for a minimal and secure base image
- azukaar for Cosmos Cloud
- All relay operators supporting privacy and anti-censorship worldwide
This project is open source. Your support helps sustainability and improvements.
bc1qltkajaswmzx9jwets8hfz43nkvred5w92syyq4
Or via AnonPay (convert any crypto)
45mNg5cG1S2B2C5dndJP65SSEXseHFVqFdv1N6paAraD1Jk9kQxQQArVcjfQmgCcmthrUF3jbNs74c5AbWqMwAAgAjDYzrZ
Or via AnonPay (convert any crypto)
- β Star the repo
- π Report bugs
- π‘ Suggest features
- π Improve documentation
- π€ Submit patches
- π§ Run a relay
Protecting privacy, one relay at a time ππ§ β¨
β Star this repo if you find it useful!
π Support Internet Freedom
π Documentation
β¬ Back to top




