Initial Discord bot in Docker behind a per-container Cloudflare WARP tunnel
- discord.js 14 bot with /ping and /warp, periodic WARP egress-IP logging - Dockerfile: node:22-bookworm-slim + cloudflare-warp 2026.7.1377.0 (.deb) - entrypoint boots dbus/warp-svc, registers, connects, verifies warp=on - docker-compose with NET_ADMIN, /dev/net/tun, sysctls, healthcheck - deploy script, README, CHANGELOG, lockfile generated inside Docker Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
# Boots Cloudflare WARP inside this container, verifies the tunnel is up and
|
||||
# that Cloudflare sees us as a WARP client, then hands over to the bot.
|
||||
set -euo pipefail
|
||||
|
||||
log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [entrypoint] $*"; }
|
||||
|
||||
WARP_MODE="${WARP_MODE:-warp}"
|
||||
WARP_CONNECT_TIMEOUT="${WARP_CONNECT_TIMEOUT:-60}"
|
||||
TRACE_URL="https://www.cloudflare.com/cdn-cgi/trace"
|
||||
|
||||
cleanup() {
|
||||
log "shutting down"
|
||||
warp-cli --accept-tos disconnect >/dev/null 2>&1 || true
|
||||
kill "${WARP_SVC_PID:-}" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# --- 1. system dbus (warp-svc talks to warp-cli over it) --------------------
|
||||
mkdir -p /run/dbus
|
||||
rm -f /run/dbus/pid
|
||||
if ! pgrep -x dbus-daemon >/dev/null; then
|
||||
dbus-daemon --system --fork
|
||||
log "dbus started"
|
||||
fi
|
||||
|
||||
# --- 2. WARP daemon ---------------------------------------------------------
|
||||
log "starting warp-svc ($(warp-cli --version | head -n1))"
|
||||
warp-svc >/var/log/warp-svc.log 2>&1 &
|
||||
WARP_SVC_PID=$!
|
||||
|
||||
for i in $(seq 1 30); do
|
||||
if warp-cli --accept-tos status >/dev/null 2>&1; then break; fi
|
||||
if ! kill -0 "$WARP_SVC_PID" 2>/dev/null; then
|
||||
log "warp-svc exited early:"; cat /var/log/warp-svc.log; exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
log "warp-svc is up"
|
||||
|
||||
# --- 3. registration (persisted in /var/lib/cloudflare-warp) ---------------
|
||||
if warp-cli --accept-tos registration show >/dev/null 2>&1; then
|
||||
log "existing WARP registration found, reusing it"
|
||||
else
|
||||
log "no registration found, creating a new one"
|
||||
warp-cli --accept-tos registration new
|
||||
fi
|
||||
|
||||
warp-cli --accept-tos mode "$WARP_MODE" >/dev/null
|
||||
log "mode set to $WARP_MODE"
|
||||
|
||||
# --- 4. connect and wait ----------------------------------------------------
|
||||
warp-cli --accept-tos connect >/dev/null
|
||||
for i in $(seq 1 "$WARP_CONNECT_TIMEOUT"); do
|
||||
if warp-cli --accept-tos status 2>/dev/null | grep -q "Connected"; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
STATUS="$(warp-cli --accept-tos status 2>/dev/null | tr -s '[:space:]' ' ')"
|
||||
log "warp-cli status: $STATUS"
|
||||
|
||||
# --- 5. prove it: Cloudflare must report warp=on and give us the egress IP --
|
||||
TRACE="$(curl -fsS --max-time 15 "$TRACE_URL" || true)"
|
||||
WARP_FLAG="$(echo "$TRACE" | sed -n 's/^warp=//p')"
|
||||
EGRESS_IP="$(echo "$TRACE" | sed -n 's/^ip=//p')"
|
||||
COLO="$(echo "$TRACE" | sed -n 's/^colo=//p')"
|
||||
|
||||
if [[ "$WARP_FLAG" == "on" || "$WARP_FLAG" == "plus" ]]; then
|
||||
log "WARP tunnel verified: ip=$EGRESS_IP warp=$WARP_FLAG colo=$COLO"
|
||||
else
|
||||
log "ERROR: Cloudflare does not see this container as a WARP client (warp='${WARP_FLAG:-none}', ip='${EGRESS_IP:-none}')"
|
||||
log "warp-svc log tail:"; tail -n 30 /var/log/warp-svc.log || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 6. run the bot ---------------------------------------------------------
|
||||
log "starting bot: $*"
|
||||
exec "$@"
|
||||
Reference in New Issue
Block a user