v1.1.1 Security Hardening & Config Enhancement 🛡️

🚀 Major architectural release with a near full rewrite of the entrypoint, validation system, diagnostics, and templates. The image is now ~20MB, fully busybox based, more secure, and more flexible for relay and bridge operators.

🔧 Critical Fixes
- Busybox compatible rewrite of OBFS4V_* parsing for values with spaces.
- Rewritten TOR_CONTACT_INFO validation to prevent crash loops.
- Restored bootstrap logs with Log notice stdout.
- Fixed ENV healthchecks and validation order.
- Resolved busybox regex and quoting issues across the script.

 Features and Enhancements
- Added PT_PORT with complete obfs4 bridge compatibility.
- Support for OR_PORT, PT_PORT, EMAIL, and NICKNAME.
- Rewritten bandwidth logic with correct Rate and Burst translation.
- Unified guard, exit, and bridge via TOR_RELAY_MODE.
- Integrated obfs4 with rewritten diagnostics for status, health, fingerprint, and bridge-line.
- Reliable ENV only mode without torrc files.

📦 Build Improvements
- Image reduced ~45MB to ~20MB with busybox only tools.
- Rewritten healthcheck for ENV and mounted configs.
- Four diagnostic tools rewritten to pure busybox sh.
- Weekly rebuilds with latest Alpine and Tor.

📚 Templates and Documentation
- All templates rewritten and updated with bandwidth options and naming alternatives.
- Updated Cosmos and Docker Compose templates for bridge, guard, exit.
- New templates README with full deployment, migration, and config comparisons.
- Revised Claude file with clearer differences and bandwidth notes.

🔒 Security Hardening
- 32 vulnerabilities fixed across critical, high, medium, low categories.
- Non root runtime with UID 100.
- Strict OBFS4V_* whitelist and rewritten validation.
- No exposed diagnostics ports, docker exec only.
- Smaller attack surface with removed binaries.

🚀 Migration Notes
- From v1.1.0: direct upgrade, no config changes, fingerprint preserved.
- From official obfs4 bridge: one time UID fix required, full ENV compatibility afterward.
- Templates include both TOR_ and official naming for smooth migration.

🧩 Compatibility
- Alpine 3.22.2 base, latest Tor from edge.
- AMD64 and ARM64 supported.
- Works with Docker, Compose, Cosmos Cloud, Portainer.
This commit is contained in:
rE-Bo0t.bx1
2025-11-14 02:08:27 +08:00
parent 384d6ed669
commit 9ed70bdb89
74 changed files with 10345 additions and 7440 deletions

View File

