#!/bin/bash # Minecraft Bedrock server startup — HuggingFace Spaces LOG_DIR="/data/logs" MC_DIR="/data/bedrock-server" SCRIPTS_DIR="/data/scripts" PLAYIT_HOME="${PLAYIT_HOME:-/data/playit_gg}" PLAYIT_LOG="$PLAYIT_HOME/playit.log" MC_LOG="$LOG_DIR/minecraft.log" STATUS_FILE="/tmp/mc_status.json" mkdir -p "$LOG_DIR" "$PLAYIT_HOME" write_status() { cat > "$STATUS_FILE" </dev/null || echo 'unknown')" } EOF } MC_ONLINE=false; PLAYIT_ONLINE=false; TUNNEL_ADDR="" STARTED_AT=$(date -Iseconds) write_status # SIGTERM is ignored — HuggingFace sends this but we must NOT exit shutdown_handler() { echo "$(date) [INFO] SIGTERM received — ignoring to stay alive." } trap 'shutdown_handler' SIGTERM real_shutdown() { echo "$(date) [SHUTDOWN] Shutting down..." [ -n "$MC_PID" ] && kill -0 "$MC_PID" 2>/dev/null && kill -SIGTERM "$MC_PID" && wait "$MC_PID" 2>/dev/null [ -n "$PLAYIT_PID" ] && kill -0 "$PLAYIT_PID" 2>/dev/null && kill -SIGTERM "$PLAYIT_PID" && wait "$PLAYIT_PID" 2>/dev/null bash "$SCRIPTS_DIR/backup.sh" || true exit 0 } trap 'real_shutdown' SIGINT SIGHUP echo "=======================================================" echo " ⛏️ Alpha MC — Minecraft Bedrock Server" echo "=======================================================" echo " Started : $(date)" echo " CPU : $(nproc) cores" echo " RAM : $(free -h | awk '/Mem:/{print $3 " used / " $2 " total"}')" echo " Disk : $(df -h /data | awk 'NR==2{print $3 " used / " $2 " total (" $5 " full)"}')" echo "=======================================================" [ -z "$SECRET_KEY" ] && echo "⚠️ WARNING: SECRET_KEY not set — tunnel will not work!" # Status dashboard on port 7860 — keeps HuggingFace from pausing echo "[*] Starting status dashboard on port 7860..." python3 "$MC_DIR/status_server.py" > "$LOG_DIR/status_server.log" 2>&1 & STATUS_PID=$! echo "[OK] Status dashboard PID $STATUS_PID" service cron start 2>/dev/null && echo "[OK] Cron started" || echo "[!] Cron unavailable" crontab /data/crontab.txt 2>/dev/null || true # Start Minecraft echo "[*] Starting Minecraft Bedrock server..." cd "$MC_DIR" if command -v script &>/dev/null; then script -q -c "./bedrock_server" /dev/null >> "$MC_LOG" 2>&1 & else ./bedrock_server >> "$MC_LOG" 2>&1 & fi MC_PID=$! sleep 4 if kill -0 "$MC_PID" 2>/dev/null; then echo "[OK] Minecraft started (PID $MC_PID)"; MC_ONLINE=true else echo "[!] Minecraft failed. Logs:"; tail -20 "$MC_LOG" fi write_status # Start playit tunnel cat > "$PLAYIT_HOME/playit.toml" << 'EOF' [tunnel.minecraft-bedrock] type = "minecraft-bedrock" local_ip = "127.0.0.1" local_port = 19132 EOF > "$PLAYIT_LOG" echo "[*] Starting playit tunnel..." TERM=xterm playit --secret "$SECRET_KEY" >> "$PLAYIT_LOG" 2>&1 & PLAYIT_PID=$! echo "[OK] playit started (PID $PLAYIT_PID)" echo "══════════════ WAITING FOR PLAYIT TUNNEL ══════════════" FOUND=0 for i in $(seq 2 2 60); do sleep 2 if ! kill -0 "$PLAYIT_PID" 2>/dev/null; then echo "[!] playit crashed — retrying with fallback..." TERM=dumb playit --secret "$SECRET_KEY" >> "$PLAYIT_LOG" 2>&1 & PLAYIT_PID=$! sleep 5 if ! kill -0 "$PLAYIT_PID" 2>/dev/null; then echo "[!] playit failed again. Log:"; tail -10 "$PLAYIT_LOG" echo "[!] Continuing without tunnel."; break fi fi CLAIM=$(grep -oE 'https://playit\.gg/claim/[A-Za-z0-9_=+-]+' "$PLAYIT_LOG" 2>/dev/null | head -1) if [ -n "$CLAIM" ]; then echo "╔══════════════════════════════════════════════════════╗" echo "║ 🔗 CLAIM YOUR TUNNEL: $CLAIM" echo "╚══════════════════════════════════════════════════════╝" FOUND=1; PLAYIT_ONLINE=true; break fi ADDR=$(grep -oE '[a-z0-9-]+\.playit\.gg(:[0-9]+)?' "$PLAYIT_LOG" 2>/dev/null | head -1) if [ -n "$ADDR" ]; then echo "╔══════════════════════════════════════════════════════╗" echo "║ ✅ TUNNEL LIVE! Connect: $ADDR" echo "╚══════════════════════════════════════════════════════╝" TUNNEL_ADDR="$ADDR"; FOUND=1; PLAYIT_ONLINE=true; break fi echo " [${i}s] waiting..." done [ "$FOUND" -eq 0 ] && echo "[!] No tunnel. Check SECRET_KEY." && tail -10 "$PLAYIT_LOG" write_status "$SCRIPTS_DIR/monitor.sh" & echo "[OK] Monitor PID $!" "$SCRIPTS_DIR/health_check.sh" & echo "[OK] Health check PID $!" echo "══════════════════════════════════════════════════════" echo " 🎮 Server running! Dashboard at the Space URL." echo "══════════════════════════════════════════════════════" # Main loop — NEVER exits, auto-restarts both services while true; do sleep 30 # Auto-restart Minecraft if dead if ! kill -0 "$MC_PID" 2>/dev/null; then MC_ONLINE=false echo "$(date) [WARN] Minecraft died — restarting..." cd "$MC_DIR" if command -v script &>/dev/null; then script -q -c "./bedrock_server" /dev/null >> "$MC_LOG" 2>&1 & else ./bedrock_server >> "$MC_LOG" 2>&1 & fi MC_PID=$!; sleep 4 kill -0 "$MC_PID" 2>/dev/null && MC_ONLINE=true && echo "$(date) [OK] Minecraft restarted PID $MC_PID" else MC_ONLINE=true fi # Auto-restart playit if dead if ! kill -0 "$PLAYIT_PID" 2>/dev/null; then PLAYIT_ONLINE=false echo "$(date) [WARN] playit died — restarting..." TERM=xterm playit --secret "$SECRET_KEY" >> "$PLAYIT_LOG" 2>&1 & PLAYIT_PID=$!; sleep 3 kill -0 "$PLAYIT_PID" 2>/dev/null && PLAYIT_ONLINE=true && echo "$(date) [OK] playit restarted PID $PLAYIT_PID" else PLAYIT_ONLINE=true fi # Auto-restart status dashboard if dead if ! kill -0 "$STATUS_PID" 2>/dev/null; then echo "$(date) [WARN] Status dashboard died — restarting..." python3 "$MC_DIR/status_server.py" > "$LOG_DIR/status_server.log" 2>&1 & STATUS_PID=$! echo "$(date) [OK] Status dashboard restarted PID $STATUS_PID" fi write_status done