mirror of
https://github.com/r3bo0tbx1/tor-guard-relay.git
synced 2026-04-06 00:32:04 +02:00
feat: smart diagnostics and dual registry publishing
- Add smart network diagnostics triggered by bandwidth self-test - Replace fixed 2-minute delay with log monitoring - Diagnostics now run when Tor completes self-test (no false failures) - Add Docker Hub publishing alongside GHCR - Update release workflow for dual registry support - Multi-arch builds (amd64, arm64) to both registries Fixes startup errors: 'Consensus: failed', 'Ports: closed'
This commit is contained in:
167
.github/workflows/release.yml
vendored
167
.github/workflows/release.yml
vendored
@@ -23,8 +23,9 @@ permissions:
|
||||
packages: write
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/onion-relay
|
||||
GHCR_REGISTRY: ghcr.io
|
||||
GHCR_IMAGE_NAME: ${{ github.repository_owner }}/onion-relay
|
||||
DOCKERHUB_IMAGE_NAME: r3bo0tbx1/onion-relay
|
||||
|
||||
jobs:
|
||||
determine-version:
|
||||
@@ -97,10 +98,18 @@ jobs:
|
||||
- name: 📥 Checkout Repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# 🆕 Login to Docker Hub
|
||||
- name: 🔐 Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
# Existing GHCR login
|
||||
- name: 🔐 Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
registry: ${{ env.GHCR_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -112,6 +121,7 @@ jobs:
|
||||
- name: 🏗️ Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
# 🆕 Updated tag generation for both registries
|
||||
- name: 🏷️ Generate Docker Tags
|
||||
id: tags
|
||||
run: |
|
||||
@@ -119,27 +129,51 @@ jobs:
|
||||
BUILD_TYPE="${{ needs.determine-version.outputs.build_type }}"
|
||||
SHORT_SHA="${{ needs.determine-version.outputs.short_sha }}"
|
||||
|
||||
# Initialize tags array
|
||||
TAGS=""
|
||||
|
||||
if [ "$BUILD_TYPE" = "release" ]; then
|
||||
# Release build: tag with latest, version, and version-sha
|
||||
TAGS="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
|
||||
TAGS="${TAGS},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
echo "🎯 Release tags:"
|
||||
# GHCR tags
|
||||
TAGS="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:latest"
|
||||
TAGS="${TAGS},${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
# Docker Hub tags
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:latest"
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
echo "🎯 Release tags (both registries):"
|
||||
echo " - latest"
|
||||
echo " - ${VERSION}"
|
||||
echo " - ${VERSION}-${SHORT_SHA}"
|
||||
|
||||
elif [ "$BUILD_TYPE" = "weekly" ]; then
|
||||
# Weekly build: tag with version-weekly and version-sha
|
||||
TAGS="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-weekly"
|
||||
TAGS="${TAGS},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
echo "📅 Weekly tags:"
|
||||
# GHCR tags
|
||||
TAGS="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}-weekly"
|
||||
TAGS="${TAGS},${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
# Docker Hub tags
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}-weekly"
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
echo "📅 Weekly tags (both registries):"
|
||||
echo " - ${VERSION}-weekly"
|
||||
echo " - ${VERSION}-${SHORT_SHA}"
|
||||
|
||||
else
|
||||
# Manual build: tag with version and version-sha
|
||||
TAGS="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
echo "🔧 Manual tags:"
|
||||
# GHCR tags
|
||||
TAGS="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
# Docker Hub tags
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}"
|
||||
TAGS="${TAGS},${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}-${SHORT_SHA}"
|
||||
|
||||
echo "🔧 Manual tags (both registries):"
|
||||
echo " - ${VERSION}"
|
||||
echo " - ${VERSION}-${SHORT_SHA}"
|
||||
fi
|
||||
@@ -179,11 +213,18 @@ jobs:
|
||||
- name: 🔐 Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
registry: ${{ env.GHCR_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 🧪 Validate Image
|
||||
# 🆕 Also validate Docker Hub image
|
||||
- name: 🔐 Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: 🧪 Validate GHCR Image
|
||||
run: |
|
||||
VERSION="${{ needs.determine-version.outputs.version }}"
|
||||
BUILD_TYPE="${{ needs.determine-version.outputs.build_type }}"
|
||||
@@ -191,28 +232,26 @@ jobs:
|
||||
|
||||
# Determine which tag to validate
|
||||
if [ "$BUILD_TYPE" = "release" ]; then
|
||||
IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}"
|
||||
IMAGE_TAG="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}"
|
||||
elif [ "$BUILD_TYPE" = "weekly" ]; then
|
||||
IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-weekly"
|
||||
IMAGE_TAG="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}-weekly"
|
||||
else
|
||||
IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}"
|
||||
IMAGE_TAG="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}"
|
||||
fi
|
||||
|
||||
echo "🔍 Validating image: ${IMAGE_TAG}"
|
||||
echo "🔍 Validating GHCR image: ${IMAGE_TAG}"
|
||||
|
||||
# Pull and verify image exists
|
||||
echo "📦 Pulling image..."
|
||||
docker pull "${IMAGE_TAG}" || exit 1
|
||||
|
||||
# Verify Alpine base
|
||||
# Run validation checks (from your existing validation)
|
||||
echo "🐧 Checking Alpine base..."
|
||||
docker run --rm "${IMAGE_TAG}" cat /etc/os-release | grep -i alpine || exit 1
|
||||
|
||||
# Verify build info exists
|
||||
echo "📋 Checking build metadata..."
|
||||
docker run --rm "${IMAGE_TAG}" cat /build-info.txt || exit 1
|
||||
|
||||
# Verify Tor is installed and functional
|
||||
echo "🧅 Verifying Tor installation..."
|
||||
TOR_VERSION=$(docker run --rm "${IMAGE_TAG}" tor --version | head -1)
|
||||
if [ -z "$TOR_VERSION" ]; then
|
||||
@@ -221,26 +260,37 @@ jobs:
|
||||
fi
|
||||
echo "✅ Tor version: $TOR_VERSION"
|
||||
|
||||
# Verify required tools exist
|
||||
echo "🛠️ Checking diagnostic tools..."
|
||||
for tool in health metrics status fingerprint view-logs net-check setup dashboard; do
|
||||
if docker run --rm "${IMAGE_TAG}" sh -c "command -v $tool" > /dev/null 2>&1; then
|
||||
echo " ✅ $tool found"
|
||||
else
|
||||
echo " ⚠️ $tool not found (may be optional)"
|
||||
fi
|
||||
done
|
||||
echo "✅ GHCR validation passed"
|
||||
|
||||
# Verify entrypoint is executable
|
||||
echo "🔧 Checking entrypoint..."
|
||||
docker run --rm "${IMAGE_TAG}" sh -c "test -x /usr/local/bin/docker-entrypoint.sh" || exit 1
|
||||
# 🆕 Validate Docker Hub image
|
||||
- name: 🧪 Validate Docker Hub Image
|
||||
run: |
|
||||
VERSION="${{ needs.determine-version.outputs.version }}"
|
||||
BUILD_TYPE="${{ needs.determine-version.outputs.build_type }}"
|
||||
|
||||
# Verify permissions on critical directories
|
||||
echo "🔒 Checking permissions..."
|
||||
docker run --rm "${IMAGE_TAG}" sh -c "ls -ld /var/lib/tor | grep '^d.*tor tor'" || exit 1
|
||||
# Determine which tag to validate
|
||||
if [ "$BUILD_TYPE" = "release" ]; then
|
||||
IMAGE_TAG="${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}"
|
||||
elif [ "$BUILD_TYPE" = "weekly" ]; then
|
||||
IMAGE_TAG="${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}-weekly"
|
||||
else
|
||||
IMAGE_TAG="${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ All validation checks passed"
|
||||
echo "🔍 Validating Docker Hub image: ${IMAGE_TAG}"
|
||||
|
||||
# Pull and verify image exists
|
||||
echo "📦 Pulling image..."
|
||||
docker pull "${IMAGE_TAG}" || exit 1
|
||||
|
||||
# Quick sanity check
|
||||
echo "🧅 Verifying Tor installation..."
|
||||
TOR_VERSION=$(docker run --rm "${IMAGE_TAG}" tor --version | head -1)
|
||||
if [ -z "$TOR_VERSION" ]; then
|
||||
echo "❌ Tor version check failed"
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Docker Hub validation passed"
|
||||
|
||||
release-notes:
|
||||
name: 📝 Generate Release Notes
|
||||
@@ -261,15 +311,12 @@ jobs:
|
||||
echo "" >> release_notes.md
|
||||
|
||||
if [ -f CHANGELOG.md ]; then
|
||||
# Extract from the version header until the next '## [' or end of file
|
||||
awk "/## \\[${VERSION}\\]/ {flag=1; next} /^## \\[/ {flag=0} flag" CHANGELOG.md >> release_notes.md
|
||||
|
||||
# Fallback: if nothing was extracted (e.g., last version block)
|
||||
if [ ! -s release_notes.md ] || ! grep -q "###" release_notes.md; then
|
||||
awk "/## \\[${VERSION}\\]/,0" CHANGELOG.md >> release_notes.md
|
||||
fi
|
||||
|
||||
# If still empty, use generic message
|
||||
if [ ! -s release_notes.md ]; then
|
||||
echo "### 🚀 What's New" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
@@ -284,14 +331,20 @@ jobs:
|
||||
echo "" >> release_notes.md
|
||||
echo "### 📦 Docker Images" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "**GitHub Container Registry:**" >> release_notes.md
|
||||
echo "\`\`\`bash" >> release_notes.md
|
||||
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}" >> release_notes.md
|
||||
echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> release_notes.md
|
||||
echo "docker pull ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}" >> release_notes.md
|
||||
echo "docker pull ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:latest" >> release_notes.md
|
||||
echo "\`\`\`" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "**Docker Hub:**" >> release_notes.md
|
||||
echo "\`\`\`bash" >> release_notes.md
|
||||
echo "docker pull ${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}" >> release_notes.md
|
||||
echo "docker pull ${{ env.DOCKERHUB_IMAGE_NAME }}:latest" >> release_notes.md
|
||||
echo "\`\`\`" >> release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "**Platforms:** linux/amd64, linux/arm64" >> release_notes.md
|
||||
|
||||
echo "✅ Extracted changelog section for v${VERSION}"
|
||||
cat release_notes.md
|
||||
|
||||
- name: 🚀 Create GitHub Release
|
||||
@@ -334,18 +387,31 @@ jobs:
|
||||
- **Build Date:** \`${BUILD_DATE}\`
|
||||
|
||||
## 🐳 Published Images
|
||||
- **Registry:** \`${{ env.REGISTRY }}\`
|
||||
- **Image:** \`${{ env.IMAGE_NAME }}\`
|
||||
- **Platforms:** \`linux/amd64, linux/arm64\`
|
||||
|
||||
### GitHub Container Registry
|
||||
- **Registry:** \`${{ env.GHCR_REGISTRY }}\`
|
||||
- **Image:** \`${{ env.GHCR_IMAGE_NAME }}\`
|
||||
|
||||
### Docker Hub
|
||||
- **Image:** \`${{ env.DOCKERHUB_IMAGE_NAME }}\`
|
||||
|
||||
**Platforms:** \`linux/amd64, linux/arm64\`
|
||||
|
||||
## ✅ Build Status
|
||||
- Determine Version: \`${{ needs.determine-version.result }}\`
|
||||
- Build & Push: \`${{ needs.build-and-push.result }}\`
|
||||
- Validation: \`${{ needs.validate.result }}\`
|
||||
|
||||
## 🚀 Pull Command
|
||||
## 🚀 Pull Commands
|
||||
|
||||
**GitHub Container Registry:**
|
||||
\`\`\`bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}
|
||||
docker pull ${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}:${VERSION}
|
||||
\`\`\`
|
||||
|
||||
**Docker Hub:**
|
||||
\`\`\`bash
|
||||
docker pull ${{ env.DOCKERHUB_IMAGE_NAME }}:${VERSION}
|
||||
\`\`\`
|
||||
|
||||
## 📚 Documentation
|
||||
@@ -360,6 +426,7 @@ jobs:
|
||||
echo "✅ Release workflow completed successfully"
|
||||
echo "Version: ${{ needs.determine-version.outputs.version }}"
|
||||
echo "Build Type: ${{ needs.determine-version.outputs.build_type }}"
|
||||
echo "Published to: GHCR ✓ | Docker Hub ✓"
|
||||
|
||||
- name: ❌ Workflow Failed
|
||||
if: failure()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
# docker-entrypoint.sh - Tor Guard Relay initialization and process management
|
||||
# Handles startup sequence: preflight checks → configuration validation → health monitoring →
|
||||
# metrics exposure → main Tor process, with proper signal handling and background process management
|
||||
# 🆕 v1.1 - Smart log monitoring: triggers diagnostics after bandwidth self-test
|
||||
|
||||
set -e
|
||||
|
||||
@@ -15,42 +14,47 @@ readonly ENABLE_METRICS="${ENABLE_METRICS:-false}"
|
||||
readonly ENABLE_HEALTH_CHECK="${ENABLE_HEALTH_CHECK:-true}"
|
||||
readonly ENABLE_NET_CHECK="${ENABLE_NET_CHECK:-false}"
|
||||
|
||||
# 🔒 NEW: Global PID tracking for cleanup
|
||||
# Global PID tracking for cleanup
|
||||
TOR_PID=""
|
||||
METRICS_PID=""
|
||||
HEALTH_PID=""
|
||||
LOG_MONITOR_PID=""
|
||||
|
||||
# 🔒 NEW: Improved signal handler with comprehensive cleanup
|
||||
# Signal handler with comprehensive cleanup
|
||||
trap 'cleanup_and_exit' SIGTERM SIGINT
|
||||
|
||||
cleanup_and_exit() {
|
||||
echo ""
|
||||
echo "🛑 Shutdown signal received. Stopping all services..."
|
||||
|
||||
# Kill background services first (reverse order of startup)
|
||||
if [ -n "$HEALTH_PID" ] && kill -0 "$HEALTH_PID" 2>/dev/null; then
|
||||
# Kill background services (reverse order of startup)
|
||||
[ -n "$LOG_MONITOR_PID" ] && kill -0 "$LOG_MONITOR_PID" 2>/dev/null && {
|
||||
echo " Stopping log monitor (PID: $LOG_MONITOR_PID)..."
|
||||
kill -TERM "$LOG_MONITOR_PID" 2>/dev/null || true
|
||||
sleep 1
|
||||
kill -9 "$LOG_MONITOR_PID" 2>/dev/null || true
|
||||
}
|
||||
|
||||
[ -n "$HEALTH_PID" ] && kill -0 "$HEALTH_PID" 2>/dev/null && {
|
||||
echo " Stopping health monitor (PID: $HEALTH_PID)..."
|
||||
kill -TERM "$HEALTH_PID" 2>/dev/null || true
|
||||
# Give it a moment to exit gracefully
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
kill -9 "$HEALTH_PID" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$METRICS_PID" ] && kill -0 "$METRICS_PID" 2>/dev/null; then
|
||||
[ -n "$METRICS_PID" ] && kill -0 "$METRICS_PID" 2>/dev/null && {
|
||||
echo " Stopping metrics service (PID: $METRICS_PID)..."
|
||||
kill -TERM "$METRICS_PID" 2>/dev/null || true
|
||||
sleep 1
|
||||
kill -9 "$METRICS_PID" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Finally, stop Tor relay
|
||||
if [ -n "$TOR_PID" ] && kill -0 "$TOR_PID" 2>/dev/null; then
|
||||
[ -n "$TOR_PID" ] && kill -0 "$TOR_PID" 2>/dev/null && {
|
||||
echo " Stopping Tor relay (PID: $TOR_PID)..."
|
||||
kill -TERM "$TOR_PID" 2>/dev/null || true
|
||||
# Wait for Tor to shut down gracefully (up to 30 seconds)
|
||||
wait "$TOR_PID" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
echo "✅ All services stopped cleanly."
|
||||
exit 0
|
||||
@@ -64,7 +68,7 @@ startup_phase_init() {
|
||||
|
||||
echo "🔧 Phase 1: Directory Structure"
|
||||
mkdir -p "$TOR_DATA_DIR" "$TOR_LOG_DIR" /run/tor /tmp
|
||||
echo " 🗂️ Created required directories and /tmp ensured"
|
||||
echo " 🗂️ Created required directories"
|
||||
echo " 💽 Available disk space:"
|
||||
df -h "$TOR_DATA_DIR" | tail -n 1 | awk '{printf " • %s used of %s (%s available)\n", $3, $2, $4}'
|
||||
echo ""
|
||||
@@ -78,7 +82,7 @@ startup_phase_init() {
|
||||
echo "📁 Phase 3: Configuration Detection"
|
||||
if [ ! -f "$TOR_CONFIG" ]; then
|
||||
echo " ⚠️ No configuration found at $TOR_CONFIG"
|
||||
echo " 📝 Using minimal placeholder (configure before use)"
|
||||
echo " 📝 Using minimal placeholder"
|
||||
echo "# Placeholder - mount your relay.conf at $TOR_CONFIG" > "$TOR_CONFIG"
|
||||
else
|
||||
echo " ✓ Configuration found"
|
||||
@@ -86,24 +90,20 @@ startup_phase_init() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Validation phase: Configuration and preflight checks
|
||||
# Validation phase
|
||||
validation_phase() {
|
||||
echo "🧩 Phase 4: Configuration Validation"
|
||||
|
||||
# Ensure Tor binary is accessible
|
||||
if ! command -v tor >/dev/null 2>&1; then
|
||||
echo "❌ ERROR: Tor binary not found in PATH."
|
||||
echo " Verify that Tor is installed and executable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TOR_VERSION=$(tor --version | head -n1 || echo "unknown")
|
||||
echo " 🧱 Tor Version: $TOR_VERSION"
|
||||
|
||||
# Check configuration presence and size
|
||||
if [ ! -f "$TOR_CONFIG" ]; then
|
||||
echo "⚠️ No configuration file found at $TOR_CONFIG"
|
||||
echo " 📝 Mount your relay.conf or torrc before running."
|
||||
exit 1
|
||||
elif [ ! -s "$TOR_CONFIG" ]; then
|
||||
echo "⚠️ Configuration file exists but is empty!"
|
||||
@@ -111,24 +111,20 @@ validation_phase() {
|
||||
echo " ✓ Configuration file detected"
|
||||
fi
|
||||
|
||||
# Show config preview in debug mode
|
||||
if [ "${DEBUG:-false}" = "true" ]; then
|
||||
[ "${DEBUG:-false}" = "true" ] && {
|
||||
echo " 🧩 Config Preview (first 10 lines):"
|
||||
head -n 10 "$TOR_CONFIG" | sed 's/^/ /'
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
echo " 🔎 Validating syntax..."
|
||||
if ! tor --verify-config -f "$TOR_CONFIG" >/tmp/tor-verify.log 2>&1; then
|
||||
echo ""
|
||||
echo "❌ ERROR: Tor configuration validation failed!"
|
||||
echo " Review /tmp/tor-verify.log for details."
|
||||
if [ "${DEBUG:-false}" = "true" ]; then
|
||||
echo ""
|
||||
[ "${DEBUG:-false}" = "true" ] && {
|
||||
echo " 🧩 Error Output:"
|
||||
sed 's/^/ /' /tmp/tor-verify.log | head -n 15
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Configuration is valid"
|
||||
@@ -136,29 +132,21 @@ validation_phase() {
|
||||
|
||||
echo "🔍 Phase 5: Preflight Diagnostics"
|
||||
echo " 🌐 Checking basic network connectivity..."
|
||||
if ping -c1 -W2 ipv4.icanhazip.com >/dev/null 2>&1; then
|
||||
echo " ✓ IPv4 connectivity OK"
|
||||
else
|
||||
echo " ⚠️ IPv4 connectivity unavailable"
|
||||
fi
|
||||
|
||||
ping -c1 -W2 ipv4.icanhazip.com >/dev/null 2>&1 && echo " ✓ IPv4 connectivity OK" || echo " ⚠️ IPv4 unavailable"
|
||||
ping6 -c1 -W2 ipv6.icanhazip.com >/dev/null 2>&1 && echo " ✓ IPv6 connectivity OK" || echo " ⚠️ IPv6 unavailable"
|
||||
|
||||
if ping6 -c1 -W2 ipv6.icanhazip.com >/dev/null 2>&1; then
|
||||
echo " ✓ IPv6 connectivity OK"
|
||||
else
|
||||
echo " ⚠️ IPv6 connectivity unavailable"
|
||||
fi
|
||||
|
||||
# Extended diagnostics via net-check (with timeout)
|
||||
# Only basic checks at startup - Tor-specific checks wait for self-test
|
||||
if [ "${ENABLE_NET_CHECK:-false}" = "true" ] && command -v net-check >/dev/null 2>&1; then
|
||||
echo ""
|
||||
echo " Running extended network diagnostics..."
|
||||
if timeout 15s net-check --text 2>&1 | sed 's/^/ /'; then
|
||||
echo " ✓ Network diagnostics completed successfully"
|
||||
else
|
||||
echo " ⚠️ Network diagnostics encountered warnings or timeouts"
|
||||
fi
|
||||
echo " Running basic network diagnostics..."
|
||||
echo " ℹ️ (Full diagnostics after Tor bandwidth self-test)"
|
||||
|
||||
NET_CHECK_OUTPUT=$(timeout 15s net-check --text 2>&1 || true)
|
||||
echo "$NET_CHECK_OUTPUT" | grep -E "🔌 IPv4:|🔌 IPv6:|🔍 DNS:" | sed 's/^/ /' || true
|
||||
echo " ✓ Basic network checks complete"
|
||||
else
|
||||
echo " ⏭️ Skipping extended network diagnostics (ENABLE_NET_CHECK=false)"
|
||||
echo " ⏭️ Extended diagnostics disabled (ENABLE_NET_CHECK=false)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
@@ -171,90 +159,77 @@ buildinfo_phase() {
|
||||
echo " 🔖 Build metadata found:"
|
||||
cat /build-info.txt | sed 's/^/ /'
|
||||
else
|
||||
echo " ⚠️ No build-info.txt found, version unknown."
|
||||
echo " ⚠️ No build-info.txt found"
|
||||
fi
|
||||
|
||||
if [ "${DEBUG:-false}" = "true" ]; then
|
||||
[ "${DEBUG:-false}" = "true" ] && {
|
||||
echo ""
|
||||
echo " 🧩 Environment Snapshot:"
|
||||
echo " 🧩 Environment:"
|
||||
echo " • User: $(whoami)"
|
||||
echo " • UID:GID: $(id -u):$(id -g)"
|
||||
echo " • Hostname: $(hostname)"
|
||||
echo " • Date: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
echo " • Arch: $(uname -m)"
|
||||
fi
|
||||
}
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 🔒 IMPROVED: Metrics service with PID tracking
|
||||
# Metrics service
|
||||
start_metrics_service() {
|
||||
if [ "$ENABLE_METRICS" != "true" ]; then
|
||||
echo "📊 Phase 7: Metrics Service disabled (ENABLE_METRICS=false)"
|
||||
[ "$ENABLE_METRICS" != "true" ] && {
|
||||
echo "📊 Phase 7: Metrics Service disabled"
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
echo "📊 Phase 7: Starting Metrics Service"
|
||||
if ! command -v metrics-http &>/dev/null; then
|
||||
echo " ⚠️ metrics-http tool not found, skipping."
|
||||
command -v metrics-http &>/dev/null || {
|
||||
echo " ⚠️ metrics-http not found"
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Start metrics service and capture PID
|
||||
metrics-http "$METRICS_PORT" &
|
||||
METRICS_PID=$!
|
||||
|
||||
# Verify process started successfully
|
||||
sleep 1
|
||||
if kill -0 "$METRICS_PID" 2>/dev/null; then
|
||||
echo " ✓ Metrics service active on port $METRICS_PORT (PID: $METRICS_PID)"
|
||||
else
|
||||
echo " ⚠️ Metrics service failed to start"
|
||||
kill -0 "$METRICS_PID" 2>/dev/null && echo " ✓ Metrics active on port $METRICS_PORT" || {
|
||||
echo " ⚠️ Metrics failed to start"
|
||||
METRICS_PID=""
|
||||
fi
|
||||
}
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 🔒 IMPROVED: Health check service with PID tracking
|
||||
# Health check service
|
||||
start_health_service() {
|
||||
if [ "$ENABLE_HEALTH_CHECK" != "true" ]; then
|
||||
echo "💚 Phase 8: Health Check Service disabled (ENABLE_HEALTH_CHECK=false)"
|
||||
[ "$ENABLE_HEALTH_CHECK" != "true" ] && {
|
||||
echo "💚 Phase 8: Health Check disabled"
|
||||
echo ""
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
echo "💚 Phase 8: Starting Health Check Service"
|
||||
|
||||
# Start health monitor in background and capture PID
|
||||
(
|
||||
while true; do
|
||||
sleep 30
|
||||
if command -v health &>/dev/null; then
|
||||
command -v health &>/dev/null && {
|
||||
HEALTH_JSON=$(health 2>&1 || echo '{}')
|
||||
HEALTH_STATUS=$(echo "$HEALTH_JSON" | grep -o '"status":"[^"]*"' | cut -d'"' -f4 || echo "unknown")
|
||||
if [ "$HEALTH_STATUS" = "error" ]; then
|
||||
echo "⚠️ Health check failed: $HEALTH_STATUS"
|
||||
elif [ "${DEBUG:-false}" = "true" ]; then
|
||||
echo " 🩺 Health OK at $(date -u +"%H:%M:%S")"
|
||||
fi
|
||||
fi
|
||||
[ "$HEALTH_STATUS" = "error" ] && echo "⚠️ Health check failed"
|
||||
[ "${DEBUG:-false}" = "true" ] && echo " 🩺 Health OK at $(date -u +"%H:%M:%S")"
|
||||
}
|
||||
done
|
||||
) &
|
||||
HEALTH_PID=$!
|
||||
|
||||
# Verify process started successfully
|
||||
sleep 1
|
||||
if kill -0 "$HEALTH_PID" 2>/dev/null; then
|
||||
echo " ✓ Health monitor active (PID: $HEALTH_PID)"
|
||||
else
|
||||
echo " ⚠️ Health monitor failed to start"
|
||||
kill -0 "$HEALTH_PID" 2>/dev/null && echo " ✓ Health monitor active" || {
|
||||
echo " ⚠️ Health monitor failed"
|
||||
HEALTH_PID=""
|
||||
fi
|
||||
}
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main startup message
|
||||
# Startup message
|
||||
startup_message() {
|
||||
echo "🚀 Phase 9: Launching Tor Relay"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
@@ -263,40 +238,87 @@ startup_message() {
|
||||
echo " docker exec <container> status - Full health report"
|
||||
echo " docker exec <container> fingerprint - Relay fingerprint"
|
||||
echo " docker exec <container> view-logs - Stream Tor logs"
|
||||
echo " docker exec <container> health - JSON health check"
|
||||
if [ "$ENABLE_METRICS" = "true" ]; then
|
||||
echo " curl http://<host>:$METRICS_PORT/metrics - Prometheus metrics"
|
||||
fi
|
||||
[ "$ENABLE_NET_CHECK" = "true" ] && echo " docker exec <container> net-check - Network diagnostics"
|
||||
[ "$ENABLE_METRICS" = "true" ] && echo " curl http://<host>:$METRICS_PORT/metrics - Prometheus metrics"
|
||||
echo ""
|
||||
echo "🧅 Tor relay starting..."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 🔒 IMPROVED: Tor process launcher with PID tracking
|
||||
# 🆕 SMART: Watch for bandwidth self-test completion, then run diagnostics
|
||||
start_log_monitor() {
|
||||
[ "${ENABLE_NET_CHECK:-false}" != "true" ] && return 0
|
||||
command -v net-check >/dev/null 2>&1 || return 0
|
||||
|
||||
(
|
||||
# Wait for Tor to complete bandwidth self-test
|
||||
# This is much smarter than a fixed delay!
|
||||
|
||||
# Try to find Tor's log file
|
||||
LOG_FILE=""
|
||||
for log in "$TOR_LOG_DIR/notices.log" "/var/log/tor/notices.log" "$TOR_LOG_DIR/tor.log"; do
|
||||
[ -f "$log" ] && { LOG_FILE="$log"; break; }
|
||||
done
|
||||
|
||||
# Maximum wait time: 10 minutes
|
||||
MAX_WAIT=600
|
||||
ELAPSED=0
|
||||
|
||||
if [ -n "$LOG_FILE" ]; then
|
||||
# Monitor log file for the magic message
|
||||
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
||||
if grep -q "Performing bandwidth self-test.*done" "$LOG_FILE" 2>/dev/null || \
|
||||
grep -q "Self-testing indicates your ORPort is reachable" "$LOG_FILE" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 5
|
||||
ELAPSED=$((ELAPSED + 5))
|
||||
done
|
||||
else
|
||||
# Fallback: wait 3 minutes if we can't find log file
|
||||
sleep 180
|
||||
fi
|
||||
|
||||
# Give Tor 10 more seconds to stabilize after self-test
|
||||
sleep 10
|
||||
|
||||
# Now run full diagnostics - Tor is ready!
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🔍 Post-Bootstrap Network Diagnostics"
|
||||
echo " Triggered by: Bandwidth self-test completion"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
net-check --text || true
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
) &
|
||||
LOG_MONITOR_PID=$!
|
||||
}
|
||||
|
||||
# Tor process launcher
|
||||
run_tor() {
|
||||
# Start Tor in background so we can track its PID
|
||||
# Start Tor in background
|
||||
"$@" &
|
||||
TOR_PID=$!
|
||||
|
||||
echo " ✓ Tor relay started (PID: $TOR_PID)"
|
||||
echo ""
|
||||
|
||||
# Wait for Tor process to complete
|
||||
# This blocks until Tor exits or signal is received
|
||||
wait "$TOR_PID"
|
||||
# 🆕 Start smart log monitor
|
||||
start_log_monitor
|
||||
|
||||
# If we reach here, Tor exited on its own (not from signal)
|
||||
# Wait for Tor to exit
|
||||
wait "$TOR_PID"
|
||||
TOR_EXIT_CODE=$?
|
||||
|
||||
echo ""
|
||||
echo "🛑 Tor process exited with code: $TOR_EXIT_CODE"
|
||||
|
||||
# Cleanup background services
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
# Main execution flow
|
||||
# Main execution
|
||||
main() {
|
||||
startup_phase_init
|
||||
validation_phase
|
||||
|
||||
Reference in New Issue
Block a user