@@ -1,6 +1,6 @@
# 🚀 Deployment Guide - Tor Guard Relay v1.1
# 🚀 Deployment Guide - Tor Guard Relay v1.1.1
Complete deployment instructions for various hosting environments.
Complete deployment instructions for guard, exit, and bridge relays across various hosting environments.
---
@@ -11,6 +11,8 @@ Complete deployment instructions for various hosting environments.
- [Method 2: Docker Compose](#method-2-docker-compose)
- [Method 3: Cosmos Cloud](#method-3-cosmos-cloud)
- [Method 4: Portainer](#method-4-portainer)
- [Multi-Mode Deployment](#multi-mode-deployment)
- [ENV-Based Deployment](#env-based-deployment)
- [Post-Deployment Verification](#post-deployment-verification)
- [Firewall Configuration](#firewall-configuration)
- [Hosting Provider Recommendations](#hosting-provider-recommendations)
@@ -25,8 +27,8 @@ Before deploying, ensure you have:
-**Root or sudo access** on your server
-**Static public IP address**
-**Sufficient bandwidth** (10+ Mbps recommended)
-**Open firewall ports** (9001/tcp at minimum)
-**Prepared configuration file** (`relay.conf`)
-**Open firewall ports** (9001/tcp minimum, 9030/tcp recommended for guard/exit, 9002/tcp for bridges)
-**Prepared configuration** (config file OR environment variables)
---
@@ -43,34 +45,38 @@ Create `relay.conf` file:
mkdir -p ~/tor-relay
cd ~/tor-relay
# Download example config
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/examples/relay.conf
# Download example config (guard relay)
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/examples/relay-guard.conf
# edit
nano relay.conf
# Edit configuration
nano relay-guard.conf
```
**Minimum required edits:**
- `Nickname` - Your relay name
- `ContactInfo` - Your email
- `ORPort` - Usually 9001
- `ORPort` - Usually 9001 or 443
- `RelayBandwidthRate` - Your bandwidth limit
### Step 2: Pull the Image
```bash
# From GitHub Container Registry (recommended)
docker pull ghcr.io/r3bo0tbx1/onion-relay:latest
# Or from Docker Hub
docker pull r3bo0tbx1/onion-relay:latest
```
### Step 3: Run the Container
```bash
docker run -d \
--name guard-relay \
--name tor-relay \
--network host \
-v ~/tor-relay/relay.conf:/etc/tor/torrc:ro \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
-v ~/tor-relay/relay-guard.conf:/etc/tor/torrc:ro \
-v tor-data:/var/lib/tor \
-v tor-logs:/var/log/tor \
--restart unless-stopped \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
@@ -79,13 +85,15 @@ docker run -d \
```bash
# Check container is running
docker ps | grep guard-relay
docker ps | grep tor-relay
# Check logs
docker logs -f guard-relay
# Check logs and bootstrap progress
docker logs -f tor-relay
# Run diagnostics
docker exec guard-relay relay-status
# Run diagnostics (4 tools available)
docker exec tor-relay status # Full health report with emojis
docker exec tor-relay health # JSON health data
docker exec tor-relay fingerprint # Show fingerprint + Tor Metrics URL
```
---
@@ -104,11 +112,11 @@ cd ~/tor-relay
### Step 2: Download Files
```bash
# Download docker-compose.yml
# Download docker-compose.yml (guard relay with mounted config)
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/docker-compose.yml
# Download example config
curl -o relay.conf https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/examples/relay.conf
curl -o relay.conf https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/examples/relay-guard.conf
```
### Step 3: Edit Configuration
@@ -132,7 +140,7 @@ docker-compose up -d
docker-compose logs -f
# Check status
docker-compose exec tor-guard-relay relay-status
docker-compose exec tor-relay status
```
### Step 5: Manage Deployment
@@ -158,8 +166,8 @@ docker-compose stats
Perfect for users with [Cosmos Cloud](https://cosmos-cloud.io/) - a modern Docker management interface.
> **About Cosmos Cloud**: Created by [azukaar](https://github.com/azukaar), Cosmos Cloud is a self-hosted platform for managing Docker containers with a beautiful UI, automatic HTTPS, integrated auth, and smart automation features. It's like Portainer meets Traefik meets simplicity.
>
> **About Cosmos Cloud**: Created by [azukaar](https://github.com/azukaar), Cosmos Cloud is a self-hosted platform for managing Docker containers with a beautiful UI, automatic HTTPS, integrated auth, and smart automation features.
>
> - 🌐 **Website**: https://cosmos-cloud.io/
> - 📦 **GitHub**: https://github.com/azukaar/Cosmos-Server
> - 📖 **Docs**: https://cosmos-cloud.io/doc
@@ -181,7 +189,7 @@ sudo mkdir -p /opt/tor-relay
sudo nano /opt/tor-relay/relay.conf
```
Paste your relay configuration (see [example config](../examples/relay.conf)).
Paste your relay configuration (see [example config](../examples/relay-guard.conf)).
**Important**: Edit at minimum:
- `Nickname` - Your relay name
@@ -199,15 +207,15 @@ sudo chmod 600 /opt/tor-relay/relay.conf
2. Navigate to **ServApps****Import Compose File**
3. Download our Cosmos configuration:
```bash
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/cosmos-compose.json
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/cosmos-compose-guard.json
```
4. Upload or paste the JSON content
5. **Optional**: Edit timezone if needed (default: `Asia/Tokyo`)
5. **Optional**: Edit timezone if needed (default: `UTC`)
```json
"TZ=Asia/Tokyo" // Change to your timezone
"TZ=UTC" // Universal (default)
"TZ=America/New_York" // US East Coast
"TZ=Europe/London" // UK
"TZ=UTC" // Universal
"TZ=Asia/Tokyo" // Japan
```
### Step 3: Deploy
@@ -215,7 +223,7 @@ sudo chmod 600 /opt/tor-relay/relay.conf
1. Review the configuration
2. Click **Create**
3. Wait for container to start
4. Navigate to **ServApps** → **TorGuardRelay**
4. Navigate to **ServApps** → **TorRelay**
5. Click **Logs** to monitor bootstrap progress
### Step 4: Verify Deployment
@@ -223,7 +231,7 @@ sudo chmod 600 /opt/tor-relay/relay.conf
From Cosmos UI, click **Console** (or use SSH):
```bash
docker exec TorGuardRelay relay-status
docker exec tor-relay status
```
Look for:
@@ -257,8 +265,6 @@ Cosmos will:
- 📧 Notify you when updates are available
- 🔁 Automatically restart with new version
You can also manually trigger updates from the Cosmos UI.
---
## Method 4: Portainer
@@ -272,7 +278,7 @@ Navigate to your Portainer instance (usually `https://your-server:9443`)
### Step 2: Create Stack
1. Click **Stacks** → **Add Stack**
2. Name it: `tor-guard-relay`
2. Name it: `tor-relay`
3. Choose **Web editor**
### Step 3: Paste Stack Definition
@@ -281,9 +287,9 @@ Navigate to your Portainer instance (usually `https://your-server:9443`)
version: '3.8'
services:
tor-guard-relay:
tor-relay:
image: ghcr.io/r3bo0tbx1/onion-relay:latest
container_name: guard-relay
container_name: tor-relay
restart: unless-stopped
network_mode: host
volumes:
@@ -298,16 +304,193 @@ volumes:
### Step 4: Upload Configuration
1. Click **Volumes** → **Add Volume**
2. Name: `tor-config`
3. Use **File Upload** to upload your `relay.conf`
1. SSH to your server and create config:
```bash
sudo mkdir -p /opt/tor-relay
sudo nano /opt/tor-relay/relay.conf
```
2. Paste your relay configuration and save
### Step 5: Deploy
1. Click **Deploy the stack**
2. Navigate to **Containers** → `guard-relay`
2. Navigate to **Containers** → `tor-relay`
3. Click **Logs** to monitor
4. Click **Console** → Connect to run diagnostics
4. Click **Console** → Connect to run diagnostics:
```bash
status
health
fingerprint
```
---
## Multi-Mode Deployment
v1.1.1 supports **guard**, **exit**, and **bridge** relays in a single container.
### Guard/Middle Relay (Default)
```bash
# With mounted config
docker run -d \
--name tor-guard \
--network host \
-v ~/relay-guard.conf:/etc/tor/torrc:ro \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
# With ENV variables
docker run -d \
--name tor-guard \
--network host \
-e TOR_RELAY_MODE=guard \
-e TOR_NICKNAME=MyGuardRelay \
-e TOR_CONTACT_INFO=tor@example.com \
-e TOR_ORPORT=9001 \
-e TOR_DIRPORT=9030 \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
### Exit Relay
```bash
# With mounted config (recommended for exits)
docker run -d \
--name tor-exit \
--network host \
-v ~/relay-exit.conf:/etc/tor/torrc:ro \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
# With ENV variables
docker run -d \
--name tor-exit \
--network host \
-e TOR_RELAY_MODE=exit \
-e TOR_NICKNAME=MyExitRelay \
-e TOR_CONTACT_INFO=tor@example.com \
-e TOR_ORPORT=9001 \
-e TOR_DIRPORT=9030 \
-e TOR_EXIT_POLICY="accept *:80,accept *:443,reject *:*" \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
### Bridge Relay (obfs4)
```bash
# With mounted config
docker run -d \
--name tor-bridge \
--network host \
-v ~/relay-bridge.conf:/etc/tor/torrc:ro \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
# With ENV variables
docker run -d \
--name tor-bridge \
--network host \
-e TOR_RELAY_MODE=bridge \
-e TOR_NICKNAME=MyBridge \
-e TOR_CONTACT_INFO=tor@example.com \
-e TOR_ORPORT=9001 \
-e TOR_OBFS4_PORT=9002 \
-v tor-data:/var/lib/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
# Get bridge line for sharing
docker exec tor-bridge bridge-line
```
**Templates:**
- Guard: [docker-compose-guard-env.yml](../templates/docker-compose-guard-env.yml)
- Exit: [docker-compose-exit.yml](../templates/docker-compose-exit.yml)
- Bridge: [docker-compose-bridge.yml](../templates/docker-compose-bridge.yml)
---
## ENV-Based Deployment
v1.1.1 supports full configuration via environment variables (no config file needed).
### Supported Environment Variables
#### Core Configuration
- `TOR_RELAY_MODE` - guard, exit, or bridge (default: guard)
- `TOR_NICKNAME` - Relay nickname (required for ENV config)
- `TOR_CONTACT_INFO` - Contact email (required for ENV config)
- `TOR_ORPORT` - ORPort (default: 9001)
- `TOR_DIRPORT` - DirPort for guard/exit (default: 9030, set to 0 to disable)
- `TOR_OBFS4_PORT` - obfs4 port for bridge mode (default: 9002)
#### Bandwidth Limits
- `TOR_BANDWIDTH_RATE` - Rate limit (e.g., "50 MBytes")
- `TOR_BANDWIDTH_BURST` - Burst limit (e.g., "100 MBytes")
#### Exit Policy (exit mode only)
- `TOR_EXIT_POLICY` - Custom exit policy (e.g., "accept *:80,accept *:443,reject *:*")
#### Official Tor Project Bridge Naming (Drop-in Compatibility)
- `NICKNAME` - Maps to TOR_NICKNAME
- `EMAIL` - Maps to TOR_CONTACT_INFO
- `OR_PORT` - Maps to TOR_ORPORT
- `PT_PORT` - Maps to TOR_OBFS4_PORT (auto-enables bridge mode)
- `OBFS4V_*` - Additional torrc options
### Docker Compose with ENV
```yaml
version: '3.8'
services:
tor-relay:
image: ghcr.io/r3bo0tbx1/onion-relay:latest
container_name: tor-relay
restart: unless-stopped
network_mode: host
environment:
TOR_RELAY_MODE: guard
TOR_NICKNAME: MyRelay
TOR_CONTACT_INFO: tor@example.com
TOR_ORPORT: 9001
TOR_DIRPORT: 9030
TOR_BANDWIDTH_RATE: 50 MBytes
TOR_BANDWIDTH_BURST: 100 MBytes
volumes:
- tor-data:/var/lib/tor
volumes:
tor-data:
```
### Drop-in Replacement for Official Bridge
Fully compatible with `thetorproject/obfs4-bridge`:
```yaml
version: '3.8'
services:
obfs4-bridge:
image: ghcr.io/r3bo0tbx1/onion-relay:latest
container_name: obfs4-bridge
restart: unless-stopped
network_mode: host
environment:
# Official Tor Project ENV naming
NICKNAME: MyBridge
EMAIL: tor@example.com
OR_PORT: 9001
PT_PORT: 9002 # Auto-enables bridge mode
volumes:
- obfs4-data:/var/lib/tor
volumes:
obfs4-data:
```
---
@@ -318,7 +501,7 @@ After deploying with any method, verify your relay is working:
### 1. Check Container Status
```bash
docker ps | grep guard-relay
docker ps | grep tor-relay
```
Expected output:
@@ -327,28 +510,57 @@ CONTAINER ID IMAGE STATUS
abc123def456 ghcr.io/r3bo0tbx1/onion-relay:latest Up 5 minutes (healthy)
```
### 2. Run Full Diagnostic
### 2. Run Diagnostics
v1.1.1 provides **4 diagnostic tools**:
```bash
docker exec guard-relay relay-status
# Full health report with emojis
docker exec tor-relay status
# JSON health data (for automation)
docker exec tor-relay health
# Show fingerprint + Tor Metrics URL
docker exec tor-relay fingerprint
# Get bridge line (bridge mode only)
docker exec tor-relay bridge-line
```
Look for:
**Expected output from `status`:**
- ✅ `Bootstrapped 100% (done): Done`
- ✅ `ORPort is reachable from the outside`
- ✅ No recent errors
### 3. Check Your Fingerprint
### 3. Monitor Bootstrap Progress
```bash
docker exec guard-relay fingerprint
# Stream logs to see bootstrap progress (0-100%)
docker logs -f tor-relay
# Check JSON health
docker exec tor-relay health
```
**Example JSON output:**
```json
{
"status": "up",
"bootstrap": 100,
"reachable": true,
"fingerprint": "1234567890ABCDEF...",
"nickname": "MyRelay",
"uptime_seconds": 3600
}
```
### 4. Wait for Network Recognition
- **10-30 minutes**: Bootstrap completes (100%)
- **1-2 hours**: Relay appears on Tor Metrics
- **24-48 hours**: Full statistics available
- **8+ days**: Eligible for Guard flag
- **8+ days**: Eligible for Guard flag (guard relays only)
Search for your relay:
- **Clearnet**: https://metrics.torproject.org/rs.html
@@ -358,14 +570,26 @@ Search for your relay:
## Firewall Configuration
### Required Ports
| Relay Type | Ports to Open |
|------------|---------------|
| **Guard/Middle** | 9001/tcp (ORPort), 9030/tcp (DirPort) |
| **Exit** | 9001/tcp (ORPort), 9030/tcp (DirPort) |
| **Bridge** | 9001/tcp (ORPort), 9002/tcp (obfs4) |
> **Note:** All ports are configurable via ENV variables or config file.
### UFW (Ubuntu/Debian)
```bash
# Allow ORPort (required)
sudo ufw allow 9001/tcp
# Guard/Exit relay
sudo ufw allow 9001/tcp # ORPort
sudo ufw allow 9030/tcp # DirPort
# Allow DirPort (optional but recommended)
sudo ufw allow 9030/tcp
# Bridge relay
sudo ufw allow 9001/tcp # ORPort
sudo ufw allow 9002/tcp # obfs4 port
# Reload firewall
sudo ufw reload
@@ -377,12 +601,14 @@ sudo ufw status
### firewalld (RHEL/CentOS)
```bash
# Allow ORPort
# Guard/Exit relay
sudo firewall-cmd --permanent --add-port=9001/tcp
# Allow DirPort
sudo firewall-cmd --permanent --add-port=9030/tcp
# Bridge relay
sudo firewall-cmd --permanent --add-port=9001/tcp
sudo firewall-cmd --permanent --add-port=9002/tcp
# Reload
sudo firewall-cmd --reload
@@ -393,12 +619,14 @@ sudo firewall-cmd --list-all
### iptables (Advanced)
```bash
# Allow ORPort
# Guard/Exit relay
sudo iptables -A INPUT -p tcp --dport 9001 -j ACCEPT
# Allow DirPort
sudo iptables -A INPUT -p tcp --dport 9030 -j ACCEPT
# Bridge relay
sudo iptables -A INPUT -p tcp --dport 9001 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9002 -j ACCEPT
# Save rules
sudo iptables-save > /etc/iptables/rules.v4
```
@@ -445,19 +673,34 @@ Don't forget to open ports in your cloud provider's firewall:
- Dynamic IP issues
- Home network security risks
**Recommendation**: Use VPS for guard relays, home for bridges only.
**Recommendation**: Use VPS for guard/exit relays, home for bridges only.
---
## Monitoring Setup
### Option 1: Manual Monitoring Script
### Option 1: JSON Health API
v1.1.1 provides a `health` tool that outputs JSON for monitoring integration:
```bash
# Get health status (raw JSON)
docker exec tor-relay health
# Parse with jq (requires jq on host)
docker exec tor-relay health | jq .
# Check specific field
docker exec tor-relay health | jq .bootstrap
```
### Option 2: Manual Monitoring Script
```bash
#!/bin/bash
# Save as: /usr/local/bin/check-tor-relay.sh
CONTAINER="guard-relay"
CONTAINER="tor-relay"
echo "🧅 Tor Relay Health Check - $(date)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -469,9 +712,9 @@ if ! docker ps | grep -q "$CONTAINER"; then
fi
# Run diagnostics
docker exec "$CONTAINER" relay-status
docker exec "$CONTAINER" status
# Check for errors
# Check for errors in recent logs
ERRORS=$(docker logs "$CONTAINER" --tail 100 2>&1 | grep -iE "(error|critical)" | wc -l)
if [ "$ERRORS" -gt 5 ]; then
@@ -492,9 +735,31 @@ crontab -e
0 */6 * * * /usr/local/bin/check-tor-relay.sh >> /var/log/tor-health.log 2>&1
```
### Option 2: Prometheus + Grafana
### Option 3: Prometheus + Grafana
Coming soon! Watch the repo for monitoring stack templates.
Use the `health` tool with Prometheus node_exporter textfile collector:
```bash
#!/bin/bash
# Save as: /usr/local/bin/tor-metrics-exporter.sh
# Requires: jq installed on host (apt install jq / brew install jq)
HEALTH=$(docker exec tor-relay health)
# Export metrics
echo "$HEALTH" | jq -r '
"tor_bootstrap_percent \(.bootstrap)",
"tor_reachable \(if .reachable then 1 else 0 end)",
"tor_uptime_seconds \(.uptime_seconds // 0)"
' > /var/lib/node_exporter/textfile_collector/tor.prom
```
Run via cron every 5 minutes:
```bash
*/5 * * * * /usr/local/bin/tor-metrics-exporter.sh
```
> 📖 **Complete guide:** See [Monitoring Documentation](MONITORING.md) for advanced setups.
---
@@ -504,9 +769,9 @@ Coming soon! Watch the repo for monitoring stack templates.
```bash
# Check Docker logs
docker logs guard-relay --tail 50
docker logs tor-relay --tail 50
# Validate configuration
# Validate configuration (if using mounted config)
docker run --rm \
-v ~/tor-relay/relay.conf:/etc/tor/torrc:ro \
ghcr.io/r3bo0tbx1/onion-relay:latest \
@@ -527,10 +792,26 @@ sudo netstat -tulpn | grep 9001
```bash
# Verify mount path
docker inspect guard-relay | grep -A 10 Mounts
docker inspect tor-relay | grep -A 10 Mounts
# Check file permissions
ls -la ~/tor-relay/relay.conf
# View generated config (ENV mode)
docker exec tor-relay cat /etc/tor/torrc
```
### Bootstrap Stuck
```bash
# Check bootstrap progress
docker exec tor-relay health | jq .bootstrap
# Check for errors
docker logs tor-relay --tail 100 | grep -i error
# Verify ports are open
docker exec tor-relay status
```
---
@@ -540,16 +821,18 @@ ls -la ~/tor-relay/relay.conf
After successful deployment:
1. ✅ Monitor logs for 24 hours
2. ✅ Verify on Tor Metrics
3. ✅ Set up monitoring/alerts
2. ✅ Verify on Tor Metrics (https://metrics.torproject.org/rs.html)
3. ✅ Set up monitoring/alerts with `health` JSON API
4. ✅ Join [Tor Relay Operators mailing list](https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-relays)
5. ✅ Consider running multiple relays
5. ✅ Consider running multiple relays for better network contribution
---
## Support
- 📖 [Main README](../README.md)
- 🔧 [Tools Documentation](TOOLS.md) - Complete guide to the 4 diagnostic tools
- 📊 [Monitoring Guide](MONITORING.md) - External monitoring integration
- 🐛 [Report Issues](https://github.com/r3bo0tbx1/tor-guard-relay/issues)
- 💬 [Tor Project Forum](https://forum.torproject.net/)
- 📧 [Relay Operators List](https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-relays)
- 📧 [Relay Operators List](https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-relays)

392
docs/LOCAL-TESTING.md Normal file
View File

@@ -0,0 +1,392 @@
# Local Testing Guide
**For Contributors and Developers Only**
> ⚠️ **Most Users Should Use Published Images**
>
> If you're deploying a Tor relay, use the published images from Docker Hub or GHCR:
> - **Docker Hub**: `r3bo0tbx1/onion-relay:latest`
> - **GHCR**: `ghcr.io/r3bo0tbx1/onion-relay:latest`
>
> This guide is for **contributors** who are modifying code, scripts, or workflows.
---
## 📋 Prerequisites
- Docker 20.10+
- Docker Compose (optional)
- Local Docker Registry v2 (for development workflow)
- dos2unix (for Windows contributors)
---
## 🏗️ Development Workflow with Local Registry
### Step 1: Start Local Registry
```bash
# Start a local Docker Registry v2
docker run -d -p 5000:5000 --name registry registry:2
# Verify it's running
curl http://localhost:5000/v2/_catalog
```
### Step 2: Build and Push to Local Registry
```bash
# Clone repository
git clone https://github.com/r3bo0tbx1/tor-guard-relay.git
cd tor-guard-relay
# Normalize line endings (important for Windows)
dos2unix docker-entrypoint.sh healthcheck.sh tools/* 2>/dev/null || true
# Build image
docker build -t localhost:5000/onion-relay:test .
# Push to local registry
docker push localhost:5000/onion-relay:test
# Verify in registry
curl http://localhost:5000/v2/onion-relay/tags/list
```
### Step 3: Test from Local Registry
```bash
# Pull from local registry
docker pull localhost:5000/onion-relay:test
# Run test container
docker run --rm localhost:5000/onion-relay:test status
```
**Why use local registry?**
- Mirrors production workflow
- Tests multi-arch builds locally
- Easier to share with team members on same network
- Closer to CI/CD environment
---
## 🧪 Test Scenarios
### Test 1: Guard Relay (Mounted Config)
```bash
# Create test config
cat > /tmp/relay-test.conf << 'EOF'
Nickname TestGuardRelay
ContactInfo test@example.com
ORPort 9001
DirPort 9030
ExitRelay 0
ExitPolicy reject *:*
DataDirectory /var/lib/tor
Log notice file /var/log/tor/notices.log
SocksPort 0
EOF
# Run guard relay
docker run -d \
--name test-guard \
--network host \
-v /tmp/relay-test.conf:/etc/tor/torrc:ro \
-v test-guard-data:/var/lib/tor \
-v test-guard-logs:/var/log/tor \
localhost:5000/onion-relay:test
# Verify
docker logs test-guard
# Expected: ✅ Using mounted configuration: /etc/tor/torrc
# Test diagnostics
docker exec test-guard status
docker exec test-guard health | jq .
docker exec test-guard fingerprint
# Cleanup
docker stop test-guard && docker rm test-guard
docker volume rm test-guard-data test-guard-logs
```
### Test 2: Bridge with Official ENV Naming
**Tests drop-in compatibility with `thetorproject/obfs4-bridge`:**
```bash
# Run bridge with official naming
docker run -d \
--name test-bridge \
--network host \
-e OR_PORT=9001 \
-e PT_PORT=9002 \
-e EMAIL="test@example.com" \
-e NICKNAME=TestBridge \
-e OBFS4_ENABLE_ADDITIONAL_VARIABLES=1 \
-e OBFS4V_AddressDisableIPv6=0 \
-e OBFS4V_MaxMemInQueues="512 MB" \
-v test-bridge-data:/var/lib/tor \
localhost:5000/onion-relay:test
# Verify auto-detection
docker logs test-bridge
# Expected:
# ✅ Configuration generated from ENV vars
# 🌐 Relay mode: bridge (auto-detected from PT_PORT)
# Check generated torrc
docker exec test-bridge cat /etc/tor/torrc
# Should include:
# - BridgeRelay 1
# - ServerTransportPlugin obfs4 exec /usr/bin/lyrebird
# - ServerTransportListenAddr obfs4 0.0.0.0:9002
# - MaxMemInQueues 512 MB
# Verify lyrebird is running
docker exec test-bridge pgrep -a lyrebird
# Test bridge-line tool (after bootstrap)
docker exec test-bridge bridge-line
# Cleanup
docker stop test-bridge && docker rm test-bridge
docker volume rm test-bridge-data
```
### Test 3: Bridge with Mounted Config (Recommended)
```bash
# Create bridge config
cat > /tmp/bridge-test.conf << 'EOF'
Nickname TestBridgeMounted
ContactInfo test@example.com
ORPort 9001
SocksPort 0
DataDirectory /var/lib/tor
Log notice file /var/log/tor/notices.log
BridgeRelay 1
PublishServerDescriptor bridge
ServerTransportPlugin obfs4 exec /usr/bin/lyrebird
ServerTransportListenAddr obfs4 0.0.0.0:9002
ExtORPort auto
MaxMemInQueues 512 MB
AddressDisableIPv6 0
EOF
# Run bridge
docker run -d \
--name test-bridge-mounted \
--network host \
-v /tmp/bridge-test.conf:/etc/tor/torrc:ro \
-v test-bridge-mounted-data:/var/lib/tor \
localhost:5000/onion-relay:test
# Verify
docker logs test-bridge-mounted
# Expected: ✅ Using mounted configuration: /etc/tor/torrc
# Cleanup
docker stop test-bridge-mounted && docker rm test-bridge-mounted
docker volume rm test-bridge-mounted-data
```
### Test 4: Health Check
```bash
# Test health check script directly
docker run --rm \
-v /tmp/relay-test.conf:/etc/tor/torrc:ro \
localhost:5000/onion-relay:test \
/usr/local/bin/healthcheck.sh
# Expected: exit code 0 (healthy)
echo "Health check status: $?"
# Test with invalid config
docker run --rm localhost:5000/onion-relay:test sh -c \
"echo 'InvalidDirective BadValue' > /etc/tor/torrc && /usr/local/bin/healthcheck.sh"
# Expected: exit code 1 (unhealthy)
echo "Health check status: $?"
```
### Test 5: Input Validation
```bash
# Test nickname validation (should fail - too long)
docker run --rm \
-e TOR_NICKNAME="ThisNicknameIsWayTooLongAndShouldFail" \
-e TOR_CONTACT_INFO="test@example.com" \
localhost:5000/onion-relay:test 2>&1 | grep -i error
# Test port validation (should fail - invalid port)
docker run --rm \
-e TOR_NICKNAME="TestRelay" \
-e TOR_CONTACT_INFO="test@example.com" \
-e TOR_ORPORT="99999" \
localhost:5000/onion-relay:test 2>&1 | grep -i error
# Test bandwidth format (should succeed)
docker run --rm \
-e TOR_NICKNAME="TestRelay" \
-e TOR_CONTACT_INFO="test@example.com" \
-e TOR_BANDWIDTH_RATE="10 MBytes" \
localhost:5000/onion-relay:test \
sh -c "cat /etc/tor/torrc | grep -i bandwidth"
```
### Test 6: OBFS4V_* Whitelist Security
```bash
# Test whitelisted variable (should succeed)
docker run --rm \
-e OR_PORT=9001 \
-e PT_PORT=9002 \
-e EMAIL="test@example.com" \
-e NICKNAME=TestSec \
-e OBFS4_ENABLE_ADDITIONAL_VARIABLES=1 \
-e OBFS4V_MaxMemInQueues="512 MB" \
localhost:5000/onion-relay:test \
sh -c "cat /etc/tor/torrc | grep MaxMemInQueues"
# Test non-whitelisted variable (should warn and skip)
docker run --rm \
-e OR_PORT=9001 \
-e PT_PORT=9002 \
-e EMAIL="test@example.com" \
-e NICKNAME=TestSec \
-e OBFS4_ENABLE_ADDITIONAL_VARIABLES=1 \
-e OBFS4V_EvilDirective="malicious value" \
localhost:5000/onion-relay:test 2>&1 | grep -i "not in whitelist"
```
---
## 🔍 Verification Checklist
After building locally:
- [ ] All tool scripts are executable (`ls -l /usr/local/bin/`)
- [ ] Tool scripts have no .sh extensions
- [ ] All scripts use `#!/bin/sh` shebang
- [ ] Build info exists (`cat /build-info.txt`)
- [ ] Tor version is current (`tor --version`)
- [ ] Lyrebird is available (`/usr/bin/lyrebird --version`)
- [ ] Health check works for both mounted and ENV configs
- [ ] Diagnostic tools produce correct output
- [ ] Input validation catches invalid values
- [ ] OBFS4V_* whitelist blocks dangerous options
- [ ] Image size is ~20MB (`docker images localhost:5000/onion-relay:test`)
---
## 🐛 Debugging
### View Generated torrc
```bash
# For ENV-based config
docker run --rm \
-e TOR_NICKNAME=Debug \
-e TOR_CONTACT_INFO=debug@test.com \
localhost:5000/onion-relay:test \
cat /etc/tor/torrc
# For mounted config
docker run --rm \
-v /tmp/relay-test.conf:/etc/tor/torrc:ro \
localhost:5000/onion-relay:test \
cat /etc/tor/torrc
```
### Check Script Syntax
```bash
# Validate all shell scripts
for script in docker-entrypoint.sh healthcheck.sh tools/*; do
echo "Checking $script..."
sh -n "$script" && echo "✅ OK" || echo "❌ FAIL"
done
```
### Test Permissions
```bash
# Check file permissions in image
docker run --rm localhost:5000/onion-relay:test ls -la /usr/local/bin/
docker run --rm localhost:5000/onion-relay:test ls -ldn /var/lib/tor
docker run --rm localhost:5000/onion-relay:test ls -ldn /var/log/tor
```
---
## 🔄 Multi-Arch Testing
### Build for Multiple Architectures
```bash
# Set up buildx (once)
docker buildx create --name multiarch --use
docker buildx inspect --bootstrap
# Build for both AMD64 and ARM64
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t localhost:5000/onion-relay:multiarch \
--push \
.
# Test on current architecture
docker pull localhost:5000/onion-relay:multiarch
docker run --rm localhost:5000/onion-relay:multiarch cat /build-info.txt
```
---
## 🧹 Cleanup
```bash
# Stop and remove all test containers
docker ps -a | grep test- | awk '{print $1}' | xargs docker rm -f
# Remove test volumes
docker volume ls | grep test- | awk '{print $2}' | xargs docker volume rm
# Remove test images
docker rmi localhost:5000/onion-relay:test
docker rmi localhost:5000/onion-relay:multiarch
# Stop local registry
docker stop registry && docker rm registry
# Clean up test configs
rm -f /tmp/relay-test.conf /tmp/bridge-test.conf
```
---
## 📚 See Also
- **[Contributing Guide](../CONTRIBUTING.md)** - How to contribute code
- **[Deployment Guide](DEPLOYMENT.md)** - Production deployment methods
- **[Migration Guide](../MIGRATION-V1.1.X.md)** - Upgrading between versions
- **[Security Audit Report](../SECURITY-AUDIT-REPORT.md)** - Security fixes
---
## 💡 Tips for Contributors
1. **Always test with local registry** - Mirrors production workflow
2. **Test both mounted config and ENV variables** - Both must work
3. **Verify input validation** - Test edge cases and invalid inputs
4. **Check all diagnostic tools** - Ensure they work correctly
5. **Test on multiple architectures** - If you can (buildx helps)
6. **Run security validation** - Use `scripts/utilities/security-validation-tests.sh`
7. **Update documentation** - If you change behavior
---
*This guide is for development and testing. Production users should use published images from Docker Hub or GHCR.*

474
docs/MIGRATION-V1.1.X.md Normal file
View File

@@ -0,0 +1,474 @@
# Migration Guide: v1.1.0 → v1.1.1
This guide documents **two successful real-world migration paths** validated in production:
1. **Guard/Middle Relay** (mounted torrc) - Zero issues
2. **Bridge from Official Image** (thetorproject/obfs4-bridge) - Requires ownership fix
---
## 📋 What's New in v1.1.1
### Security Fixes
-**Fixed**: Command injection via OBFS4V_* environment variables (CWE-78, CWE-94)
-**Fixed**: Health check failure on ENV-based deployments (CWE-703)
-**Fixed**: Privilege escalation attempt with silent failure (CWE-250)
-**Fixed**: Inadequate input validation (CWE-20)
-**Fixed**: Workflow permission over-granting (CWE-269)
-**Fixed**: Temporary file race condition (CWE-377)
-**Fixed**: TOR_CONTACT_INFO validation false positives
### Improvements
- ✅ Smart healthcheck script works with both mounted and ENV configs
- ✅ Comprehensive input validation with whitespace trimming
- ✅ Better error messages and debugging
- ✅ Removed non-functional chown attempt
- ✅ Cleaned up bridge configuration (removed redundant ExitPolicy)
### Breaking Changes
**None** - All changes are backward compatible!
---
## ✅ Migration Path 1: Guard/Middle Relay (Mounted Config)
**Difficulty**: Easy
**Downtime**: < 2 minutes
**Fingerprint Preserved**: Yes ✅
**Volume Changes Required**: None
### Prerequisites
```bash
# Verify you're using a mounted torrc file
docker inspect <container> --format='{{range .Mounts}}{{if eq .Destination "/etc/tor/torrc"}}MOUNTED{{end}}{{end}}'
# Should output: MOUNTED
```
### Step 1: Backup
```bash
# Stop container
docker stop <container>
# Backup volumes
docker run --rm \
-v tor-guard-data:/data \
-v /tmp:/backup \
alpine:3.22.2 tar czf /backup/tor-guard-data-backup-$(date +%Y%m%d).tar.gz /data
docker run --rm \
-v tor-guard-logs:/data \
-v /tmp:/backup \
alpine:3.22.2 tar czf /backup/tor-guard-logs-backup-$(date +%Y%m%d).tar.gz /data
# Save fingerprint
docker run --rm -v tor-guard-data:/data alpine:3.22.2 cat /data/fingerprint > /tmp/fingerprint-backup.txt
```
### Step 2: Update Configuration
**Cosmos JSON changes**:
```json
{
"image": "r3bo0tbx1/onion-relay:1.1.1", // ← Update from :latest or :1.1.0
"cap_add": [
"NET_BIND_SERVICE" // ← Removed unnecessary CHOWN, SETUID, SETGID, DAC_OVERRIDE
],
"labels": {
"cosmos-version": "1.1.1" // ← Update version
}
}
```
### Step 3: Remove Old Container
```bash
docker rm <container>
```
### Step 4: Deploy Updated Container
- Import updated JSON in Cosmos UI
- Or redeploy with `docker-compose up -d`
### Step 5: Verify
```bash
# Check logs
docker logs -f <container>
# Expected: ✅ Using mounted configuration: /etc/tor/torrc
# Verify fingerprint matches
docker exec <container> fingerprint
cat /tmp/fingerprint-backup.txt
# Must match!
# Run diagnostics
docker exec <container> status
docker exec <container> health | jq .
```
### ✅ Success Criteria
- [ ] Container starts successfully
- [ ] Logs show "Using mounted configuration"
- [ ] Fingerprint matches backup
- [ ] Bootstrap reaches 100%
- [ ] Relay is reachable
---
## ⚠️ Migration Path 2: Bridge from Official Image
**Difficulty**: Moderate
**Downtime**: 5-10 minutes
**Fingerprint Preserved**: Yes ✅ (after fix)
**Volume Changes Required**: Yes - UID ownership fix
### The Challenge
**UID Mismatch**:
- Official `thetorproject/obfs4-bridge` (Debian): UID **101**
- `r3bo0tbx1/onion-relay` (Alpine): UID **100**
**Symptom**: `Permission denied` errors if not fixed.
### Prerequisites
```bash
# Verify current image
docker inspect <container> --format='{{.Config.Image}}'
# Should show: thetorproject/obfs4-bridge or similar
# Check ENV variables
docker inspect <container> --format='{{range .Config.Env}}{{println .}}{{end}}' | grep -E "OR_PORT|PT_PORT|EMAIL|NICKNAME"
```
### Recommended Approach: Use Mounted Config
**Why?**
- ✅ More reliable than ENV variables
- ✅ Bypasses validation complexity
- ✅ Same as guard relay (consistent approach)
- ✅ Easier to troubleshoot
### Step 1: Backup Everything
```bash
# Stop container
docker stop obfs4-bridge
# Backup volume (CRITICAL!)
docker run --rm \
-v obfs4-data:/data \
-v /tmp:/backup \
alpine:3.22.2 tar czf /backup/obfs4-data-backup-$(date +%Y%m%d).tar.gz /data
# Verify backup
ls -lh /tmp/obfs4-data-backup-*.tar.gz
# Save fingerprint
docker run --rm -v obfs4-data:/data alpine:3.22.2 cat /data/fingerprint > /tmp/bridge-fingerprint-backup.txt
cat /tmp/bridge-fingerprint-backup.txt
```
### Step 2: Fix Volume Ownership (CRITICAL!)
```bash
# Check current ownership (should be 101:101)
docker run --rm -v obfs4-data:/data alpine:3.22.2 ls -ldn /data
# Output: drwx------ ... 101 101 ...
# Fix ownership: 101 → 100
docker run --rm -v obfs4-data:/data alpine:3.22.2 chown -R 100:101 /data
# Verify fix
docker run --rm -v obfs4-data:/data alpine:3.22.2 ls -ldn /data
# Output: drwx------ ... 100 101 ... ← MUST show 100!
# Verify key files are readable
docker run --rm -v obfs4-data:/data alpine:3.22.2 ls -la /data/keys/
# Should show files owned by 100:101
```
### Step 3: Create Bridge Config File
```bash
# Create config directory
sudo mkdir -p /home/$(whoami)/onion
# Create bridge.conf
sudo tee /home/$(whoami)/onion/bridge.conf > /dev/null << 'EOF'
# Tor obfs4 Bridge Configuration
Nickname MyObfs4Bridge
ContactInfo admin@email.org
# Network configuration
ORPort 9001
SocksPort 0
# Data directories
DataDirectory /var/lib/tor
Log notice file /var/log/tor/notices.log
# Bridge relay configuration
BridgeRelay 1
PublishServerDescriptor bridge
# obfs4 pluggable transport
ServerTransportPlugin obfs4 exec /usr/bin/lyrebird
ServerTransportListenAddr obfs4 0.0.0.0:9005
ExtORPort auto
# Additional options
MaxMemInQueues 1024 MB
AddressDisableIPv6 0
EOF
# Customize with your values
sudo nano /home/$(whoami)/onion/bridge.conf
```
### Step 4: Remove Old Container
```bash
docker rm obfs4-bridge
```
### Step 5: Deploy with Mounted Config
**Cosmos JSON**:
```json
{
"minVersion": "0.8.0",
"services": {
"obfs4-bridge": {
"image": "r3bo0tbx1/onion-relay:1.1.1",
"container_name": "obfs4-bridge",
"restart": "unless-stopped",
"network_mode": "host",
"environment": [
"TZ=UTC"
],
"volumes": [
{
"type": "volume",
"source": "obfs4-data",
"target": "/var/lib/tor"
},
{
"type": "bind",
"source": "/home/youruser/onion/bridge.conf",
"target": "/etc/tor/torrc",
"read_only": true
}
],
"security_opt": [
"no-new-privileges:true"
],
"labels": {
"cosmos-stack": "TorBridge",
"cosmos-stack-main": "obfs4-bridge",
"cosmos-description": "🌉 Hardened obfs4 Bridge v1.1.1",
"cosmos-icon": "https://iili.io/KsXP2Y7.png",
"cosmos-auto-update": "true",
"cosmos-auto-update-type": "registry",
"cosmos-force-network-secured": "false",
"cosmos-version": "1.1.1"
}
}
},
"volumes": {
"obfs4-data": {}
}
}
```
**Key changes**:
- ✅ Removed ALL ENV variables
- ✅ Added mounted bridge.conf
- ✅ Updated image to 1.1.1
### Step 6: Deploy and Verify
```bash
# Import JSON in Cosmos UI and start
# Check logs
docker logs -f obfs4-bridge
# Expected:
# ✅ Using mounted configuration: /etc/tor/torrc
# ✅ Configuration is valid
# 🚀 Tor relay started
# Wait 30 seconds, then verify fingerprint
docker exec obfs4-bridge fingerprint
cat /tmp/bridge-fingerprint-backup.txt
# MUST MATCH!
# Check configuration
docker exec obfs4-bridge cat /etc/tor/torrc
# Should show BridgeRelay 1, obfs4 config, etc.
# Run health check
docker exec obfs4-bridge health | jq .
# Run full status
docker exec obfs4-bridge status
```
### Step 7: Get Bridge Line (After 24-48 Hours)
```bash
# Bridge line appears after Tor publishes to BridgeDB
docker exec obfs4-bridge bridge-line
```
### ✅ Success Criteria
- [ ] Container starts successfully
- [ ] Logs show "Using mounted configuration"
- [ ] Fingerprint matches backup (CRITICAL!)
- [ ] Bootstrap reaches 100%
- [ ] Bridge line available after 24-48 hours
---
## 🚨 Troubleshooting
### Issue 1: "Permission denied" on startup
**Symptom**:
```
Directory /var/lib/tor cannot be read: Permission denied
```
**Cause**: Volume ownership not fixed (still UID 101)
**Fix**:
```bash
docker stop obfs4-bridge
docker run --rm -v obfs4-data:/data alpine:3.22.2 chown -R 100:101 /data
docker start obfs4-bridge
```
### Issue 2: Different fingerprint after migration
**Symptom**: Fingerprint changed, new bridge identity
**Cause**: Bridge keys not preserved
**Fix**: Restore from backup:
```bash
docker stop obfs4-bridge
docker run --rm -v obfs4-data:/data -v /tmp:/backup alpine:3.22.2 \
sh -c 'rm -rf /data/* && tar xzf /backup/obfs4-data-backup-*.tar.gz -C / && chown -R 100:101 /data'
docker start obfs4-bridge
```
### Issue 3: "TOR_CONTACT_INFO contains invalid characters"
**Symptom**: Container in restart loop with validation error
**Cause**: Fixed in v1.1.1 - validation was too strict
**Solution**: Use mounted config instead of ENV variables (see Step 3-5 above)
### Issue 4: Container restart loop (general)
**Debug**:
```bash
# Check logs
docker logs obfs4-bridge --tail 50
# Check if it's actually using new image
docker inspect obfs4-bridge --format='{{.Image}}'
docker images r3bo0tbx1/onion-relay:1.1.1 --format='{{.ID}}'
# IDs must match!
# If IDs don't match: remove and recreate container
docker stop obfs4-bridge
docker rm obfs4-bridge
# Then redeploy
```
### Issue 5: Health check failing
**Symptom**: Container marked unhealthy
**Cause**: Old health check used hardcoded path
**Fix**: v1.1.1 includes smart healthcheck.sh that works with both mounted and ENV configs. Just update to 1.1.1 image.
---
## 📊 Comparison: ENV vs Mounted Config
| Aspect | ENV Variables | Mounted Config |
|--------|---------------|----------------|
| **Complexity** | Medium | Simple |
| **Validation** | Strict (can cause issues) | Minimal (tor validates) |
| **Debugging** | Harder | Easier (just cat file) |
| **Updates** | Restart container | Edit file + restart |
| **Recommended** | No ⚠️ | **Yes** ✅ |
| **Use Case** | Quick testing | Production |
**Recommendation**: Always use mounted config for production deployments.
---
## 🎯 Pre-Migration Checklist
### For All Migrations
- [ ] Current fingerprint saved to file
- [ ] Volumes backed up with timestamps
- [ ] Old container can be removed (stopped first)
- [ ] Firewall rules documented
- [ ] Testing plan prepared
### For Bridge from Official Image
- [ ] Volume ownership fix command prepared
- [ ] bridge.conf file created and customized
- [ ] Backup includes pt_state/obfs4_state.json
- [ ] Expected fingerprint documented
### Post-Migration
- [ ] Fingerprint matches backup
- [ ] Container starts without errors
- [ ] Bootstrap reaches 100%
- [ ] Diagnostic tools work (status, health, fingerprint)
- [ ] Monitoring updated (if applicable)
---
## 📚 Additional Resources
- **Security Audit Report**: `SECURITY-AUDIT-REPORT.md`
- **General Migration Guide**: `MIGRATION.md`
- **Troubleshooting**: `docs/TROUBLESHOOTING-BRIDGE-MIGRATION.md`
- **Tools Documentation**: `docs/TOOLS.md`
- **Deployment Guide**: `docs/DEPLOYMENT.md`
---
## 🔒 Security Notes
### What's Fixed in v1.1.1
1. **Command Injection** (CRITICAL): OBFS4V_* variables now validated with whitelist
2. **Health Check** (CRITICAL): Works with both mounted and ENV configs
3. **Input Validation** (CRITICAL): Comprehensive validation with whitespace trimming
4. **Permissions** (HIGH): Removed non-functional chown attempt
5. **Contact Info Validation** (HIGH): Fixed false positives
### Risk Assessment
**Before Migration**: MEDIUM (using v1.1.0 with known vulnerabilities)
**After Migration**: LOW (all critical vulnerabilities patched)
**Recommendation**: Migrate as soon as possible to address security fixes.
---
*Last Updated: 2025-11-13*
*Validated with production deployments*

View File

@@ -1,490 +1,371 @@
# 🔄 Migration Guide
# Migration Guide - Tor Guard Relay
Guide for migrating between Tor Guard Relay versions and from other Tor relay setups.
This document provides general migration guidance for Tor Guard Relay deployments.
For **specific v1.1.0 → v1.1.1 migration**, see [`MIGRATION-V1.1.X.md`](MIGRATION-V1.1.X.md).
---
## 📋 Overview
## 📋 General Migration Principles
This guide covers:
- ✅ Migrating from v1.0 to v1.1
- ✅ Migrating from official Tor Docker images
- ✅ Migrating from manual Tor installations
- ✅ Preserving relay identity and keys
- ✅ Zero-downtime migration strategies
---
## 🚀 v1.0 → v1.1 Migration
### What's New in v1.1
**Major Changes:**
- ✅ Reorganized repository structure (tools/, templates/, docs/)
- ✅ Enhanced CI/CD workflows with multi-arch builds
- ✅ New monitoring tools (dashboard, metrics-http)
- ✅ Improved docker-entrypoint.sh with better error handling
- ✅ Comprehensive documentation (TOOLS.md, MONITORING.md)
- ✅ Updated Prometheus and Grafana templates
- ✅ Better health checks and diagnostics
**Breaking Changes:**
- ⚠️ **None** - v1.1 is backward compatible with v1.0
- Volume mounts and configuration remain unchanged
- All tools maintain the same interface
### Migration Steps
#### Method 1: In-Place Update (Recommended)
### 1. Always Backup First
```bash
# 1. Stop the current relay
docker stop tor-relay
# 2. Backup relay data (CRITICAL - preserves identity)
# Backup data volume
docker run --rm \
-v tor-guard-data:/data \
-v ~/backups:/backup \
alpine tar czf /backup/tor-backup-$(date +%Y%m%d).tar.gz -C /data .
-v <volume-name>:/data \
-v /tmp:/backup \
alpine:3.22.2 tar czf /backup/tor-backup-$(date +%Y%m%d).tar.gz /data
# 3. Pull new v1.1 image
docker pull ghcr.io/r3bo0tbx1/onion-relay:v1.1
# Verify backup
ls -lh /tmp/tor-backup-*.tar.gz
# 4. Update container (data volumes persist automatically)
docker rm tor-relay
docker run -d \
--name tor-relay \
--restart unless-stopped \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
-p 9001:9001 \
-e ENABLE_METRICS=true \
-e ENABLE_HEALTH_CHECK=true \
ghcr.io/r3bo0tbx1/onion-relay:v1.1
# 5. Verify relay identity is preserved
docker exec tor-relay fingerprint
# Should show same fingerprint as before
# 6. Check new tools are available
docker exec tor-relay status
docker exec tor-relay health | jq .
# Save fingerprint
docker run --rm -v <volume-name>:/data alpine:3.22.2 cat /data/fingerprint > /tmp/fingerprint-backup.txt
```
#### Method 2: Docker Compose Update
### 2. Fingerprint Preservation
```bash
# 1. Update docker-compose.yml
sed -i 's/:latest/:v1.1/g' docker-compose.yml
**Your relay identity is stored in**:
- `/var/lib/tor/keys/secret_id_key` (RSA identity)
- `/var/lib/tor/keys/ed25519_master_id_secret_key` (Ed25519 identity)
- `/var/lib/tor/pt_state/obfs4_state.json` (bridge credentials, bridges only)
# 2. Pull new image
docker-compose pull
**CRITICAL**: These files must be preserved or your relay will get a new fingerprint.
# 3. Recreate containers (volumes persist)
docker-compose up -d
### 3. Configuration Approaches
# 4. Verify
docker-compose exec tor-relay status
**Recommended: Mounted Config File**
```yaml
volumes:
- type: bind
source: /path/to/relay.conf
target: /etc/tor/torrc
read_only: true
```
### Verification Checklist
**Alternative: Environment Variables**
```yaml
environment:
- TOR_RELAY_MODE=guard
- TOR_NICKNAME=MyRelay
- TOR_CONTACT_INFO=email@example.com
```
After migration, verify:
**Priority**: Mounted file > ENV variables
- [ ] Relay fingerprint matches pre-migration
- [ ] Bootstrap completes to 100%
- [ ] ORPort is reachable
- [ ] Metrics endpoint works (if enabled)
- [ ] New tools respond: `status`, `health`, `dashboard`
- [ ] Logs show no errors
- [ ] Relay appears on Tor Metrics with same identity
---
## 🔄 Migration Scenarios
### Scenario 1: Upgrading Between Versions (Same Image)
**Example**: v1.1.0 → v1.1.1
**Steps**:
1. Stop container
2. Backup volumes
3. Remove container (`docker rm`)
4. Pull new image version
5. Create new container with same volumes
6. Verify fingerprint matches
**Expected Downtime**: 1-5 minutes
**See**: [`MIGRATION-V1.1.X.md`](MIGRATION-V1.1.X.md) for detailed instructions
### Scenario 2: Migrating from Official Tor Images
**Example**: `thetorproject/obfs4-bridge``r3bo0tbx1/onion-relay`
**Challenges**:
- Different base OS (Debian → Alpine)
- Different user UID (101 → 100)
- Volume ownership needs fixing
**Steps**:
1. Backup everything
2. **Fix volume ownership**: `chown -R 100:101`
3. Create config file (recommended over ENV)
4. Deploy new container
5. Verify fingerprint preserved
**Expected Downtime**: 5-10 minutes
**See**: [`MIGRATION-V1.1.X.md`](MIGRATION-V1.1.X.md) - Migration Path 2
### Scenario 3: Changing Relay Type
**Example**: Guard → Exit, Guard → Bridge
**Warning**: ⚠️ This changes your relay's role and requires careful consideration.
**Steps**:
1. Understand legal implications (especially for exit relays)
2. Update configuration
3. Restart container
4. Monitor logs for warnings
5. Wait 24-48 hours for Tor network to update
**Fingerprint**: Preserved ✅
### Scenario 4: Moving to New Server
**Steps**:
1. **On old server**:
- Stop container
- Backup volume to tarball
- Transfer tarball to new server
2. **On new server**:
- Create volume
- Restore from tarball
- Deploy container with same configuration
- Verify fingerprint
**Example**:
```bash
# Quick verification script
#!/bin/bash
echo "🧅 v1.1 Migration Verification"
echo "================================"
# Old server - create backup
docker run --rm -v tor-data:/data -v $PWD:/backup alpine:3.22.2 \
tar czf /backup/tor-data.tar.gz /data
echo -n "✓ Container running: "
docker ps | grep -q tor-relay && echo "YES" || echo "NO"
# Transfer tor-data.tar.gz to new server
echo -n "✓ Fingerprint: "
docker exec tor-relay fingerprint | grep -q "Fingerprint:" && echo "OK" || echo "FAILED"
echo -n "✓ Health check: "
docker exec tor-relay health | jq -e '.status == "healthy"' &>/dev/null && echo "HEALTHY" || echo "CHECK FAILED"
echo -n "✓ Metrics: "
curl -s http://localhost:9035/metrics | grep -q "tor_relay_" && echo "OK" || echo "DISABLED/FAILED"
echo -n "✓ Bootstrap: "
docker exec tor-relay health | jq -r '.bootstrap.percent' | grep -q "100" && echo "100%" || echo "IN PROGRESS"
echo "================================"
echo "Migration verification complete!"
# New server - restore
docker volume create tor-data
docker run --rm -v tor-data:/data -v $PWD:/backup alpine:3.22.2 \
tar xzf /backup/tor-data.tar.gz -C /
```
---
## 🔄 Migrating from Official Tor Docker
## ⚙️ Container vs Image vs Configuration
If you're currently using the official Tor Project Docker images:
**Image**: The Docker image (`r3bo0tbx1/onion-relay:1.1.1`)
- Contains Tor binary, scripts, OS
- Immutable
- Can be updated independently
### Pre-Migration
**Container**: Running instance
- Created from image
- Has specific configuration
- Must be recreated to use new image
```bash
# 1. Note your current relay fingerprint
docker exec <your-tor-container> cat /var/lib/tor/fingerprint
# Save this - you'll verify it matches after migration
**Configuration**: Your relay settings
- Mounted file (`/etc/tor/torrc`)
- OR environment variables
- Persists across container recreations
# 2. Backup relay keys (CRITICAL)
docker cp <your-tor-container>:/var/lib/tor/keys ./tor-keys-backup
# 3. Backup your torrc configuration
docker cp <your-tor-container>:/etc/tor/torrc ./torrc-backup
```
### Migration
```bash
# 4. Stop official Tor container
docker stop <your-tor-container>
# 5. Create volume for Tor Guard Relay
docker volume create tor-guard-data
docker volume create tor-guard-logs
# 6. Restore keys to new volume
docker run --rm \
-v tor-guard-data:/data \
-v $(pwd)/tor-keys-backup:/backup:ro \
alpine sh -c "cp -a /backup/* /data/keys/ && chown -R 100:101 /data"
# 7. Start Tor Guard Relay with same config
docker run -d \
--name tor-relay \
--restart unless-stopped \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
-v $(pwd)/torrc-backup:/etc/tor/torrc:ro \
-p 9001:9001 \
ghcr.io/r3bo0tbx1/onion-relay:latest
# 8. Verify fingerprint matches
docker exec tor-relay fingerprint
```
### Configuration Differences
Official Tor images vs. Tor Guard Relay:
| Feature | Official Tor | Tor Guard Relay |
|---------|-------------|-----------------|
| Base image | Debian/Alpine | Alpine (minimal) |
| Built-in tools | None | 9 diagnostic tools |
| Monitoring | External | Built-in Prometheus |
| Health checks | Basic | Comprehensive JSON |
| Dashboard | None | Built-in HTML dashboard |
| Auto-healing | No | Yes (permissions) |
| Architecture | Manual | Multi-arch auto |
**Volumes**: Your relay data
- Identity keys
- State information
- Logs
- Persists across container recreations
---
## 🖥️ Migrating from Manual Installation
## 🔍 Verification Checklist
If you're running Tor directly on a server (not containerized):
After any migration:
### Pre-Migration
```bash
# 1. Backup relay keys (MOST IMPORTANT)
sudo tar czf ~/tor-keys-backup.tar.gz -C /var/lib/tor keys/
# 2. Backup torrc
sudo cp /etc/tor/torrc ~/torrc-backup
# 3. Note fingerprint
sudo cat /var/lib/tor/fingerprint
```
### Migration Strategy
**Option A: Side-by-Side (Zero Downtime)**
```bash
# 1. Change manual Tor ORPort to temporary port
sudo sed -i 's/ORPort 9001/ORPort 9002/g' /etc/tor/torrc
sudo systemctl restart tor
# 2. Start Docker relay on port 9001 with restored keys
docker volume create tor-guard-data
docker run --rm \
-v tor-guard-data:/data \
-v ~/tor-keys-backup.tar.gz:/backup.tar.gz:ro \
alpine sh -c "tar xzf /backup.tar.gz -C /data && chown -R 100:101 /data"
docker run -d \
--name tor-relay \
-v tor-guard-data:/var/lib/tor \
-v $(pwd)/torrc-backup:/etc/tor/torrc:ro \
-p 9001:9001 \
ghcr.io/r3bo0tbx1/onion-relay:latest
# 3. Wait for Docker relay to be fully bootstrapped
docker exec tor-relay status
# 4. Stop manual Tor
sudo systemctl stop tor
sudo systemctl disable tor
# 5. Clean up
docker exec tor-relay fingerprint # Verify same fingerprint
```
**Option B: Replace (Requires Downtime)**
```bash
# 1. Stop manual Tor
sudo systemctl stop tor
# 2. Create volume and restore keys
docker volume create tor-guard-data
docker run --rm \
-v tor-guard-data:/data \
-v ~/tor-keys-backup.tar.gz:/backup.tar.gz:ro \
alpine sh -c "tar xzf /backup.tar.gz -C /data && chown -R 100:101 /data"
# 3. Start containerized relay
docker run -d \
--name tor-relay \
--restart unless-stopped \
-v tor-guard-data:/var/lib/tor \
-v $(pwd)/torrc-backup:/etc/tor/torrc:ro \
-p 9001:9001 \
ghcr.io/r3bo0tbx1/onion-relay:latest
# 4. Verify
docker exec tor-relay fingerprint
docker exec tor-relay status
```
### Post-Migration Cleanup
```bash
# Optional: Remove manual Tor installation
sudo apt-get remove --purge tor tor-geoipdb -y
sudo apt-get autoremove -y
# Optional: Clean up old data (AFTER verifying Docker relay works)
# sudo rm -rf /var/lib/tor
# sudo rm -rf /etc/tor
```
- [ ] Container starts successfully
- [ ] No errors in logs: `docker logs <container> | grep -i error`
- [ ] Fingerprint matches backup
- [ ] Configuration loaded correctly
- [ ] Bootstrap reaches 100%
- [ ] Relay/bridge is reachable
- [ ] Diagnostic tools work:
- `docker exec <container> status`
- `docker exec <container> health`
- `docker exec <container> fingerprint`
- [ ] Tor Metrics shows relay (after 1-2 hours)
---
## 🔑 Preserving Relay Identity
## 🛠️ Common Migration Issues
**CRITICAL:** Your relay's identity is stored in these files:
### Issue: "Permission denied" Errors
```
/var/lib/tor/keys/
├── ed25519_master_id_public_key
├── ed25519_master_id_secret_key
├── ed25519_signing_cert
├── ed25519_signing_secret_key
└── secret_id_key
```
**To preserve your relay's reputation and identity:**
1. **Always backup these files before migration**
2. **Never lose these files** - they cannot be recovered
3. **Verify fingerprint after migration** matches original
4. **If fingerprint changes** - you've lost your identity and must start over
### Emergency Recovery
If you've lost your keys but have a backup:
**Cause**: Volume ownership mismatch
**Fix**:
```bash
# Create new volume
docker volume create tor-guard-data-recovered
# Check ownership
docker run --rm -v <volume>:/data alpine:3.22.2 ls -ldn /data
# Restore keys
docker run --rm \
-v tor-guard-data-recovered:/data \
-v ~/tor-keys-backup.tar.gz:/backup.tar.gz:ro \
alpine sh -c "mkdir -p /data/keys && tar xzf /backup.tar.gz -C /data && chown -R 100:101 /data"
# Start relay with recovered volume
docker run -d \
--name tor-relay-recovered \
-v tor-guard-data-recovered:/var/lib/tor \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
-p 9001:9001 \
ghcr.io/r3bo0tbx1/onion-relay:latest
# Verify fingerprint
docker exec tor-relay-recovered fingerprint
# Fix if needed (Alpine tor user is UID 100)
docker run --rm -v <volume>:/data alpine:3.22.2 chown -R 100:101 /data
```
---
### Issue: Fingerprint Changed
## 🚨 Common Migration Issues
**Cause**: Identity keys not preserved
### Issue: Fingerprint Changed After Migration
**Cause:** Keys were not properly preserved or restored with wrong permissions.
**Solution:**
**Fix**: Restore from backup:
```bash
# Stop relay
docker stop tor-relay
# Restore keys backup
docker run --rm \
-v tor-guard-data:/data \
-v ~/tor-keys-backup.tar.gz:/backup.tar.gz:ro \
alpine sh -c "rm -rf /data/keys && tar xzf /backup.tar.gz -C /data && chown -R 100:101 /data"
# Restart
docker start tor-relay
docker stop <container>
docker run --rm -v <volume>:/data -v /tmp:/backup alpine:3.22.2 \
sh -c 'rm -rf /data/* && tar xzf /backup/tor-backup-*.tar.gz -C /'
docker start <container>
```
### Issue: Permission Denied Errors
### Issue: Container Restart Loop
**Cause:** Wrong file ownership in restored keys.
**Solution:**
**Debug**:
```bash
# Fix permissions (auto-healed on next restart, but can force)
docker run --rm \
-v tor-guard-data:/data \
alpine sh -c "chown -R 100:101 /data && chmod 700 /data/keys && chmod 600 /data/keys/*"
```
### Issue: Bootstrap Fails After Migration
**Cause:** Network connectivity or configuration issues.
**Solution:**
```bash
# Run network diagnostics
docker exec tor-relay net-check
# Check logs
docker exec tor-relay view-logs --errors
docker logs <container> --tail 50
# Verify configuration
docker exec tor-relay cat /etc/tor/torrc
# Verify using correct image
docker inspect <container> --format='{{.Image}}'
# Check configuration
docker exec <container> cat /etc/tor/torrc
```
### Issue: Old Tor Process Still Running
**Common causes**:
- Invalid configuration syntax
- Missing required fields
- ENV variable validation failures (use mounted config instead)
**Cause:** Manual Tor installation not fully stopped.
### Issue: Health Check Failing
**Solution:**
```bash
# Stop system Tor
sudo systemctl stop tor
sudo systemctl disable tor
**Cause**: Old versions had hardcoded health check path
# Verify nothing on port 9001
sudo netstat -tulpn | grep 9001
# Kill any remaining Tor processes
sudo pkill -9 tor
```
**Fix**: Update to v1.1.1+ which includes smart healthcheck script
---
## 📊 Migration Checklist
## 📊 Migration Planning
Use this checklist for smooth migrations:
### Before Migration
### Pre-Migration
- [ ] Backup relay keys (most critical)
- [ ] Backup torrc configuration
- [ ] Note current fingerprint
- [ ] Test backups can be extracted
- [ ] Document current monitoring setup
- [ ] Check current bandwidth usage
1. **Document current state**:
- Image version
- Configuration source (file or ENV)
- Volume names
- Port mappings
- Current fingerprint
2. **Test plan**:
- What to verify post-migration
- Rollback procedure
- Downtime window
3. **Communication**:
- Notify users (for bridges)
- Schedule maintenance window
- Prepare status updates
### During Migration
- [ ] Pull new image version
- [ ] Create new volumes
- [ ] Restore keys with correct ownership
- [ ] Mount configuration
- [ ] Start new container
- [ ] Verify container starts without errors
### Post-Migration
- [ ] Verify same fingerprint
- [ ] Confirm bootstrap reaches 100%
- [ ] Check ORPort reachability
- [ ] Test all tools (status, health, etc.)
- [ ] Verify metrics (if enabled)
- [ ] Update monitoring dashboards
- [ ] Test log access
- [ ] Check Tor Metrics shows relay as active
1. **Follow documented procedure**
2. **Take backups**
3. **Verify each step**
4. **Don't skip verification**
### Cleanup (after 24h of successful operation)
- [ ] Remove old container
- [ ] Clean up old volumes (if not reusing)
- [ ] Remove manual Tor installation (if applicable)
- [ ] Archive old backups
- [ ] Update documentation
### After Migration
1. **Monitor logs for 30 minutes**
2. **Verify fingerprint**
3. **Check Tor Metrics after 1-2 hours**
4. **Update documentation**
5. **Keep backups for 7 days**
---
## 🆘 Rollback Procedure
## 🔒 Security Considerations
If migration fails and you need to rollback:
### UID/GID Consistency
```bash
# 1. Stop new container
docker stop tor-relay
docker rm tor-relay
**This image uses**:
- User: `tor`
- UID: 100
- GID: 101
# 2. If upgrading from v1.0: revert to old image
docker run -d \
--name tor-relay \
--restart unless-stopped \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
-p 9001:9001 \
ghcr.io/r3bo0tbx1/onion-relay:v1.0
**When migrating from Debian-based images**:
- Old UID: 101
- **Must fix volume ownership**
# 3. If migrating from manual: restore system Tor
sudo systemctl start tor
sudo systemctl enable tor
### File Permissions
# 4. Verify fingerprint matches original
**Expected permissions**:
```
drwx------ /var/lib/tor (700, owned by tor)
drwxr-xr-x /var/log/tor (755, owned by tor)
-rw------- keys/* (600, owned by tor)
```
---
### Capabilities
## 📚 Related Documentation
**Minimal required**:
```yaml
cap_add:
- NET_BIND_SERVICE # Only if using ports < 1024
```
- [Deployment Guide](./DEPLOYMENT.md) - Fresh installation
- [Backup Guide](./BACKUP.md) - Data persistence strategies
- [Tools Reference](./TOOLS.md) - Using diagnostic tools
- [Monitoring Guide](./MONITORING.md) - Setting up monitoring
**Avoid granting unnecessary capabilities**.
---
## 💡 Migration Tips
## 📚 Resources
1. **Always test in staging first** if you have multiple relays
2. **Migrate during low-traffic periods** to minimize impact
3. **Keep old backups for 30 days** after successful migration
4. **Document your specific configuration** before starting
5. **Have rollback plan ready** before beginning migration
6. **Monitor closely for 24-48h** after migration
- **v1.1.0 → v1.1.1 Migration**: [`MIGRATION-V1.1.X.md`](MIGRATION-V1.1.X.md)
- **Deployment Guide**: [`DEPLOYMENT.md`](DEPLOYMENT.md)
- **Troubleshooting**: [`TROUBLESHOOTING-BRIDGE-MIGRATION.md`](TROUBLESHOOTING-BRIDGE-MIGRATION.md)
- **Tools Documentation**: [`TOOLS.md`](TOOLS.md)
- **Security Audit**: [`../SECURITY-AUDIT-REPORT.md`](../SECURITY-AUDIT-REPORT.md)
---
**Last Updated:** November 2025 | **Version:** 1.1
## 🆘 Getting Help
If migration fails:
1. **Check logs**: `docker logs <container>`
2. **Verify backup**: `ls -lh /tmp/tor-backup-*.tar.gz`
3. **Restore from backup** if needed
4. **Consult troubleshooting docs**
5. **Open GitHub issue** with:
- Migration path (what → what)
- Error messages
- Log output
- Configuration (redact sensitive info)
---
## ⚡ Quick Reference
### Common Commands
```bash
# Backup
docker run --rm -v <vol>:/data -v /tmp:/backup alpine:3.22.2 tar czf /backup/backup.tar.gz /data
# Restore
docker run --rm -v <vol>:/data -v /tmp:/backup alpine:3.22.2 tar xzf /backup/backup.tar.gz -C /
# Fix ownership (Alpine)
docker run --rm -v <vol>:/data alpine:3.22.2 chown -R 100:101 /data
# Get fingerprint
docker exec <container> fingerprint
# Check health
docker exec <container> health | jq .
# Full status
docker exec <container> status
```
### Version-Specific Migrations
| From | To | Guide |
|------|-----|-------|
| v1.1.0 | v1.1.1 | [MIGRATION-V1.1.X.md](MIGRATION-V1.1.X.md) |
| Official bridge | v1.1.1 | [MIGRATION-V1.1.X.md](MIGRATION-V1.1.X.md) - Path 2 |
| Future | Future | This document + version-specific guide |
---
*Last Updated: 2025-11-13*

View File

@@ -1,544 +1,456 @@
# 📊 Monitoring & Observability Guide
# 📊 Monitoring Guide
Complete guide to monitoring your Tor Guard Relay with **Prometheus**, **Grafana**, and **Alertmanager**.
Guide to monitoring your Tor Guard Relay with external tools. The v1.1.1 ultra-optimized build (~20 MB) does not include built-in Prometheus metrics endpoints, but provides multiple alternatives for monitoring.
---
## 📋 Overview
This guide covers:
- ✅ Prometheus metrics collection
- ✅ Grafana dashboard setup
-Alert configuration
-Multi-relay monitoring
-Best practices and troubleshooting
**What Changed in v1.1.1:**
- ❌ Removed built-in `metrics-http` server (to reduce image size)
- ❌ Removed Python-based dashboard
-Kept `health` tool for JSON status output
-Kept `status` tool for human-readable output
-Enhanced logging for external monitoring integration
**Monitoring Options:**
1. Docker health checks (built-in)
2. `health` tool with external scrapers
3. Log file monitoring
4. External Prometheus exporters
5. Cloud monitoring services
---
## 🏗️ Architecture
## 🚀 Quick Start Options
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Tor Relay │────▶│ Prometheus │────▶│ Grafana │
│ :9035 │ │ :9090 │ │ :3000 │
└─────────────┘ └──────┬──────┘ └─────────────┘
┌─────────────┐
│Alertmanager │
│ :9093 │
└─────────────┘
```
### Option 1: Docker Health Checks (Simplest)
**Components:**
- **Tor Relay** - Exposes metrics via `metrics-http` tool on port 9035
- **Prometheus** - Scrapes and stores metrics
- **Grafana** - Visualizes metrics with dashboards
- **Alertmanager** - Handles alerts and notifications
---
## 🚀 Quick Start
### Single Relay with Monitoring
Use the provided Docker Compose template:
Built-in Docker health checks automatically monitor relay status:
```bash
# Download template
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/docker-compose.yml
# Check health status
docker inspect --format='{{.State.Health.Status}}' tor-relay
# Download Prometheus config
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/prometheus.yml
# Start services
docker-compose up -d
# Access Grafana
open http://localhost:3000
# Get health history (requires jq on host)
docker inspect --format='{{json .State.Health}}' tor-relay | jq
```
### Multi-Relay Setup
For monitoring multiple relays:
```bash
# Download multi-relay template
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/docker-compose-multi-relay.yml
# Configure and start
docker-compose -f docker-compose-multi-relay.yml up -d
```
---
## 📊 Metrics Reference
### Available Metrics
All metrics are prefixed with `tor_relay_` and include a `relay_name` label.
#### Bootstrap & Connectivity
```prometheus
# Bootstrap completion percentage (0-100)
tor_relay_bootstrap_percent{relay_name="MyRelay"} 100
# ORPort reachability (1=reachable, 0=unreachable)
tor_relay_or_port_reachable{relay_name="MyRelay",port="9001"} 1
# DirPort reachability (1=reachable, 0=unreachable)
tor_relay_dir_port_reachable{relay_name="MyRelay",port="9030"} 1
```
#### Performance
```prometheus
# Relay uptime in seconds
tor_relay_uptime_seconds{relay_name="MyRelay"} 214830
# Configured bandwidth rate in bytes/sec
tor_relay_bandwidth_rate_bytes{relay_name="MyRelay"} 52428800
# Configured bandwidth burst in bytes/sec
tor_relay_bandwidth_burst_bytes{relay_name="MyRelay"} 104857600
```
#### Health Status
```prometheus
# Overall health status (1=healthy, 0=unhealthy)
tor_relay_healthy{relay_name="MyRelay"} 1
# Error count
tor_relay_errors_total{relay_name="MyRelay"} 0
# Warning count
tor_relay_warnings_total{relay_name="MyRelay"} 0
```
#### System Resources (when available)
```prometheus
# CPU usage percentage
process_cpu_seconds_total{relay_name="MyRelay"} 1234.56
# Memory usage in bytes
process_resident_memory_bytes{relay_name="MyRelay"} 134217728
# Open file descriptors
process_open_fds{relay_name="MyRelay"} 42
```
---
## 🎨 Prometheus Configuration
### Basic Configuration
**File:** `prometheus.yml`
**Healthcheck Configuration:**
```yaml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: 'tor-relays'
environment: 'production'
# Already included in all compose templates
healthcheck:
test: ["CMD-SHELL", "/usr/local/bin/healthcheck.sh"]
interval: 10m
timeout: 15s
start_period: 30s
retries: 3
```
# Scrape configurations
**Monitoring:**
- Use `docker events` to watch health changes
- Integrate with Docker monitoring tools (Portainer, Netdata, etc.)
- Alert on `health_status: unhealthy` events
---
### Option 2: Health Tool with External Scraper
Use the `health` tool's JSON output with your monitoring system:
**Setup Simple HTTP Wrapper:**
```bash
# Create simple health endpoint with netcat
while true; do
HEALTH=$(docker exec tor-relay health)
echo -e "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n$HEALTH" | nc -l -p 9100
done
```
**Or use a proper wrapper script:**
```python
#!/usr/bin/env python3
from flask import Flask, jsonify
import subprocess
import json
app = Flask(__name__)
@app.route('/health')
def health():
result = subprocess.run(
['docker', 'exec', 'tor-relay', 'health'],
capture_output=True,
text=True
)
return jsonify(json.loads(result.stdout))
@app.route('/metrics')
def metrics():
health_data = subprocess.run(
['docker', 'exec', 'tor-relay', 'health'],
capture_output=True,
text=True
)
data = json.loads(health_data.stdout)
# Convert to Prometheus format
metrics = f"""# HELP tor_relay_up Relay is running
# TYPE tor_relay_up gauge
tor_relay_up {{nickname="{data['nickname']}"}} {1 if data['status'] == 'up' else 0}
# HELP tor_relay_bootstrap_percent Bootstrap completion
# TYPE tor_relay_bootstrap_percent gauge
tor_relay_bootstrap_percent {{nickname="{data['nickname']}"}} {data['bootstrap']}
# HELP tor_relay_errors Error count
# TYPE tor_relay_errors gauge
tor_relay_errors {{nickname="{data['nickname']}"}} {data['errors']}
"""
return metrics, 200, {'Content-Type': 'text/plain; charset=utf-8'}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9100)
```
**Prometheus Configuration:**
```yaml
scrape_configs:
# Single relay
- job_name: 'tor-relay'
static_configs:
- targets: ['tor-relay:9035']
labels:
relay_name: 'MyTorRelay'
# Multiple relays
- job_name: 'tor-relay-multi'
- targets: ['localhost:9100']
scrape_interval: 60s
```
---
### Option 3: Log File Monitoring
Monitor Tor logs directly for events and errors:
**Filebeat Configuration:**
```yaml
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/lib/docker/volumes/tor-guard-logs/_data/notices.log
fields:
service: tor-relay
multiline:
pattern: '^\['
negate: true
match: after
output.elasticsearch:
hosts: ["localhost:9200"]
index: "tor-relay-logs-%{+yyyy.MM.dd}"
```
**Promtail Configuration (for Loki):**
```yaml
# promtail-config.yml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://localhost:3100/loki/api/v1/push
scrape_configs:
- job_name: tor-relay
static_configs:
- targets:
- 'tor-relay-1:9035'
- 'tor-relay-2:9036'
- 'tor-relay-3:9037'
- localhost
labels:
cluster: 'tor-multi-relay'
job: tor-relay
__path__: /var/lib/docker/volumes/tor-guard-logs/_data/*.log
```
### Auto-Discovery (Docker)
**Key Log Patterns to Monitor:**
```bash
# Bootstrap complete
grep "Bootstrapped 100%" /var/log/tor/notices.log
For dynamic relay discovery:
# ORPort reachability
grep "Self-testing indicates your ORPort is reachable" /var/log/tor/notices.log
```yaml
# Errors
grep "\[err\]" /var/log/tor/notices.log
# Warnings
grep "\[warn\]" /var/log/tor/notices.log
# Bandwidth self-test
grep "bandwidth self-test...done" /var/log/tor/notices.log
```
---
### Option 4: External Prometheus Exporters
Use dedicated Tor exporters that parse Tor control port:
**Option A: tor_exporter**
```bash
# Install tor_exporter
docker run -d --name tor-exporter \
--network host \
ghcr.io/atx/prometheus-tor_exporter:latest \
--tor.control-address=127.0.0.1:9051
# Add to Prometheus
scrape_configs:
- job_name: 'tor-relays-docker'
docker_sd_configs:
- host: unix:///var/run/docker.sock
relabel_configs:
- source_labels: [__meta_docker_container_label_com_example_service]
regex: 'tor-relay'
action: keep
- source_labels: [__meta_docker_container_name]
target_label: relay_name
- job_name: 'tor-exporter'
static_configs:
- targets: ['localhost:9099']
```
**Option B: Custom exporter from health tool**
See Option 2 above for Python Flask example.
---
## 📈 Grafana Dashboards
### Pre-built Dashboard
A complete Grafana dashboard is provided in the repository:
```bash
# Import dashboard
curl -O https://raw.githubusercontent.com/r3bo0tbx1/tor-guard-relay/main/templates/grafana-dashboard.json
# In Grafana UI:
# 1. Go to Dashboards → Import
# 2. Upload grafana-dashboard.json
# 3. Select Prometheus datasource
# 4. Click Import
```
### Dashboard Panels
The provided dashboard includes:
1. **Overview Row**
- Relay Status (UP/DOWN)
- Bootstrap Progress
- Uptime
- ORPort/DirPort Reachability
2. **Network Row**
- Public IP Address
- Port Status
- Bandwidth Configuration
3. **Performance Row**
- CPU Usage Graph
- Memory Usage Graph
- Network Traffic (if available)
4. **Health Row**
- Error Count
- Warning Count
- Recent Issues Timeline
5. **Multi-Relay Row** (when monitoring multiple relays)
- Relay Comparison Table
- Aggregate Statistics
### Custom Queries
Example PromQL queries for custom panels:
```prometheus
# Average bootstrap across all relays
avg(tor_relay_bootstrap_percent)
# Relays not fully bootstrapped
count(tor_relay_bootstrap_percent < 100)
# Total bandwidth capacity
sum(tor_relay_bandwidth_rate_bytes)
# Relay availability (24h)
avg_over_time(tor_relay_healthy[24h])
# Unreachable relays
count(tor_relay_or_port_reachable == 0)
```
---
## 🚨 Alerting
### Alert Rules
**File:** `prometheus-alerts.yml`
### Option 5: Cloud Monitoring Services
**DataDog:**
```yaml
groups:
- name: tor_relay_alerts
interval: 30s
rules:
# Critical: Relay is down
- alert: TorRelayDown
expr: up{job="tor-relay"} == 0
for: 5m
labels:
severity: critical
alert_type: availability
annotations:
summary: "Relay {{ $labels.relay_name }} is down"
description: "Relay has been unreachable for 5 minutes"
# datadog.yaml
logs:
- type: file
path: /var/lib/docker/volumes/tor-guard-logs/_data/notices.log
service: tor-relay
source: tor
# Critical: Bootstrap not complete
- alert: TorBootstrapIncomplete
expr: tor_relay_bootstrap_percent < 100
for: 10m
labels:
severity: warning
alert_type: bootstrap
annotations:
summary: "Relay {{ $labels.relay_name }} bootstrap incomplete"
description: "Bootstrap at {{ $value }}% for 10+ minutes"
# Critical: ORPort unreachable
- alert: TorORPortUnreachable
expr: tor_relay_or_port_reachable == 0
for: 10m
labels:
severity: critical
alert_type: reachability
annotations:
summary: "Relay {{ $labels.relay_name }} ORPort unreachable"
description: "ORPort {{ $labels.port }} has been unreachable for 10 minutes"
# Warning: High error count
- alert: TorRelayHighErrors
expr: increase(tor_relay_errors_total[5m]) > 5
for: 5m
labels:
severity: warning
alert_type: health
annotations:
summary: "Relay {{ $labels.relay_name }} has high error count"
description: "{{ $value }} errors in last 5 minutes"
# Warning: High CPU usage
- alert: TorRelayHighCPU
expr: rate(process_cpu_seconds_total[5m]) > 0.8
for: 15m
labels:
severity: warning
alert_type: performance
annotations:
summary: "Relay {{ $labels.relay_name }} high CPU"
description: "CPU usage: {{ $value | humanizePercentage }}"
# Warning: High memory usage
- alert: TorRelayHighMemory
expr: process_resident_memory_bytes / 1024 / 1024 > 512
for: 10m
labels:
severity: warning
alert_type: performance
annotations:
summary: "Relay {{ $labels.relay_name }} high memory"
description: "Memory: {{ $value | humanize }}MB"
checks:
http_check:
instances:
- name: tor-relay-health
url: http://localhost:9100/health
timeout: 5
```
### Alertmanager Configuration
**File:** `alertmanager.yml`
**New Relic:**
```yaml
global:
resolve_timeout: 5m
slack_api_url: 'YOUR_SLACK_WEBHOOK_URL'
integrations:
- name: nri-docker
env:
DOCKER_API_VERSION: v1.40
interval: 60s
route:
receiver: 'default'
group_by: ['alertname', 'relay_name']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
routes:
# Critical alerts - immediate notification
- match:
severity: critical
receiver: 'critical-alerts'
group_wait: 10s
repeat_interval: 4h
# Warnings - less frequent
- match:
severity: warning
receiver: 'warnings'
group_wait: 2m
repeat_interval: 24h
receivers:
- name: 'default'
slack_configs:
- channel: '#tor-relay-general'
title: '🧅 Tor Guard Relay Alert'
text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'
- name: 'critical-alerts'
slack_configs:
- channel: '#tor-relay-critical'
title: '🚨 CRITICAL: Tor Relay Alert'
text: '{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}'
color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
# Optional: Discord webhook
webhook_configs:
- url: 'YOUR_DISCORD_WEBHOOK_URL'
- name: 'warnings'
slack_configs:
- channel: '#tor-relay-warnings'
title: '⚠️ Warning: Tor Relay'
text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'
- name: nri-flex
config:
name: tor-relay-health
apis:
- event_type: TorRelayHealth
commands:
- run: docker exec tor-relay health
split: none
```
---
## 🔍 Troubleshooting
## 📊 Monitoring Metrics
### Prometheus Not Scraping Metrics
```bash
# Check if metrics endpoint is accessible
curl http://localhost:9035/metrics
# Check Prometheus targets
open http://localhost:9090/targets
# Check container networking
docker network inspect bridge
# Verify ENABLE_METRICS is set
docker exec tor-relay env | grep ENABLE_METRICS
```
### No Data in Grafana
```bash
# Verify Prometheus datasource
# Grafana → Configuration → Data Sources → Prometheus
# Test the connection
# Check if Prometheus has data
curl 'http://localhost:9090/api/v1/query?query=tor_relay_uptime_seconds'
# Check time range in Grafana dashboard
# Ensure time range covers when relay was running
```
### Alerts Not Firing
```bash
# Check alert rules are loaded
open http://localhost:9090/rules
# Verify Alertmanager connection
open http://localhost:9090/alerts
# Check Alertmanager is receiving alerts
open http://localhost:9093
# Test webhook endpoints
curl -X POST YOUR_SLACK_WEBHOOK_URL -d '{"text":"Test"}'
```
---
## 📊 Best Practices
### 1. Retention Configuration
```yaml
# In prometheus.yml
global:
# Keep metrics for 30 days
storage.tsdb.retention.time: 30d
# Or limit by size
storage.tsdb.retention.size: 10GB
```
### 2. Scrape Intervals
- **Production:** 15-30 seconds
- **Development:** 5-10 seconds
- **High-load relays:** 30-60 seconds
### 3. Alert Tuning
- Set appropriate `for` durations to avoid alert fatigue
- Use `group_wait` to batch related alerts
- Configure escalation via `repeat_interval`
### 4. Dashboard Organization
- Use template variables for relay selection
- Create separate dashboards for overview vs. detailed metrics
- Use row collapse for optional sections
### 5. Resource Management
```yaml
# Limit Prometheus memory
command:
- '--storage.tsdb.retention.time=30d'
- '--config.file=/etc/prometheus/prometheus.yml'
# Set resource limits in Docker Compose
deploy:
resources:
limits:
cpus: '1'
memory: 2G
```
---
## 🔐 Security
### Metrics Endpoint Protection
```nginx
# Nginx reverse proxy example
server {
listen 443 ssl;
server_name metrics.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /metrics {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:9035;
}
**Available from `health` tool:**
```json
{
"status": "up|down|error",
"pid": 123,
"uptime": "2d 14h 30m",
"bootstrap": 0-100,
"reachable": "true|false",
"errors": 0,
"nickname": "MyRelay",
"fingerprint": "ABCD..."
}
```
### Grafana Authentication
**Key Metrics to Track:**
- `status` - Relay health (up/down/error)
- `bootstrap` - Connection progress (0-100%)
- `reachable` - ORPort accessibility
- `errors` - Error count
- `uptime` - Relay uptime
**From Logs:**
- Bootstrap events
- ORPort reachability tests
- Bandwidth usage
- Connection counts (if exit relay)
- Warning and error messages
---
## 🔔 Alerting
### Simple Shell Script Alert
```bash
#!/bin/bash
# check-tor-relay.sh
# Requires: jq installed on host (apt install jq / brew install jq)
STATUS=$(docker exec tor-relay health | jq -r '.status')
BOOTSTRAP=$(docker exec tor-relay health | jq -r '.bootstrap')
ERRORS=$(docker exec tor-relay health | jq -r '.errors')
if [ "$STATUS" != "up" ]; then
echo "CRITICAL: Tor relay is $STATUS"
# Send alert via email, Slack, Discord, etc.
curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK \
-d "{\"text\": \"Tor relay is $STATUS\"}"
exit 2
fi
if [ "$BOOTSTRAP" -lt 100 ]; then
echo "WARNING: Bootstrap at $BOOTSTRAP%"
exit 1
fi
if [ "$ERRORS" -gt 0 ]; then
echo "WARNING: $ERRORS errors detected"
exit 1
fi
echo "OK: Relay healthy, $BOOTSTRAP% bootstrapped"
exit 0
```
**Run with cron:**
```cron
*/5 * * * * /usr/local/bin/check-tor-relay.sh
```
### Docker Events Alert
```bash
#!/bin/bash
# watch-docker-health.sh
# Requires: jq installed on host (apt install jq / brew install jq)
docker events --filter 'event=health_status' --format '{{json .}}' | while read event; do
STATUS=$(echo $event | jq -r '.Actor.Attributes."health_status"')
CONTAINER=$(echo $event | jq -r '.Actor.Attributes.name')
if [ "$STATUS" = "unhealthy" ]; then
echo "ALERT: $CONTAINER is unhealthy"
# Send notification
fi
done
```
---
## 🏗️ Example: Complete Monitoring Stack
**Docker Compose with external monitoring:**
```yaml
# In grafana datasource config
environment:
- GF_SECURITY_ADMIN_PASSWORD=secure_password_here
- GF_USERS_ALLOW_SIGN_UP=false
- GF_AUTH_ANONYMOUS_ENABLED=false
version: '3.8'
services:
tor-relay:
image: r3bo0tbx1/onion-relay:latest
container_name: tor-relay
network_mode: host
volumes:
- ./relay.conf:/etc/tor/torrc:ro
- tor-data:/var/lib/tor
- tor-logs:/var/log/tor
healthcheck:
test: ["CMD", "tor", "--verify-config", "-f", "/etc/tor/torrc"]
interval: 10m
timeout: 15s
retries: 3
# Health exporter (Python wrapper)
health-exporter:
image: python:3.11-slim
container_name: tor-health-exporter
network_mode: host
volumes:
- ./health-exporter.py:/app/exporter.py
- /var/run/docker.sock:/var/run/docker.sock:ro
command: python /app/exporter.py
depends_on:
- tor-relay
# Prometheus
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
# Grafana
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
volumes:
tor-data:
tor-logs:
prometheus-data:
grafana-data:
```
---
## 💡 Tips & Best Practices
1. **Use `health` tool** - JSON output perfect for automation
2. **Monitor Docker health** - Built-in, no extra tools needed
3. **Alert on status changes** - Watch for `status != "up"`
4. **Track bootstrap** - New relays take 5-15 minutes
5. **Monitor logs** - Tor logs are comprehensive and informative
6. **External exporters** - Use tor_exporter for detailed metrics
7. **Keep it simple** - Don't over-complicate monitoring
---
## 📚 Related Documentation
- [Tools Reference](./TOOLS.md) - Detailed tool documentation
- [Deployment Guide](./DEPLOYMENT.md) - Installation instructions
- [Tools Reference](./TOOLS.md) - Built-in diagnostic tools
- [Deployment Guide](./DEPLOYMENT.md) - Installation and configuration
- [Performance Guide](./PERFORMANCE.md) - Optimization tips
- [Backup Guide](./BACKUP.md) - Data persistence
---
## 🆘 Support
## ❓ FAQ
- 📖 [Prometheus Documentation](https://prometheus.io/docs/)
- 📖 [Grafana Documentation](https://grafana.com/docs/)
- 🐛 [Report Issues](https://github.com/r3bo0tbx1/tor-guard-relay/issues)
- 💬 [Community Forum](https://forum.torproject.org/)
**Q: Why was the built-in metrics endpoint removed?**
A: To achieve the ultra-small image size (~20 MB). The metrics server required Python, Flask, and other dependencies (~25+ MB). External monitoring is more flexible anyway.
**Q: Can I still use Prometheus?**
A: Yes! Use the Python wrapper example above, or a dedicated Tor exporter like `prometheus-tor_exporter`.
**Q: What's the simplest monitoring option?**
A: Docker health checks + the `health` tool. No additional infrastructure needed.
**Q: How do I monitor multiple relays?**
A: Run the health exporter on each host, or use log aggregation (Loki, ELK, Datadog).
**Q: Where can I find the logs?**
A:
- Inside container: `/var/log/tor/notices.log`
- On host: `/var/lib/docker/volumes/tor-guard-logs/_data/notices.log`
- Via docker: `docker logs tor-relay`
---
**Last Updated:** November 2025 | **Version:** 1.1
**Last Updated:** November 2025 | **Version:** 1.1.1

535
docs/MULTI-MODE.md Normal file
View File

@@ -0,0 +1,535 @@
# 🔄 Multi-Mode Relay Guide - Tor Guard Relay
Complete guide to running Guard/Middle relays, Exit relays, and obfs4 Bridges.
---
## Table of Contents
- [Overview](#overview)
- [Mode Comparison](#mode-comparison)
- [Guard/Middle Relay Mode](#guardmiddle-relay-mode)
- [Exit Relay Mode](#exit-relay-mode)
- [obfs4 Bridge Mode](#obfs4-bridge-mode)
- [Configuration Methods](#configuration-methods)
- [Environment Variables Reference](#environment-variables-reference)
- [Switching Modes](#switching-modes)
- [Troubleshooting](#troubleshooting)
---
## Overview
The Tor Guard Relay container now supports **three relay modes**:
| Mode | Purpose | Public Visibility | Legal Risk | Bandwidth Needs |
|------|---------|------------------|------------|-----------------|
| **Guard/Middle** | Entry/routing relay | High | Low | Medium-High |
| **Exit** | Exit traffic to internet | High | **HIGH** | High |
| **Bridge** | Help censored users | Hidden | Low | Low-Medium |
### Key Features
-**Dynamic Configuration** - Generate config from environment variables
-**obfs4 Support** - Pluggable transport for bridges
-**Backwards Compatible** - Still supports mounting config files
-**Secure Defaults** - Guard/middle as default mode
---
## Mode Comparison
### Guard/Middle Relay (Default)
**What it does:**
- Acts as entry point (guard) or routing node (middle) in Tor circuits
- Does NOT handle exit traffic to the internet
- Published in the main Tor directory
**Best for:**
- Operators who want to contribute without legal complexity
- Stable, high-bandwidth connections
- Long-term operation (8+ days to earn Guard flag)
**Requirements:**
- Public IP with ports 9001, 9030 accessible
- Stable uptime (99%+ recommended)
- 10+ Mbps bandwidth recommended
### Exit Relay
**What it does:**
- Allows Tor traffic to exit to the internet
- Your IP is associated with all exit traffic
- Published in the main Tor directory
**Best for:**
- Experienced operators who understand legal implications
- Datacenters with abuse handling
- Dedicated servers/IPs
**⚠️ CRITICAL REQUIREMENTS:**
- **Understand legal risks** - read [EFF Tor Legal FAQ](https://community.torproject.org/relay/community-resources/eff-tor-legal-faq/)
- Prepare for abuse complaints
- Inform your ISP
- Set up abuse@ email address
- Have legal resources available
- Use dedicated IP/server
### obfs4 Bridge
**What it does:**
- Helps users in censored countries connect to Tor
- NOT published in main directory (distributed via BridgeDB)
- Uses obfs4 to make traffic look random
**Best for:**
- Operators in non-censored countries
- Lower bandwidth contributions
- Helping circumvent censorship
**Requirements:**
- Stable IP with ports 9001, 9002 accessible
- Less bandwidth than relays (10+ Mbps sufficient)
- Not blocked by censors in target countries
---
## Guard/Middle Relay Mode
### Quick Start with Environment Variables
```bash
docker run -d \
--name tor-guard-relay \
--network host \
--restart unless-stopped \
-e TOR_RELAY_MODE=guard \
-e TOR_NICKNAME=MyGuardRelay \
-e TOR_CONTACT_INFO="your-email@example.com" \
-e TOR_BANDWIDTH_RATE="50 MBytes" \
-e TOR_BANDWIDTH_BURST="100 MBytes" \
-v tor-guard-data:/var/lib/tor \
-v tor-guard-logs:/var/log/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
### Docker Compose
```yaml
version: '3.8'
services:
tor-guard-relay:
image: ghcr.io/r3bo0tbx1/onion-relay:latest
container_name: tor-guard-relay
restart: unless-stopped
network_mode: host
environment:
TOR_RELAY_MODE: guard
TOR_NICKNAME: MyGuardRelay
TOR_CONTACT_INFO: "your-email@example.com"
TOR_BANDWIDTH_RATE: "50 MBytes"
TOR_BANDWIDTH_BURST: "100 MBytes"
volumes:
- tor-guard-data:/var/lib/tor
- tor-guard-logs:/var/log/tor
volumes:
tor-guard-data:
tor-guard-logs:
```
Save as `docker-compose.yml` and run:
```bash
docker-compose up -d
```
### Verification
```bash
# Check status
docker exec tor-guard-relay status
# View logs
docker logs -f tor-guard-relay
# Get fingerprint
docker exec tor-guard-relay fingerprint
```
---
## Exit Relay Mode
### ⚠️ Before You Start
**READ THIS FIRST:**
1. [EFF Tor Legal FAQ](https://community.torproject.org/relay/community-resources/eff-tor-legal-faq/)
2. [Tor Abuse Response Templates](https://community.torproject.org/relay/community-resources/tor-abuse-templates/)
3. [Good/Bad ISPs for Exit Relays](https://community.torproject.org/relay/community-resources/good-bad-isps/)
**Exit Relay Checklist:**
- [ ] Read and understand legal implications
- [ ] Prepared to handle abuse complaints
- [ ] Informed ISP (recommended)
- [ ] Set up abuse@ email address
- [ ] Using dedicated IP/server
- [ ] Have abuse response template ready
- [ ] Have legal resources available if needed
### Quick Start
```bash
docker run -d \
--name tor-exit-relay \
--network host \
--restart unless-stopped \
-e TOR_RELAY_MODE=exit \
-e TOR_NICKNAME=MyExitRelay \
-e TOR_CONTACT_INFO="your-email@example.com <0xPGP_KEY>" \
-e TOR_BANDWIDTH_RATE="50 MBytes" \
-e TOR_BANDWIDTH_BURST="100 MBytes" \
-v tor-exit-data:/var/lib/tor \
-v tor-exit-logs:/var/log/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
### Exit Policy
By default, uses the **Reduced Exit Policy** (Tor Project recommended):
- Allows common services (HTTP, HTTPS, SSH, email, etc.)
- Blocks high-risk ports
- Good starting point for exit operators
**Custom Exit Policy:**
```bash
-e TOR_EXIT_POLICY="accept *:80,accept *:443,reject *:*"
```
**More restrictive (HTTPS only):**
```bash
-e TOR_EXIT_POLICY="accept *:443,reject *:*"
```
### Docker Compose
See [templates/docker-compose-exit.yml](../templates/docker-compose-exit.yml) for complete example.
### Handling Abuse Complaints
**Standard Response Template:**
```
This is a Tor exit relay (https://www.torproject.org/).
The IP address you reported is not the source of the activity.
Tor is an anonymity network that helps people protect their
privacy and security online.
For more information about Tor and exit relays:
- What is Tor: https://www.torproject.org/about/overview.html
- Tor and abuse: https://blog.torproject.org/blog/tips-running-exit-node
If you have concerns about specific traffic, please contact
the destination website directly. The exit relay operator
does not control the traffic passing through the relay.
Contact: your-email@example.com
```
---
## obfs4 Bridge Mode
### Quick Start
```bash
docker run -d \
--name tor-bridge \
--network host \
--restart unless-stopped \
-e TOR_RELAY_MODE=bridge \
-e TOR_NICKNAME=MyTorBridge \
-e TOR_CONTACT_INFO="your-email@example.com" \
-e TOR_ORPORT=9001 \
-e TOR_OBFS4_PORT=9002 \
-e TOR_BANDWIDTH_RATE="10 MBytes" \
-e TOR_BANDWIDTH_BURST="20 MBytes" \
-v tor-bridge-data:/var/lib/tor \
-v tor-bridge-logs:/var/log/tor \
ghcr.io/r3bo0tbx1/onion-relay:latest
```
### Docker Compose
See [templates/docker-compose-bridge.yml](../templates/docker-compose-bridge.yml) for complete example.
### Getting Your Bridge Line
**After 24-48 hours**, your bridge will be registered and you can get the bridge line:
```bash
# Method 1: Check pt_state directory
docker exec tor-bridge cat /var/lib/tor/pt_state/obfs4_bridgeline.txt
# Method 2: Search logs
docker exec tor-bridge grep "bridge line" /var/log/tor/notices.log
# Method 3: Check pt_state directory contents
docker exec tor-bridge ls -la /var/lib/tor/pt_state/
```
Output will look like:
```
Bridge obfs4 <IP>:<PORT> <FINGERPRINT> cert=<CERT> iat-mode=0
```
### Sharing Your Bridge
**IMPORTANT:**
- Only share with people you trust
- Do NOT publish publicly (defeats the purpose)
- Users can also request bridges from [BridgeDB](https://bridges.torproject.org/)
### Verification
```bash
# Check if obfs4proxy is running
docker exec tor-bridge pgrep -a obfs4proxy
# Check bridge status
docker exec tor-bridge status
```
---
## Configuration Methods
The container supports **two configuration methods**:
### Method 1: Environment Variables (Recommended for Simple Setups)
**Pros:**
✓ No config file to maintain
✓ Easy to change settings
✓ Good for simple setups
✓ Works well with orchestration tools
**Cons:**
✗ Less flexible for advanced options
✗ Cannot set all possible Tor directives
**Example:**
```bash
docker run -d \
-e TOR_RELAY_MODE=guard \
-e TOR_NICKNAME=MyRelay \
-e TOR_CONTACT_INFO="email@example.com" \
...
```
### Method 2: Config File Mount (Advanced)
**Pros:**
✓ Full control over Tor configuration
✓ Can use any Tor directive
✓ Better for complex setups
**Cons:**
✗ Need to maintain config file
✗ Less portable
**Example:**
```bash
docker run -d \
-v $(pwd)/relay.conf:/etc/tor/torrc:ro \
...
```
### Can I Use Both?
Yes! If you mount a config file, it takes precedence over environment variables.
The container will detect the mounted file and skip dynamic config generation.
---
## Environment Variables Reference
### Core Configuration
| Variable | Default | Description |
|----------|---------|-------------|
| `TOR_RELAY_MODE` | `guard` | Relay mode: `guard`, `exit`, or `bridge` |
| `TOR_NICKNAME` | _(required)_ | Relay nickname (1-19 alphanumeric chars) |
| `TOR_CONTACT_INFO` | _(required)_ | Contact email (+ optional PGP key) |
### Network Ports
| Variable | Default | Description |
|----------|---------|-------------|
| `TOR_ORPORT` | `9001` | Tor connection port |
| `TOR_DIRPORT` | `9030` | Directory service port (not used for bridges) |
| `TOR_OBFS4_PORT` | `9002` | obfs4 pluggable transport port (bridges only) |
### Bandwidth
| Variable | Default | Description |
|----------|---------|-------------|
| `TOR_BANDWIDTH_RATE` | _(none)_ | Sustained bandwidth (e.g., `50 MBytes`) |
| `TOR_BANDWIDTH_BURST` | _(none)_ | Burst bandwidth (e.g., `100 MBytes`) |
### Exit Policy (Exit Mode Only)
| Variable | Default | Description |
|----------|---------|-------------|
| `TOR_EXIT_POLICY` | Reduced Exit Policy | Custom exit policy (comma-separated) |
Example: `TOR_EXIT_POLICY="accept *:80,accept *:443,reject *:*"`
### Advanced
| Variable | Default | Description |
|----------|---------|-------------|
| `TOR_DATA_DIR` | `/var/lib/tor` | Tor data directory |
| `TOR_LOG_DIR` | `/var/log/tor` | Tor log directory |
| `TOR_CONFIG` | `/etc/tor/torrc` | Tor configuration file path |
| `DEBUG` | `false` | Enable debug output |
---
## Switching Modes
You can switch between modes by changing `TOR_RELAY_MODE` and restarting:
### From Guard to Exit
```bash
docker stop tor-relay
docker rm tor-relay
docker run -d \
--name tor-relay \
-e TOR_RELAY_MODE=exit \
-e TOR_NICKNAME=MyExitRelay \
... # Same volumes
```
**⚠️ WARNING:** Switching to exit mode has legal implications. Read the Exit Relay section first.
### From Guard to Bridge
```bash
docker stop tor-relay
docker rm tor-relay
docker run -d \
--name tor-relay \
-e TOR_RELAY_MODE=bridge \
-e TOR_NICKNAME=MyBridge \
-e TOR_OBFS4_PORT=9002 \
... # Same volumes
```
**Note:** Your relay will get a new identity when switching modes.
---
## Troubleshooting
### Configuration Not Generating
**Symptom:** Container starts but uses placeholder config
**Solution:**
1. Make sure no config file is mounted at `/etc/tor/torrc`
2. Set required environment variables:
- `TOR_NICKNAME`
- `TOR_CONTACT_INFO`
3. Check logs: `docker logs <container>`
### Bridge Line Not Appearing
**Symptom:** Bridge line file doesn't exist after 24+ hours
**Solution:**
1. Check both ports are accessible: `9001` and `9002`
2. Verify obfs4proxy is running: `docker exec <container> pgrep obfs4proxy`
3. Check logs for obfs4proxy errors: `docker logs <container> | grep obfs4`
4. Wait 48 hours - bridge distribution takes time
### Exit Relay - Too Many Abuse Complaints
**Symptom:** Receiving excessive abuse complaints
**Solutions:**
1. Switch to more restrictive exit policy (HTTPS only)
2. Consider running as guard relay instead
3. Check if your ISP supports exit relays: [Good/Bad ISPs](https://community.torproject.org/relay/community-resources/good-bad-isps/)
4. Use abuse complaint template to respond efficiently
### Ports Not Accessible
**Symptom:** `ORPort not reachable` in status
**Solution:**
```bash
# Check firewall
sudo ufw status
# Open required ports
sudo ufw allow 9001/tcp
sudo ufw allow 9030/tcp # Guards/exits only
sudo ufw allow 9002/tcp # Bridges only
# Test from outside
nc -zv <your-ip> 9001
```
### Low/No Traffic
**Symptom:** Relay shows very little bandwidth usage
**Normal for:**
- New relays (2-8 weeks to build reputation)
- Bridges (intentionally low visibility)
- Guards without Guard flag (need 8+ days uptime)
**Check:**
1. Verify relay is reachable: `docker exec <container> status`
2. Check Tor Metrics: https://metrics.torproject.org/rs.html
3. Ensure adequate bandwidth: `TOR_BANDWIDTH_RATE`
---
## Resources
### Official Tor Project
- [Relay Setup Guide](https://community.torproject.org/relay/setup/)
- [Bridge Setup Guide](https://community.torproject.org/relay/setup/bridge/)
- [Relay Requirements](https://community.torproject.org/relay/relays-requirements/)
- [Tor Metrics](https://metrics.torproject.org/)
- [BridgeDB](https://bridges.torproject.org/)
### Legal & Compliance
- [EFF Tor Legal FAQ](https://community.torproject.org/relay/community-resources/eff-tor-legal-faq/)
- [Abuse Response Templates](https://community.torproject.org/relay/community-resources/tor-abuse-templates/)
- [Good/Bad ISPs](https://community.torproject.org/relay/community-resources/good-bad-isps/)
### Technical Documentation
- [obfs4 Specification](https://gitlab.com/yawning/obfs4)
- [Tor Manual](https://2019.www.torproject.org/docs/tor-manual.html.en)
### This Project
- [Main README](../README.md)
- [Deployment Guide](DEPLOYMENT.md)
- [Tools Documentation](TOOLS.md)
- [Monitoring Guide](MONITORING.md)
---
**Made with 💜 for a freer, uncensored internet**
*Protecting privacy, one relay at a time* 🧅✨

View File

@@ -346,38 +346,65 @@ time docker exec guard-relay tor --resolve example.com
## Monitoring & Metrics
### 1. Enable Prometheus Metrics
v1.1.1 uses **external monitoring** with the `health` JSON API for minimal image size and maximum security.
**In docker-compose.yml:**
### 1. JSON Health API
```yaml
services:
tor-guard-relay:
environment:
- "ENABLE_METRICS=true"
- "METRICS_PORT=9035"
```
**Or in relay.conf:**
```conf
# Prometheus metrics port
# MetricsPort 9035
```
### 2. Access Metrics Endpoint
Get relay metrics via the `health` tool:
```bash
# Pull metrics
curl http://localhost:9035/metrics
# Get full health status (raw JSON)
docker exec guard-relay health
# Example output:
# tor_relay_bandwidth_read_bytes 1234567890
# tor_relay_bandwidth_write_bytes 1987654321
# tor_relay_connections 234
# Parse with jq (requires jq on host)
docker exec guard-relay health | jq .
# Check specific metrics
docker exec guard-relay health | jq .bootstrap # Bootstrap percentage
docker exec guard-relay health | jq .reachable # ORPort reachability
docker exec guard-relay health | jq .uptime_seconds # Uptime
```
### 3. Set Up Prometheus Monitoring
**Example JSON output:**
```json
{
"status": "up",
"bootstrap": 100,
"reachable": true,
"fingerprint": "1234567890ABCDEF...",
"nickname": "MyRelay",
"uptime_seconds": 86400
}
```
### 2. Prometheus Integration (External)
Use the `health` tool with Prometheus node_exporter textfile collector:
**Create metrics exporter script:**
```bash
#!/bin/bash
# /usr/local/bin/tor-metrics-exporter.sh
# Requires: jq on host (apt install jq / brew install jq)
HEALTH=$(docker exec guard-relay health)
echo "$HEALTH" | jq -r '
"tor_bootstrap_percent \(.bootstrap)",
"tor_reachable \(if .reachable then 1 else 0 end)",
"tor_uptime_seconds \(.uptime_seconds // 0)"
' > /var/lib/node_exporter/textfile_collector/tor.prom
```
**Run via cron every 5 minutes:**
```bash
chmod +x /usr/local/bin/tor-metrics-exporter.sh
crontab -e
*/5 * * * * /usr/local/bin/tor-metrics-exporter.sh
```
### 3. Set Up Prometheus Scraping
**prometheus.yml:**
@@ -386,7 +413,7 @@ global:
scrape_interval: 15s
scrape_configs:
- job_name: 'tor-relay'
- job_name: 'node_exporter' # Scrapes textfile collector
static_configs:
- targets: ['localhost:9035']
metrics_path: '/metrics'
@@ -548,7 +575,9 @@ docker exec guard-relay grep "RelayBandwidth" /etc/tor/torrc
docker logs guard-relay 2>&1 | grep "Average"
# Verify ORPort is reachable
docker exec guard-relay relay-status | grep "reachable"
docker exec guard-relay status | grep "reachable"
# Or use JSON health check
docker exec guard-relay health | jq .reachable
```
**Solutions:**

View File

@@ -1,22 +1,17 @@
# 🛠️ Tools Reference Guide
**Tor Guard Relay v1.1** includes a comprehensive suite of diagnostic and management tools built directly into the container. All tools are Alpine-compatible, executable without file extensions, and designed for production use.
**Tor Guard Relay v1.1.1** includes 4 essential diagnostic tools built directly into the ultra-optimized ~20 MB container. All tools are busybox-compatible, executable without file extensions, and designed for production use.
---
## 📋 Tool Overview
| Tool | Purpose | Output Format | ENV Variables |
|------|---------|---------------|---------------|
| **status** | Complete relay health report | Text (emoji) | None |
| **fingerprint** | Display relay fingerprint | Text | None |
| **health** | JSON health diagnostics | JSON | None |
| **metrics** | Prometheus metrics | Prometheus | `RELAY_NICKNAME` |
| **metrics-http** | HTTP metrics server | HTTP | `METRICS_PORT` |
| **dashboard** | Live HTML dashboard | HTML | None |
| **setup** | Interactive config wizard | Interactive | All Tor vars |
| **net-check** | Network diagnostics | Text (emoji) | None |
| **view-logs** | Live log streaming | Text | `TOR_LOG_DIR` |
| Tool | Purpose | Output Format | Notes |
|------|---------|---------------|-------|
| **status** | Complete relay health report | Text (emoji) | Full diagnostic dashboard |
| **health** | JSON health diagnostics | JSON | Machine-readable for monitoring |
| **fingerprint** | Display relay fingerprint | Text | With Tor Metrics link |
| **bridge-line** | Get obfs4 bridge line | Text | Bridge mode only |
---
@@ -24,7 +19,7 @@
### `status`
**Purpose:** Comprehensive relay health and status report
**Purpose:** Comprehensive relay health and status report with emoji formatting
**Usage:**
```bash
@@ -33,35 +28,79 @@ docker exec tor-relay status
**Output Example:**
```
🧅 Tor Relay Status Report
═══════════════════════════════════
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🧅 Tor Relay Status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Build Information
Version: v1.1
Build Date: 2025-11-04
Architecture: amd64
🚀 Status: RUNNING (PID: 123)
✅ Bootstrap: 100% COMPLETE
🌐 ORPort: REACHABLE
🪪 Nickname: MyGuardRelay
🔑 Fingerprint: ABCD1234...WXYZ9876
✅ Errors: 0
⏱️ Uptime: 2d 14h 30m
🚀 Bootstrap Progress
Status: ✅ Complete (100%)
Circuits: 3 active
🔗 Network Status
ORPort: ✅ Reachable (9001)
Public IP: 203.0.113.42
📊 Performance
Uptime: 2d 14h 30m
Bandwidth: 50 MB/s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💡 Tip: Use 'docker logs -f <container>' for live logs
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
**Environment Variables:** None required
**Exit Codes:**
- `0` - Status retrieved successfully
- `1` - Tor service not running or error
---
### `health`
**Purpose:** Machine-readable JSON health check for monitoring systems and automation
**Usage:**
```bash
docker exec tor-relay health
# Parse with jq
docker exec tor-relay health | jq .status
```
**Output Example:**
```json
{
"status": "up",
"pid": 123,
"uptime": "2d 14h 30m",
"bootstrap": 100,
"reachable": "true",
"errors": 0,
"nickname": "MyGuardRelay",
"fingerprint": "ABCD1234567890ABCDEF1234567890ABCDEFGHIJ"
}
```
**Status Values:**
- `up` - Relay is running and healthy
- `down` - Relay is not running
- `error` - Critical issues detected
**Exit Codes:**
- `0` - Health check completed
- `1` - Critical error or Tor not running
**Integration Example:**
```bash
#!/bin/bash
# Simple health monitoring script
HEALTH=$(docker exec tor-relay health)
STATUS=$(echo "$HEALTH" | jq -r '.status')
if [ "$STATUS" != "up" ]; then
echo "ALERT: Relay is $STATUS"
# Send notification
fi
```
---
### `fingerprint`
**Purpose:** Display relay fingerprint with direct links to Tor Metrics
@@ -73,274 +112,71 @@ docker exec tor-relay fingerprint
**Output Example:**
```
🔑 Tor Relay Fingerprint
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔑 Relay Fingerprint
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Nickname: MyTorRelay
Fingerprint: 1234 5678 90AB CDEF 1234 5678 90AB CDEF 1234 5678
🪪 Nickname: MyTorRelay
🔑 Fingerprint: ABCD 1234 5678 90AB CDEF 1234 5678 90AB CDEF 1234
🔗 Tor Metrics: https://metrics.torproject.org/rs.html#details/123456...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔗 Tor Metrics: https://metrics.torproject.org/rs.html#details/ABCD...
💡 Your relay will appear in Tor Metrics after 1-2 hours
```
**Environment Variables:** None required
**Exit Codes:**
- `0` - Fingerprint retrieved
- `1` - Fingerprint not yet available (bootstrapping)
- `1` - Fingerprint not yet available (still bootstrapping)
**When Available:**
- Guard/Middle relays: ~1-2 hours after first start
- Exit relays: ~1-2 hours after first start
- Bridges: Not published publicly (by design)
---
### `health`
### `bridge-line`
**Purpose:** Machine-readable JSON health check for monitoring systems
**Purpose:** Get the obfs4 bridge line for sharing with users (bridge mode only)
**Usage:**
```bash
docker exec tor-relay health
```
**Output Example:**
```json
{
"status": "healthy",
"uptime": 214830,
"bootstrap": {
"percent": 100,
"status": "Done"
},
"timestamp": "2025-11-04T12:30:45Z",
"relay_info": {
"nickname": "MyTorRelay",
"fingerprint": "1234567890ABCDEF...",
"or_port": 9001,
"dir_port": 9030
},
"network": {
"or_port_reachable": true,
"dir_port_reachable": true,
"public_ip": "203.0.113.42"
},
"issues": {
"errors": 0,
"warnings": 0
}
}
```
**Environment Variables:** None required
**Status Values:**
- `healthy` - All systems operational
- `warning` - Minor issues detected
- `error` - Critical issues present
- `bootstrapping` - Still connecting to Tor network
**Exit Codes:**
- `0` - Health check completed
- `1` - Critical error or Tor not running
---
### `metrics`
**Purpose:** Generate Prometheus-format metrics for monitoring
**Usage:**
```bash
docker exec tor-relay metrics
```
**Output Example:**
```prometheus
# HELP tor_relay_uptime_seconds Relay uptime in seconds
# TYPE tor_relay_uptime_seconds gauge
tor_relay_uptime_seconds{relay_name="MyTorRelay"} 214830
# HELP tor_relay_bootstrap_percent Bootstrap completion percentage
# TYPE tor_relay_bootstrap_percent gauge
tor_relay_bootstrap_percent{relay_name="MyTorRelay"} 100
# HELP tor_relay_or_port_reachable ORPort reachability status
# TYPE tor_relay_or_port_reachable gauge
tor_relay_or_port_reachable{relay_name="MyTorRelay",port="9001"} 1
# HELP tor_relay_bandwidth_rate_bytes Configured bandwidth rate
# TYPE tor_relay_bandwidth_rate_bytes gauge
tor_relay_bandwidth_rate_bytes{relay_name="MyTorRelay"} 52428800
```
**Environment Variables:**
- `RELAY_NICKNAME` - Sets the relay name label in metrics (optional)
**Exit Codes:**
- `0` - Metrics generated
- `1` - Error generating metrics
---
### `metrics-http`
**Purpose:** HTTP server for exposing Prometheus metrics
**Usage:**
```bash
# Start metrics HTTP server (runs in background)
metrics-http 9035
# Access metrics endpoint
curl http://localhost:9035/metrics
```
**Environment Variables:**
- `METRICS_PORT` - Port to listen on (default: 9035)
**Endpoints:**
- `GET /metrics` - Prometheus metrics
- `GET /health` - Health check endpoint
- `GET /` - Simple status page
**Exit Codes:**
- `0` - Server running
- `1` - Port already in use or error
**Note:** Automatically started by docker-entrypoint.sh if `ENABLE_METRICS=true`
---
### `dashboard`
**Purpose:** Interactive HTML dashboard with real-time relay status
**Usage:**
```bash
# Generate dashboard HTML
docker exec tor-relay dashboard > dashboard.html
# Or access via HTTP if metrics-http is running
curl http://localhost:9035/dashboard
```
**Features:**
- Real-time bootstrap progress
- Network reachability status
- Performance metrics visualization
- Quick action buttons
- Auto-refresh every 30 seconds
**Environment Variables:** None required
**Browser Access:**
When `metrics-http` is running, access dashboard at:
`http://<server-ip>:9035/dashboard`
---
### `setup`
**Purpose:** Interactive wizard for generating relay configuration
**Usage:**
```bash
docker exec -it tor-relay setup
```
**Interactive Prompts:**
1. Relay Nickname
2. Contact Information (email)
3. ORPort (default: 9001)
4. DirPort (default: 9030)
5. Bandwidth Rate (MB/s)
6. Bandwidth Burst (MB/s)
7. IPv6 support (yes/no)
8. Exit policy (guard/middle only)
**Output:** Generates `/etc/tor/torrc` or outputs to stdout
**Environment Variables:**
- `TOR_CONFIG` - Config file path (default: /etc/tor/torrc)
- All standard Tor environment variables
**Exit Codes:**
- `0` - Configuration created successfully
- `1` - Invalid input or error
---
### `net-check`
**Purpose:** Comprehensive network diagnostics for relay troubleshooting
**Usage:**
```bash
docker exec tor-relay net-check
docker exec tor-bridge bridge-line
```
**Output Example:**
```
🌐 Network Diagnostics Report
════════════════════════════════════
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🌉 obfs4 Bridge Line
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ IPv4 Connectivity: OK (203.0.113.42)
✅ IPv6 Connectivity: OK (2001:db8::1)
✅ DNS Resolution: OK
✅ Tor Consensus: Reachable
✅ ORPort 9001: OPEN
✅ DirPort 9030: OPEN
Bridge obfs4 203.0.113.42:9002 ABCD...WXYZ cert=abc123...xyz789 iat-mode=0
🔍 Diagnostic Details:
• Public IPv4: 203.0.113.42
• Public IPv6: 2001:db8::1
DNS Resolver: 1.1.1.1
Tor Authority: 128.31.0.34:9131 (reachable)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 Sharing Guidelines:
Only share with people you trust
Do NOT publish publicly
• Helps users in censored countries
💡 Bridge line available 24-48 hours after first start
```
**Checks Performed:**
- IPv4 connectivity and public IP detection
- IPv6 connectivity and public IP detection (if enabled)
- DNS resolution (multiple resolvers)
- Tor directory authority connectivity
- ORPort reachability (internal and external)
- DirPort reachability (internal and external)
**Environment Variables:** None required
**Exit Codes:**
- `0` - All checks passed
- `1` - One or more checks failed
- `0` - Bridge line retrieved
- `1` - Bridge line not yet available or not in bridge mode
---
**When Available:**
- Bridges take 24-48 hours after first start to generate the bridge line
- The bridge line is stored in `/var/lib/tor/pt_state/obfs4_bridgeline.txt`
- Also visible in logs: `docker logs <container> | grep "bridge line"`
### `view-logs`
**Purpose:** Stream Tor relay logs with optional filtering
**Usage:**
```bash
# View last 50 lines
docker exec tor-relay view-logs
# Follow logs in real-time
docker exec tor-relay view-logs -f
# Filter for errors only
docker exec tor-relay view-logs --errors
# Filter for warnings and errors
docker exec tor-relay view-logs --warn
```
**Options:**
- `-f, --follow` - Follow log output (like tail -f)
- `-n <lines>` - Show last N lines (default: 50)
- `--errors` - Show only ERROR level messages
- `--warn` - Show WARNING and ERROR messages
- `--bootstrap` - Show only bootstrap-related messages
**Environment Variables:**
- `TOR_LOG_DIR` - Log directory path (default: /var/log/tor)
**Exit Codes:**
- `0` - Logs displayed successfully
- `1` - Log file not found or error
**Important:**
- Only works in bridge mode (`TOR_RELAY_MODE=bridge`)
- Requires persistent volumes for `/var/lib/tor`
- Bridge addresses are NOT published in public directories
---
@@ -348,52 +184,65 @@ docker exec tor-relay view-logs --warn
### 1. Quick Health Check
```bash
# Simple status check
# Visual status check
docker exec tor-relay status
# JSON health check for automation
docker exec tor-relay health | jq .status
# Check bootstrap progress
docker exec tor-relay health | jq .bootstrap
```
### 2. Setup Prometheus Monitoring
### 2. Find Your Relay on Tor Metrics
```bash
# Start metrics HTTP server
docker exec tor-relay metrics-http 9035 &
# Configure Prometheus to scrape:
# http://<relay-ip>:9035/metrics
```
### 3. Troubleshoot Network Issues
```bash
# Run comprehensive network diagnostics
docker exec tor-relay net-check
# Check relay fingerprint and Metrics link
# Get fingerprint and metrics link
docker exec tor-relay fingerprint
# View recent errors
docker exec tor-relay view-logs --errors | tail -20
# Wait 1-2 hours after first start
# Click the Tor Metrics link or search manually
```
### 4. Monitor Bootstrap Progress
### 3. Share Your Bridge
```bash
# Watch bootstrap in real-time
watch -n 5 'docker exec tor-relay health | jq .bootstrap'
# Get bridge line (bridge mode only)
docker exec tor-bridge bridge-line
# Or use status tool
docker exec tor-relay status | grep Bootstrap
# Wait 24-48 hours after first start
# Share ONLY with trusted users, NOT publicly
```
### 5. Generate Configuration
### 4. Automated Monitoring
```bash
# Interactive setup
docker exec -it tor-relay setup
# Simple monitoring script
while true; do
STATUS=$(docker exec tor-relay health | jq -r '.status')
BOOTSTRAP=$(docker exec tor-relay health | jq -r '.bootstrap')
# Or use environment variables
docker run -e RELAY_NICKNAME=MyRelay \
-e RELAY_CONTACT=admin@example.com \
ghcr.io/r3bo0tbx1/onion-relay:latest
echo "[$(date)] Status: $STATUS | Bootstrap: $BOOTSTRAP%"
if [ "$STATUS" != "up" ]; then
# Send alert
echo "ALERT: Relay is down!"
fi
sleep 60
done
```
### 5. Check Logs
```bash
# View recent logs
docker logs --tail 100 tor-relay
# Follow logs in real-time
docker logs -f tor-relay
# Filter for errors
docker logs tor-relay 2>&1 | grep -i error
# Filter for warnings
docker logs tor-relay 2>&1 | grep -i warn
```
---
@@ -401,10 +250,10 @@ docker run -e RELAY_NICKNAME=MyRelay \
## 🔐 Security Notes
- All tools run as non-root `tor` user
- No tools write to disk (except setup when instructed)
- Metrics expose no sensitive data
- Dashboard can be password-protected via reverse proxy
- Logs contain no sensitive user data (Tor privacy design)
- Tools are read-only and don't modify relay state
- No sensitive data exposed (fingerprints are public by design)
- Bridge lines should be shared privately, not published
- Logs contain no user traffic data (Tor privacy design)
---
@@ -412,62 +261,100 @@ docker run -e RELAY_NICKNAME=MyRelay \
### Tool not found
```bash
# Verify tool exists and is executable
# Verify tools exist
docker exec tor-relay ls -la /usr/local/bin/
# Should show: status, health, fingerprint, bridge-line
# Check PATH
docker exec tor-relay echo $PATH
```
### Permission denied
```bash
# Should not happen - tools auto-fixed by entrypoint
# If it does, check Dockerfile COPY command
# Manual fix (shouldn't be needed):
docker exec -u root tor-relay chmod +x /usr/local/bin/*
# Should not happen - tools are set to +x in Dockerfile
# If it does, rebuild image:
docker build --no-cache -t tor-relay:latest .
```
### Empty or error output
### Empty output or errors
```bash
# Check if Tor is running
docker exec tor-relay pgrep tor
docker exec tor-relay ps aux | grep tor
# Check logs for errors
docker exec tor-relay view-logs --errors
docker logs tor-relay | tail -50
# Restart container
docker restart tor-relay
```
### Metrics HTTP server fails to start
### Fingerprint not available
```bash
# Check if port is in use
docker exec tor-relay netstat -tulpn | grep 9035
# Normal during bootstrap (first 5-15 minutes)
# Check bootstrap progress
docker exec tor-relay health | jq .bootstrap
# Try different port
docker exec tor-relay metrics-http 9036
# Wait for 100% bootstrap
docker logs tor-relay | grep "Bootstrapped 100%"
```
### Bridge line not available
```bash
# Normal for first 24-48 hours
# Check if in bridge mode
docker exec tor-relay grep BridgeRelay /etc/tor/torrc
# Check for obfs4 files
docker exec tor-relay ls -la /var/lib/tor/pt_state/
# Check logs
docker logs tor-relay | grep -i obfs4
```
---
## 💡 Tips & Best Practices
1. **Use `health` for automation** - JSON output is perfect for scripts and monitoring systems
2. **Check `status` during troubleshooting** - Human-readable format with emoji makes issues obvious
3. **Save your fingerprint** - Store it somewhere safe for relay tracking
4. **Monitor bootstrap** - New relays take 5-15 minutes to fully bootstrap
5. **Be patient with bridges** - Bridge lines take 24-48 hours to generate
6. **Use docker logs** - Built-in logging is comprehensive and easier than installing extra tools
7. **Keep it simple** - This minimal toolset covers 99% of relay operation needs
---
## 📚 Related Documentation
- [Deployment Guide](./DEPLOYMENT.md) - Installation and configuration
- [Monitoring Guide](./MONITORING.md) - Prometheus and Grafana setup
- [Multi-Mode Guide](./MULTI-MODE.md) - Guard, Exit, and Bridge modes
- [Backup Guide](./BACKUP.md) - Data persistence and recovery
- [Performance Guide](./PERFORMANCE.md) - Optimization tips
---
## 💡 Tips
## ❓ FAQ
1. **Automation**: Use `health` tool's JSON output for monitoring scripts
2. **Monitoring**: Always enable `metrics-http` for production relays
3. **Diagnostics**: Run `net-check` after any network configuration changes
4. **Logs**: Use `view-logs --follow` during initial bootstrap
5. **Dashboard**: Useful for at-a-glance status without CLI
**Q: Why only 4 tools instead of 9?**
A: The v1.1.1 build prioritizes size optimization (~20 MB vs 45+ MB). These 4 tools cover all essential operations. For advanced monitoring, use external tools like Prometheus.
**Q: Where are metrics/monitoring endpoints?**
A: Removed to achieve ultra-small image size. Use `health` tool with external monitoring systems or check `/var/log/tor/notices.log` directly.
**Q: Can I still use Prometheus?**
A: Yes! Export logs or use `health` JSON output with a Prometheus exporter. See [MONITORING.md](./MONITORING.md) for alternatives.
**Q: What happened to the dashboard?**
A: Removed (required Python/Flask). Use `status` tool for visual output or build your own dashboard using `health` JSON.
---
**Last Updated:** November 2025 | **Version:** 1.1
**Last Updated:** November 2025 | **Version:** 1.1.1

View File

@@ -0,0 +1,508 @@
# Troubleshooting Bridge Migration to v1.1.1
This guide addresses the specific issue where migrating from `thetorproject/obfs4-bridge` to `r3bo0tbx1/onion-relay:1.1.1` results in configuration validation failures and changing fingerprints.
## Problem Description
### Symptoms
1. **Container crash loop** with these logs:
```
✅ Using mounted configuration: /etc/tor/torrc
🛑 Configuration validation failed!
🛑 ERROR: Invalid Tor configuration. Set DEBUG=true for details.
```
2. **Fingerprints changing on every restart** - CRITICAL issue indicating bridge identity loss:
```
2025-11-12 17:45:45: CD2A0C40DA625C943A2174171D18AFF2849328DC
2025-11-12 17:50:18: 5895203866064C4270F909BE4327B43AA5E5D44A
2025-11-12 17:58:31: D059C6613DB06B256AD488859659A9A605E8643B
```
### Root Cause
The `thetorproject/obfs4-bridge` image creates a `torrc` file that may persist in the Docker volume or get recreated. When you migrate to `r3bo0tbx1/onion-relay:1.1.1`, the entrypoint script checks for existing configuration files with this priority:
1. **Priority 1**: Existing `/etc/tor/torrc` file (mounted or in volume)
2. **Priority 2**: Environment variables (OR_PORT, PT_PORT, EMAIL, NICKNAME)
If an old `torrc` exists, v1.1.1 tries to use it but it may be:
- Incompatible format
- Using different paths
- Missing required directives for v1.1.1 validation
The **changing fingerprints** indicate an even more serious issue: the `/var/lib/tor/keys/` directory is being lost, meaning your bridge identity is being regenerated each time.
## Emergency Fix Procedure
### Step 1: Run Diagnostic Script
We've provided a comprehensive diagnostic script that will:
- Check if your volume exists
- Verify Tor identity keys are preserved
- Find and remove incompatible torrc files
- Create a backup of your current volume
- Extract your current fingerprint
**Run this first:**
```bash
# Make sure you're in the tor-guard-relay directory
cd /path/to/tor-guard-relay
# Run the diagnostic script
./bridge-migration-fix.sh
```
**Expected output:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 Bridge Migration Emergency Fix
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1: Checking container status...
✅ Container found
Step 2: Inspecting volume obfs4-data...
✅ Volume exists
Volume mountpoint: /var/lib/docker/volumes/obfs4-data/_data
Step 3: Checking volume contents...
📁 Volume contents:
drwxr-xr-x 5 tor tor 4096 Nov 12 17:45 .
drwxr-xr-x 3 root root 4096 Nov 12 17:40 ..
drwx------ 2 tor tor 4096 Nov 12 17:45 keys
drwx------ 2 tor tor 4096 Nov 12 17:45 pt_state
-rw-r--r-- 1 tor tor 12345 Nov 12 17:45 cached-descriptors
🔑 Checking for Tor identity keys...
✅ keys/ directory exists
-rw------- 1 tor tor 1024 Nov 12 17:45 secret_id_key
-rw------- 1 tor tor 96 Nov 12 17:45 ed25519_master_id_secret_key
✅ secret_id_key found (RSA identity)
✅ ed25519_master_id_secret_key found (Ed25519 identity)
🔐 Checking for obfs4 bridge state...
✅ pt_state/ directory exists
-rw------- 1 tor tor 512 Nov 12 17:45 obfs4_state.json
✅ obfs4_state.json found (bridge credentials)
Step 4: Checking for incompatible torrc files...
✅ No torrc files found in volume (this is GOOD)
Step 5: Creating backup of volume...
✅ Backup created: bridge-backup-20251112-180000.tar.gz
Keep this backup safe - it contains your bridge identity keys!
Step 6: No torrc cleanup needed
Step 7: Extracting current bridge fingerprint...
✅ Current fingerprint: B1702095E8D048CF68190284BB11E183A0CDD533
Save this! You'll verify it matches after migration.
Tor Metrics: https://metrics.torproject.org/rs.html#search/B1702095E8D048CF68190284BB11E183A0CDD533
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Diagnosis and cleanup complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Your bridge identity keys are preserved
✅ No torrc cleanup was needed
✅ Backup created: bridge-backup-20251112-180000.tar.gz
```
### Step 2: Deploy Fixed Configuration
After the diagnostic script completes, use the corrected Cosmos JSON:
**File:** `templates/cosmos-compose-bridge-migrated-v1.1.1.json`
```json
{
"minVersion": "0.8.0",
"services": {
"obfs4-bridge": {
"image": "localhost:5000/r3bo0tbx1/onion-relay:latest",
"container_name": "obfs4-bridge",
"restart": "unless-stopped",
"network_mode": "host",
"environment": [
"OR_PORT=9001",
"PT_PORT=9005",
"EMAIL=admin@email.org",
"NICKNAME=MyObfs4Bridge",
"OBFS4_ENABLE_ADDITIONAL_VARIABLES=1",
"OBFS4V_AddressDisableIPv6=0",
"OBFS4V_MaxMemInQueues=1024 MB"
],
"volumes": [
{
"type": "volume",
"source": "obfs4-data",
"target": "/var/lib/tor"
}
],
"security_opt": ["no-new-privileges:true"],
"cap_add": ["NET_BIND_SERVICE", "CHOWN", "SETUID", "SETGID", "DAC_OVERRIDE"],
"labels": {
"cosmos-stack": "TorBridge",
"cosmos-stack-main": "obfs4-bridge",
"cosmos-icon": "https://iili.io/KsXP2Y7.png",
"cosmos-auto-update": "true",
"cosmos-force-network-secured": "false",
"cosmos-version": "1.1.1"
}
}
},
"volumes": {
"obfs4-data": {}
}
}
```
**Key points:**
- ✅ Uses ENV variables (OR_PORT, PT_PORT, etc.) - official Tor Project naming
- ✅ Volume mount: `obfs4-data` → `/var/lib/tor` (preserves keys)
- ✅ No `/etc/tor/torrc` bind mount (lets v1.1.1 generate config from ENV)
- ✅ Bridge mode auto-detected from `PT_PORT`
- ✅ `OBFS4_ENABLE_ADDITIONAL_VARIABLES=1` enables OBFS4V_* processing
### Step 3: Verify Migration Success
After deploying, verify everything works:
```bash
# 1. Check container is running
docker ps | grep obfs4-bridge
# 2. Check logs for successful startup
docker logs -f obfs4-bridge
```
**Expected successful startup logs:**
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🧅 Tor Guard Relay v1.1.1 - Initialization
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🗂️ Phase 1: Directory Structure
Created directories:
• Data: /var/lib/tor
• Logs: /var/log/tor
• Run: /run/tor
🔐 Phase 2: Permission Hardening
✅ Permissions configured securely
🔧 Phase 3: Configuration Setup
Generating configuration from environment variables...
✅ Configuration generated from ENV vars
🔎 Phase 4: Configuration Validation
📦 Tor version: Tor version 0.4.8.20.
Validating torrc syntax...
✅ Configuration is valid
📊 Phase 5: Build Information
🌐 Relay mode: bridge
🔧 Config source: environment
🧩 Phase 6: Available Diagnostic Tools
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Starting Tor relay...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Nov 12 18:30:00.000 [notice] Tor 0.4.8.20 running on Linux...
Nov 12 18:30:00.000 [notice] Read configuration file "/etc/tor/torrc".
Nov 12 18:30:01.000 [notice] Bootstrapped 5% (conn): Connecting to a relay
Nov 12 18:30:02.000 [notice] Bootstrapped 10% (conn_done): Connected to a relay
...
Nov 12 18:30:10.000 [notice] Bootstrapped 100% (done): Done
```
**Critical checks:**
1. **Config source must be "environment"**, not "mounted":
```
✅ Configuration generated from ENV vars ← GOOD
🔧 Config source: environment ← GOOD
```
2. **Relay mode must be "bridge"** (auto-detected from PT_PORT):
```
🌐 Relay mode: bridge ← GOOD
```
3. **Verify fingerprint matches** (from diagnostic script):
```bash
docker exec obfs4-bridge fingerprint
```
Should output the SAME fingerprint from Step 1. If it's different, your keys weren't preserved!
4. **Check health**:
```bash
docker exec obfs4-bridge health | jq .
```
Expected output:
```json
{
"status": "ok",
"relay_mode": "bridge",
"bootstrap": "100%",
"fingerprint": "B1702095E8D048CF68190284BB11E183A0CDD533",
"nickname": "MyObfs4Bridge",
"or_port": 9001,
"obfs4_port": 9005
}
```
5. **Get bridge line** (after 10-30 minutes of operation):
```bash
docker exec obfs4-bridge bridge-line
```
## If Still Failing: Advanced Debugging
### Enable DEBUG mode
If the container still crashes, add `DEBUG=true` to environment to see exact validation error:
```json
"environment": [
"DEBUG=true", // ← Add this first
"OR_PORT=9001",
"PT_PORT=9005",
// ... rest of ENV vars
]
```
Redeploy and check logs:
```bash
docker logs obfs4-bridge 2>&1 | grep -A 10 "Configuration validation failed"
```
### Common Issues
#### Issue 1: "Using mounted configuration" when you don't have a mount
**Symptom:**
```
✅ Using mounted configuration: /etc/tor/torrc
🛑 Configuration validation failed!
```
**Cause:** Old torrc file exists somewhere (in volume or image)
**Fix:**
```bash
# Check if torrc exists in volume
docker run --rm -v obfs4-data:/data alpine find /data -name "torrc"
# Remove any found torrc files
docker run --rm -v obfs4-data:/data alpine rm -f /data/torrc /data/etc/tor/torrc
```
#### Issue 2: Fingerprints still changing after migration
**Symptom:** `docker exec obfs4-bridge fingerprint` shows different value each time
**Cause:** Volume is being recreated or not properly mounted
**Fix:**
```bash
# Verify volume exists and has keys
docker run --rm -v obfs4-data:/data alpine ls -la /data/keys
# Should see:
# -rw------- secret_id_key
# -rw------- ed25519_master_id_secret_key
# If missing, restore from backup:
docker run --rm \
-v obfs4-data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/bridge-backup-YYYYMMDD-HHMMSS.tar.gz -C /
```
#### Issue 3: Permission errors after migration
**Symptom:**
```
[warn] Directory /var/lib/tor cannot be read: Permission denied
```
**Fix:** v1.1.1 has automatic permission healing. If it still fails:
```bash
# Fix permissions manually
docker run --rm -v obfs4-data:/data alpine chown -R 1000:1000 /data
docker run --rm -v obfs4-data:/data alpine chmod 700 /data
```
#### Issue 4: obfs4 transport not working
**Symptom:**
```
[warn] We were supposed to start obfs4 but couldn't
```
**Fix:** Verify lyrebird is installed:
```bash
docker exec obfs4-bridge which lyrebird
# Should output: /usr/bin/lyrebird
# Check if obfs4 port is configured
docker exec obfs4-bridge grep -i "ServerTransportListenAddr" /etc/tor/torrc
# Should output: ServerTransportListenAddr obfs4 0.0.0.0:9005
```
## Rollback Procedure
If migration fails and you need to go back to the official bridge image:
### Step 1: Stop v1.1.1 container
```bash
docker stop obfs4-bridge
docker rm obfs4-bridge
```
### Step 2: Restore backup (if needed)
```bash
# Only if you lost keys or data
docker volume rm obfs4-data
docker volume create obfs4-data
docker run --rm \
-v obfs4-data:/data \
-v $(pwd):/backup \
alpine tar xzf /backup/bridge-backup-YYYYMMDD-HHMMSS.tar.gz -C /
```
### Step 3: Redeploy official bridge
Use your original `thetorproject/obfs4-bridge` configuration:
```json
{
"minVersion": "0.8.0",
"services": {
"obfs4-bridge": {
"image": "thetorproject/obfs4-bridge:latest",
"container_name": "obfs4-bridge",
"restart": "unless-stopped",
"network_mode": "host",
"environment": [
"OR_PORT=9001",
"PT_PORT=9005",
"EMAIL=admin@email.org",
"NICKNAME=MyObfs4Bridge"
],
"volumes": [
{
"type": "volume",
"source": "obfs4-data",
"target": "/var/lib/tor"
}
]
}
},
"volumes": {
"obfs4-data": {}
}
}
```
### Step 4: Verify rollback success
```bash
docker logs -f obfs4-bridge
# Should start successfully and reuse existing keys
# Fingerprint should match your original
```
## Prevention for Future Migrations
1. **Always backup first:**
```bash
docker run --rm \
-v obfs4-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/bridge-backup-$(date +%Y%m%d).tar.gz /data
```
2. **Test with DEBUG=true** on first migration
3. **Verify fingerprint immediately** after migration
4. **Keep old container stopped** (not removed) until you verify new one works:
```bash
docker stop obfs4-bridge # ← Just stop, don't remove
# ... deploy new v1.1.1 container with different name ...
# ... verify it works ...
# ... then remove old container
```
5. **Monitor Tor Metrics** for 24-48 hours to ensure bridge stays published
## Support
If you've followed all steps and still have issues:
1. Run diagnostic script and save output:
```bash
./bridge-migration-fix.sh > migration-debug.log 2>&1
```
2. Collect container logs with DEBUG:
```bash
# Add DEBUG=true to environment, redeploy, then:
docker logs obfs4-bridge > container-debug.log 2>&1
```
3. Open an issue with:
- `migration-debug.log`
- `container-debug.log`
- Your Cosmos JSON (remove sensitive info like EMAIL)
- Output of `docker volume inspect obfs4-data`
**GitHub Issues:** https://github.com/r3bo0tbx1/tor-guard-relay/issues
## Summary Checklist
Before migration:
- [ ] Run `bridge-migration-fix.sh` diagnostic script
- [ ] Save current fingerprint
- [ ] Create backup of `obfs4-data` volume
- [ ] Verify identity keys exist in volume
After migration:
- [ ] Container starts without crash loop
- [ ] Logs show "Config source: environment" (not "mounted")
- [ ] Relay mode is "bridge" (auto-detected)
- [ ] Fingerprint matches original (verify with `docker exec obfs4-bridge fingerprint`)
- [ ] Health check passes (`docker exec obfs4-bridge health | jq .`)
- [ ] Bootstrap reaches 100%
- [ ] Bridge line available after 10-30 minutes (`docker exec obfs4-bridge bridge-line`)
- [ ] Tor Metrics still shows your bridge (wait 1-2 hours)
**Migration should preserve:**
- ✅ Bridge fingerprint (same identity keys)
- ✅ obfs4 credentials (pt_state/obfs4_state.json)
- ✅ Bridge reputation and history
- ✅ All configuration (ORPort, PT port, nickname, contact info)
**Migration adds:**
- ✨ Official Tor Project ENV variable compatibility
- ✨ Bootstrap progress logs in terminal
- ✨ Enhanced emoji logging (v1.1.0 style)
- ✨ 4 diagnostic tools (status, health, fingerprint, bridge-line)
- ✨ Auto-detection of bridge mode from PT_PORT
- ✨ OBFS4V_* variable processing
Your bridge identity and reputation are preserved throughout the migration!