Files
tor-guard-relay/scripts/utilities/quick-start.sh
rE-Bo0t.bx1 a94d409f2b feat(v1.1.2): Alpine edge variant, dual CI, GHCR edge builds 🚀
- Add Dockerfile.edge 🐚🔧
- Add stable and edge CI matrix 🔁📦
- GHCR edge-only deployment 🟣📤
- SBOMs for both variants 📜🔍
- Tests, screenshots, logo 🧪🖼️
- Update docs and PR template 📝
- Remove dependabot.yml 🗑️
2025-11-17 22:38:30 +08:00

626 lines
17 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# quick-start.sh - Interactive Tor relay deployment script
# Helps beginners set up guard, exit, or bridge relays
set -e
# Color output helpers (if terminal supports it)
if [ -t 1 ]; then
BOLD='\033[1m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
else
BOLD=''
GREEN=''
BLUE=''
YELLOW=''
RED=''
NC=''
fi
# Logging helpers
log() { printf "${BOLD}%s${NC}\n" "$1"; }
info() { printf " ${BLUE} %s${NC}\n" "$1"; }
success() { printf "${GREEN}✅ %s${NC}\n" "$1"; }
warn() { printf "${YELLOW}⚠️ %s${NC}\n" "$1"; }
error() { printf "${RED}🛑 ERROR: %s${NC}\n" "$1"; exit 1; }
# Banner
show_banner() {
cat << "EOF"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🧅 Tor Guard Relay - Quick Start Setup
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
This script will help you deploy a Tor relay in minutes!
EOF
}
# Prompt for input with default value
prompt() {
prompt_text="$1"
default_val="$2"
var_name="$3"
if [ -n "$default_val" ]; then
printf "${BOLD}%s${NC} [${GREEN}%s${NC}]: " "$prompt_text" "$default_val"
else
printf "${BOLD}%s${NC}: " "$prompt_text"
fi
read -r input
if [ -z "$input" ]; then
input="$default_val"
fi
eval "$var_name=\"\$input\""
}
# Validate nickname
validate_nickname() {
nickname="$1"
# Length check (1-19 characters)
nickname_len=$(printf "%s" "$nickname" | wc -c)
if [ "$nickname_len" -lt 1 ] || [ "$nickname_len" -gt 19 ]; then
warn "Nickname must be 1-19 characters (you entered: $nickname_len)"
return 1
fi
# Alphanumeric only
if ! printf "%s" "$nickname" | grep -qE '^[a-zA-Z0-9]+$'; then
warn "Nickname must contain only letters and numbers"
return 1
fi
# Reserved names
case "$(printf "%s" "$nickname" | tr '[:upper:]' '[:lower:]')" in
unnamed|noname|default|tor|relay|bridge|exit)
warn "Cannot use reserved name: $nickname"
return 1
;;
esac
return 0
}
# Validate email
validate_email() {
email="$1"
# Basic length check
email_len=$(printf "%s" "$email" | wc -c)
if [ "$email_len" -lt 5 ]; then
warn "Email must be at least 5 characters"
return 1
fi
# Very basic email format check
if ! printf "%s" "$email" | grep -qE '^[^@]+@[^@]+\.[^@]+$'; then
warn "Email format appears invalid (should be: name@domain.com)"
return 1
fi
return 0
}
# Validate port
validate_port() {
port="$1"
port_name="$2"
# Integer check
if ! printf "%s" "$port" | grep -qE '^[0-9]+$'; then
warn "$port_name must be a valid number"
return 1
fi
# Range check
if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
warn "$port_name must be between 1-65535"
return 1
fi
# Warn about privileged ports
if [ "$port" -lt 1024 ]; then
warn "$port_name is a privileged port (<1024) - may require CAP_NET_BIND_SERVICE capability"
fi
return 0
}
# Main menu
show_menu() {
log ""
log "What type of Tor relay do you want to run?"
log ""
printf " ${BOLD}1)${NC} ${GREEN}Guard/Middle Relay${NC} - Safest option, routes traffic\n"
printf " ${BOLD}2)${NC} ${YELLOW}Exit Relay${NC} - Advanced, requires legal compliance\n"
printf " ${BOLD}3)${NC} ${BLUE}Bridge Relay${NC} - Helps users in censored regions (obfs4)\n"
printf " ${BOLD}4)${NC} ${RED}Quit${NC}\n"
log ""
}
# Collect common information
collect_common_info() {
log ""
log "📋 Basic Relay Information"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
# Nickname
while true; do
prompt "Relay Nickname (1-19 alphanumeric)" "MyTorRelay" NICKNAME
if validate_nickname "$NICKNAME"; then
success "Nickname accepted: $NICKNAME"
break
fi
done
log ""
# Email
while true; do
prompt "Contact Email" "admin@example.com" EMAIL
if validate_email "$EMAIL"; then
success "Email accepted: $EMAIL"
break
fi
done
log ""
# ORPort
while true; do
if [ "$RELAY_MODE" = "guard" ]; then
prompt "ORPort (recommended: 443 or 9001)" "9001" OR_PORT
elif [ "$RELAY_MODE" = "exit" ]; then
prompt "ORPort (recommended: 443)" "443" OR_PORT
else
prompt "ORPort (recommended: 443 or 9001)" "9001" OR_PORT
fi
if validate_port "$OR_PORT" "ORPort"; then
success "ORPort set to: $OR_PORT"
break
fi
done
}
# Guard relay specific
collect_guard_info() {
log ""
log "⚙️ Guard Relay Configuration"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
info "Guard relays provide directory services and route traffic."
info "They are the safest and easiest type of relay to operate."
log ""
# DirPort
while true; do
prompt "DirPort (set to 0 to disable)" "9030" DIR_PORT
if [ "$DIR_PORT" = "0" ]; then
success "DirPort disabled"
break
fi
if validate_port "$DIR_PORT" "DirPort"; then
success "DirPort set to: $DIR_PORT"
break
fi
done
log ""
# Bandwidth
prompt "Bandwidth Rate (e.g., 50 MBytes, leave empty for unlimited)" "" BANDWIDTH_RATE
if [ -n "$BANDWIDTH_RATE" ]; then
prompt "Bandwidth Burst (e.g., 100 MBytes)" "" BANDWIDTH_BURST
fi
}
# Exit relay specific
collect_exit_info() {
log ""
log "⚠️ Exit Relay Configuration"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
warn "EXIT RELAYS ARE ADVANCED AND HAVE LEGAL IMPLICATIONS!"
log ""
info "Exit relays route traffic to the public internet."
info "You WILL receive abuse complaints and may need to respond to legal requests."
info "Make sure you understand the risks and legal requirements."
log ""
# Confirmation
prompt "Are you sure you want to run an exit relay? (yes/no)" "no" CONFIRM
if [ "$CONFIRM" != "yes" ] && [ "$CONFIRM" != "YES" ]; then
error "Exit relay setup cancelled. Consider running a guard or bridge relay instead."
fi
log ""
# DirPort
while true; do
prompt "DirPort (set to 0 to disable)" "9030" DIR_PORT
if [ "$DIR_PORT" = "0" ]; then
success "DirPort disabled"
break
fi
if validate_port "$DIR_PORT" "DirPort"; then
success "DirPort set to: $DIR_PORT"
break
fi
done
log ""
# Exit policy
log "Exit Policy Options:"
printf " ${BOLD}1)${NC} Reduced exit (recommended) - allows common ports\n"
printf " ${BOLD}2)${NC} Reject all (safer) - effectively a guard relay\n"
printf " ${BOLD}3)${NC} Custom policy - you provide the policy\n"
log ""
prompt "Exit Policy Choice" "1" POLICY_CHOICE
case "$POLICY_CHOICE" in
1)
EXIT_POLICY="ExitPolicy accept *:80\\nExitPolicy accept *:443\\nExitPolicy reject *:*"
info "Using reduced exit policy (HTTP/HTTPS only)"
;;
2)
EXIT_POLICY="ExitPolicy reject *:*"
info "Using reject all policy"
;;
3)
prompt "Enter custom exit policy (e.g., 'ExitPolicy reject *:*')" "ExitPolicy reject *:*" EXIT_POLICY
;;
*)
EXIT_POLICY="ExitPolicy reject *:*"
warn "Invalid choice, using reject all"
;;
esac
log ""
# Bandwidth
prompt "Bandwidth Rate (e.g., 50 MBytes, leave empty for unlimited)" "" BANDWIDTH_RATE
if [ -n "$BANDWIDTH_RATE" ]; then
prompt "Bandwidth Burst (e.g., 100 MBytes)" "" BANDWIDTH_BURST
fi
}
# Bridge relay specific
collect_bridge_info() {
log ""
log "🌉 Bridge Relay Configuration"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
info "Bridge relays help users in censored regions access Tor."
info "They use obfs4 pluggable transport to disguise Tor traffic."
log ""
# PT_PORT (obfs4 port)
while true; do
prompt "obfs4 Port (PT_PORT, recommended: 443 or 9002)" "9002" PT_PORT
if validate_port "$PT_PORT" "PT_PORT"; then
success "obfs4 Port set to: $PT_PORT"
break
fi
done
log ""
# Bandwidth
prompt "Bandwidth Rate (e.g., 50 MBytes, leave empty for unlimited)" "" BANDWIDTH_RATE
if [ -n "$BANDWIDTH_RATE" ]; then
prompt "Bandwidth Burst (e.g., 100 MBytes)" "" BANDWIDTH_BURST
fi
}
# Generate docker run command
generate_docker_run() {
log ""
log "🐳 Docker Run Command"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
cat > /tmp/tor-relay-run.sh << EOF
#!/bin/sh
# Tor ${RELAY_MODE} Relay - Generated by quick-start.sh
# Run this script to start your Tor relay
docker run -d \\
--name tor-${RELAY_MODE} \\
--network host \\
--restart unless-stopped \\
--cap-drop ALL \\
--cap-add NET_BIND_SERVICE \\
--security-opt no-new-privileges \\
-e NICKNAME="${NICKNAME}" \\
-e EMAIL="${EMAIL}" \\
-e OR_PORT=${OR_PORT} \\
EOF
# Mode-specific additions
if [ "$RELAY_MODE" = "guard" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
-e TOR_RELAY_MODE=guard \\
-e TOR_DIRPORT=${DIR_PORT} \\
EOF
elif [ "$RELAY_MODE" = "exit" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
-e TOR_RELAY_MODE=exit \\
-e TOR_DIRPORT=${DIR_PORT} \\
-e TOR_EXIT_POLICY="${EXIT_POLICY}" \\
EOF
elif [ "$RELAY_MODE" = "bridge" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
-e PT_PORT=${PT_PORT} \\
EOF
fi
# Bandwidth (if set)
if [ -n "$BANDWIDTH_RATE" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
-e TOR_BANDWIDTH_RATE="${BANDWIDTH_RATE}" \\
EOF
fi
if [ -n "$BANDWIDTH_BURST" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
-e TOR_BANDWIDTH_BURST="${BANDWIDTH_BURST}" \\
EOF
fi
# Volumes and image
cat >> /tmp/tor-relay-run.sh << EOF
-v tor-${RELAY_MODE}-data:/var/lib/tor \\
-v tor-${RELAY_MODE}-logs:/var/log/tor \\
ghcr.io/r3bo0tbx1/onion-relay:latest
# Wait for container to start
sleep 5
# Show container status
docker ps | grep tor-${RELAY_MODE}
echo ""
echo "✅ Tor ${RELAY_MODE} relay started!"
echo ""
echo "📋 Useful commands:"
echo " docker logs tor-${RELAY_MODE} - View logs"
echo " docker exec tor-${RELAY_MODE} status - Full health check"
echo " docker exec tor-${RELAY_MODE} health - JSON health API"
EOF
if [ "$RELAY_MODE" = "bridge" ]; then
cat >> /tmp/tor-relay-run.sh << EOF
echo " docker exec tor-${RELAY_MODE} bridge-line - Get bridge line to share"
EOF
else
cat >> /tmp/tor-relay-run.sh << EOF
echo " docker exec tor-${RELAY_MODE} fingerprint - Get relay fingerprint"
EOF
fi
chmod +x /tmp/tor-relay-run.sh
success "Docker run script generated: /tmp/tor-relay-run.sh"
log ""
cat /tmp/tor-relay-run.sh
log ""
}
# Generate docker-compose.yml
generate_docker_compose() {
log ""
log "🐳 Docker Compose Configuration"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
cat > /tmp/docker-compose.yml << EOF
# Tor ${RELAY_MODE} Relay - Generated by quick-start.sh
# Deploy with: docker-compose up -d
version: '3.8'
services:
tor-${RELAY_MODE}:
image: ghcr.io/r3bo0tbx1/onion-relay:latest
container_name: tor-${RELAY_MODE}
restart: unless-stopped
network_mode: host
# Security settings
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
# Environment variables
environment:
NICKNAME: "${NICKNAME}"
EMAIL: "${EMAIL}"
OR_PORT: ${OR_PORT}
EOF
# Mode-specific additions
if [ "$RELAY_MODE" = "guard" ]; then
cat >> /tmp/docker-compose.yml << EOF
TOR_RELAY_MODE: guard
TOR_DIRPORT: ${DIR_PORT}
EOF
elif [ "$RELAY_MODE" = "exit" ]; then
cat >> /tmp/docker-compose.yml << EOF
TOR_RELAY_MODE: exit
TOR_DIRPORT: ${DIR_PORT}
TOR_EXIT_POLICY: "${EXIT_POLICY}"
EOF
elif [ "$RELAY_MODE" = "bridge" ]; then
cat >> /tmp/docker-compose.yml << EOF
PT_PORT: ${PT_PORT}
EOF
fi
# Bandwidth (if set)
if [ -n "$BANDWIDTH_RATE" ]; then
cat >> /tmp/docker-compose.yml << EOF
TOR_BANDWIDTH_RATE: "${BANDWIDTH_RATE}"
EOF
fi
if [ -n "$BANDWIDTH_BURST" ]; then
cat >> /tmp/docker-compose.yml << EOF
TOR_BANDWIDTH_BURST: "${BANDWIDTH_BURST}"
EOF
fi
# Volumes
cat >> /tmp/docker-compose.yml << EOF
# Data persistence
volumes:
- tor-${RELAY_MODE}-data:/var/lib/tor
- tor-${RELAY_MODE}-logs:/var/log/tor
volumes:
tor-${RELAY_MODE}-data:
driver: local
tor-${RELAY_MODE}-logs:
driver: local
EOF
success "Docker Compose file generated: /tmp/docker-compose.yml"
log ""
cat /tmp/docker-compose.yml
log ""
}
# Next steps
show_next_steps() {
log ""
log "🚀 Next Steps"
log "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
log ""
log "1. Review the generated configuration:"
info " - Docker run script: /tmp/tor-relay-run.sh"
info " - Docker Compose file: /tmp/docker-compose.yml"
log ""
log "2. Deploy your relay:"
info " ${BOLD}Option A:${NC} Run the script"
info " sh /tmp/tor-relay-run.sh"
log ""
info " ${BOLD}Option B:${NC} Use Docker Compose"
info " cp /tmp/docker-compose.yml ~/tor-relay/"
info " cd ~/tor-relay && docker-compose up -d"
log ""
log "3. Monitor your relay:"
info " docker logs tor-${RELAY_MODE}"
info " docker exec tor-${RELAY_MODE} status"
log ""
if [ "$RELAY_MODE" = "bridge" ]; then
log "4. Share your bridge line:"
info " Wait 2-5 minutes for Tor to bootstrap (100%)"
info " docker exec tor-${RELAY_MODE} bridge-line"
info " Share the output with users in censored regions"
log ""
else
log "4. Find your relay on Tor Metrics:"
info " Wait 24-48 hours for your relay to appear"
info " docker exec tor-${RELAY_MODE} fingerprint"
info " Visit the Tor Metrics URL shown"
log ""
fi
if [ "$RELAY_MODE" = "exit" ]; then
warn "IMPORTANT FOR EXIT RELAYS:"
info " - Monitor abuse complaints: ${EMAIL}"
info " - Set up reverse DNS (PTR record) for your IP"
info " - Consider getting AS number and WHOIS info"
info " - Read: https://community.torproject.org/relay/community-resources/tor-exit-guidelines/"
log ""
fi
log "5. Documentation:"
info " - FAQ: https://github.com/r3bo0tbx1/tor-guard-relay/blob/main/docs/FAQ.md"
info " - Architecture: https://github.com/r3bo0tbx1/tor-guard-relay/blob/main/docs/ARCHITECTURE.md"
info " - Monitoring: https://github.com/r3bo0tbx1/tor-guard-relay/blob/main/docs/MONITORING.md"
log ""
success "Setup complete! Thank you for supporting the Tor network! 🧅"
log ""
}
# Main execution
main() {
show_banner
# Main menu loop
while true; do
show_menu
prompt "Choose an option" "1" CHOICE
case "$CHOICE" in
1)
RELAY_MODE="guard"
collect_common_info
collect_guard_info
generate_docker_run
generate_docker_compose
show_next_steps
exit 0
;;
2)
RELAY_MODE="exit"
collect_common_info
collect_exit_info
generate_docker_run
generate_docker_compose
show_next_steps
exit 0
;;
3)
RELAY_MODE="bridge"
collect_common_info
collect_bridge_info
generate_docker_run
generate_docker_compose
show_next_steps
exit 0
;;
4)
log ""
log "👋 Goodbye! Thank you for considering running a Tor relay."
log ""
exit 0
;;
*)
warn "Invalid choice. Please select 1-4."
;;
esac
done
}
main "$@"