File size: 20,686 Bytes
722781c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 | # 📖 Alpha MC — Complete Setup Guide
> Everything explained: what every file does, how to set it up, and how it all works together.
---
## 📋 Table of Contents
1. [How It All Works](#how-it-all-works)
2. [File-by-File Explanation](#file-by-file-explanation)
3. [Step-by-Step Setup](#step-by-step-setup)
4. [HuggingFace Secrets Reference](#huggingface-secrets-reference)
5. [Google Drive Backup Setup](#google-drive-backup-setup)
6. [How to Connect and Play](#how-to-connect-and-play)
7. [Troubleshooting](#troubleshooting)
8. [FAQ](#faq)
---
## How It All Works
```
┌─────────────────────────────────────────────────────┐
│ HuggingFace Space (Docker) │
│ │
│ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ Minecraft │ │ Status Dashboard │ │
│ │ Bedrock │ │ (port 7860, HTTP) │ │
│ │ Server │ │ Shows: status, logs, │ │
│ │ (UDP 19132) │ │ tunnel address, RAM/CPU │ │
│ └──────┬───────┘ └─────────────────────────┘ │
│ │ │
│ ┌──────▼───────┐ ┌─────────────────────────┐ │
│ │ playit.gg │ │ Cron Jobs │ │
│ │ agent │ │ - Backup every 6 hours │ │
│ │ (tunnel) │ │ - Log rotation weekly │ │
│ └──────┬───────┘ └─────────────────────────┘ │
└─────────┼───────────────────────────────────────────┘
│ UDP tunnel
▼
playit.gg servers
│
▼
Your friends' Minecraft (anywhere in the world)
```
**Why playit.gg?** HuggingFace Spaces only expose HTTP (TCP) ports publicly. Minecraft Bedrock uses UDP, which HF doesn't support directly. playit.gg acts as a free UDP tunnel — the Minecraft server connects outward to playit.gg, and players connect to playit.gg's address.
**Why port 7860?** HuggingFace watches this port. If nothing responds on 7860, it marks your Space as "idle" and pauses it. Our status dashboard runs on 7860 and keeps it alive.
---
## File-by-File Explanation
### 🐳 `Dockerfile`
The main blueprint Docker uses to build your container.
**What it does, line by line:**
- `FROM ubuntu:22.04` — Starts with a clean Ubuntu Linux environment
- `ENV DEBIAN_FRONTEND=noninteractive` — Stops apt-get from asking questions during install
- `apt-get install` — Installs tools: curl/wget (downloading), unzip (extracting), python3 (status server + Drive backup), cron (scheduled jobs)
- `pip install` — Installs Python libraries for Google Drive API
- `mkdir -p` — Creates the folder structure: `/data/bedrock-server/`, `/data/scripts/`, `/data/logs/`, `/data/playit_gg/`
- `COPY prepare.sh ... && RUN bash prepare.sh` — Runs the download script at build time (downloads Minecraft + playit)
- `WORKDIR /data/bedrock-server` — Sets the default directory (fixes the path bug from before)
- `COPY server.properties allowlist.json permissions.json ./` — Copies game config INTO the server folder
- `COPY start.sh run.sh status_server.py ./` — Copies startup scripts into server folder
- `COPY backup.sh ... /data/scripts/` — Copies utility scripts to their own folder
- `chmod +x` — Makes all `.sh` scripts executable (runnable)
- `EXPOSE 7860 19132/udp 19133/udp` — Declares which ports the container uses
- `CMD ["bash", "/data/bedrock-server/start.sh"]` — The command that runs when the container starts
---
### 🔧 `prepare.sh`
Runs **once during Docker build** to download Minecraft and playit.
**What it does:**
1. Fetches the Minecraft.net download page with a browser-like User-Agent (so the site doesn't block it)
2. Tries 3 different URL patterns to extract the Bedrock server download link (in case the page layout changes)
3. Downloads the `.zip` with retry logic (retries up to 4 times with exponential backoff: 5s, 10s, 20s)
4. Extracts it to `/data/bedrock-server/`
5. Downloads the latest `playit-linux-amd64` binary from GitHub releases
6. Makes both executables
**Why it runs at build time:** So the Minecraft server binary is baked into the Docker image. Every time your Space restarts, Minecraft is already there — no download wait.
---
### 🚀 `start.sh`
The **main startup script** — this is what runs every time your Space starts.
**What it does, in order:**
1. **Sets up graceful shutdown** — catches SIGTERM signal (when HF stops the container), runs a final backup, stops Minecraft cleanly before exiting
2. **Prints a banner** with system info (CPU cores, RAM, disk)
3. **Warns if SECRET_KEY is missing** so you know immediately if the tunnel won't work
4. **Starts `status_server.py`** on port 7860 — the live dashboard (also prevents HF from pausing the Space)
5. **Starts cron daemon** for scheduled backups and log rotation
6. **Configures playit.toml** — tells playit.gg which local port to tunnel (19132 UDP)
7. **Starts the playit agent** with your SECRET_KEY
8. **Waits up to 180 seconds** for the tunnel to show a claim URL or live address, printing progress every 2 seconds
9. **Starts `bedrock_server`** (the actual Minecraft process), redirecting its output to `/data/logs/minecraft.log`
10. **Starts monitor.sh and health_check.sh** in the background
11. **Keeps running** in a loop, updating the status JSON file every 30 seconds and watching if Minecraft/playit are still alive
**Key fixes from original:**
- No `set -e` (crashes won't kill the whole script)
- Proper SIGTERM trap for graceful shutdown
- Status JSON written continuously so the dashboard has fresh data
---
### 🌐 `status_server.py`
A Python HTTP server that serves a **live web dashboard** on port 7860.
**What it shows:**
- 🟢/🔴 Server online/offline status
- RAM usage (used / total)
- Disk usage (used / total / percent)
- CPU load average
- Tunnel address to copy into Minecraft
- Last 40 lines of the Minecraft server log (auto-scrolled)
**How it works:**
- Reads `/tmp/mc_status.json` (written by `start.sh` every 30 seconds)
- Reads the last 40 lines of `/data/logs/minecraft.log` using the `tail` command
- Reads the playit log to extract the tunnel address
- Generates a full HTML page on every request
- Page auto-refreshes every 15 seconds via a `<meta refresh>` tag
- No dependencies needed beyond Python's built-in `http.server`
**Why this matters:** Without something running on port 7860, HuggingFace marks your Space as idle within minutes and pauses it. This keeps it alive 24/7.
---
### ⚙️ `server.properties`
The Minecraft Bedrock server configuration file.
| Setting | Value | Explanation |
|---|---|---|
| `server-name` | Gaganpreet's Minecraft Server | Name shown in the server browser |
| `gamemode` | survival | Players are in survival mode |
| `difficulty` | hard | Hard difficulty |
| `allow-cheats` | false | No commands like /gamemode |
| `max-players` | 20 | Up to 20 players at once |
| `online-mode` | true | Requires legitimate Xbox/Microsoft account |
| `white-list` | false | Anyone can join (set to true + edit allowlist.json to restrict) |
| `server-port` | 19132 | Main UDP port (IPv4) |
| `server-portv6` | 19133 | IPv6 UDP port |
| `view-distance` | 10 | Chunks loaded around each player |
| `tick-distance` | 4 | Active simulation distance |
| `player-idle-timeout` | 30 | Kick players idle for 30 minutes |
| `level-name` | Bedrock level | Name of the world folder |
| `level-seed` | *(blank)* | Random seed — fill in a number for a specific world |
| `server-authoritative-movement` | server-auth | Server controls player movement (anti-cheat) |
---
### 📋 `allowlist.json`
Controls who can join if `white-list=true` in server.properties.
**Default:** Empty array `[]` — whitelist is disabled so anyone can join.
**To add a player:**
```json
[
{
"ignoresPlayerLimit": false,
"name": "PlayerGamerTag",
"xuid": "2535123456789"
}
]
```
Get a player's XUID from sites like xuidgrabber.com.
---
### 🔑 `permissions.json`
Sets operator/member/visitor permissions for specific players.
**Default:** Empty `[]` — everyone gets the `default-player-permission-level` from server.properties.
**To make someone an operator:**
```json
[
{
"permission": "operator",
"xuid": "2535123456789"
}
]
```
---
### 💾 `backup.sh`
Creates world backups locally and optionally uploads to Google Drive.
**What it does:**
1. Checks if the worlds folder exists and has data
2. Creates a `.tar.gz` archive of the entire `worlds/` folder with a timestamp in the filename (e.g. `world_20240425_143000.tar.gz`)
3. Saves it to `/data/bedrock-server/backups/`
4. Prunes old backups — keeps only the 10 most recent
5. If `GDRIVE_SA_KEY` secret is set → calls `google_drive_backup.py` to upload the new backup to Google Drive
6. If `GDRIVE_SA_KEY` is not set → logs a helpful message and skips Drive upload gracefully
**Run manually:** `bash /data/scripts/backup.sh`
---
### ☁️ `google_drive_backup.py`
Uploads the latest backup `.tar.gz` to a Google Drive folder using a **Service Account** (no browser, works headlessly).
**How it's different from the original:**
- Original used `InstalledAppFlow` → needs a browser popup → **impossible in Docker**
- New version uses a **Service Account** → authenticates silently using a JSON key stored as a base64 HF Secret
- Supports **resumable uploads** with 5 MB chunks → handles large world files reliably
- Shows upload progress percentage
- Auto-deletes oldest Drive backups beyond 10 files
- Cleans up the temp credentials file after upload
**Required HF Secret:** `GDRIVE_SA_KEY` (base64-encoded service account JSON — see setup below)
---
### 🏥 `health_check.sh`
Runs in the background and **automatically restarts** Minecraft or playit if either crashes.
**What it does (every 30 seconds):**
1. Checks if `bedrock_server` process is running — if not, restarts it
2. Checks if `playit` process is running — if not, restarts it with your SECRET_KEY
3. Logs all events with timestamps to `/data/logs/health.log`
**Why this matters:** Without this, if Minecraft crashes at 3am while your friends are playing, the server stays down until you manually restart the Space. With this, it auto-recovers within 30 seconds.
---
### 📊 `monitor.sh`
Logs system resource stats every 60 seconds to `/data/logs/monitor.log`.
**Each log line contains:** timestamp, CPU load average, RAM used/total, disk used/total, Minecraft PID, playit PID.
Useful for diagnosing performance issues or seeing exactly when the server went down.
---
### 🔄 `auto_restart.sh`
A simple utility script to restart Minecraft after a delay.
**Usage:** `bash /data/scripts/auto_restart.sh 10` — restarts after 10 seconds
Called automatically by health_check.sh when needed.
---
### 🕐 `crontab.txt`
Schedules automatic recurring tasks using cron.
```
0 */6 * * * bash /data/scripts/backup.sh
```
→ Runs backup.sh every 6 hours (at 00:00, 06:00, 12:00, 18:00)
```
0 0 * * 0 truncate -s 0 /data/logs/*.log
```
→ Every Sunday at midnight, clears all log files so they don't grow forever
---
### 🗺️ `run.sh`
A simple wrapper that changes directory to the Minecraft server folder and runs `start.sh`. Kept for compatibility.
---
### 🔧 `setup_google_drive.sh`
Run this **on your own computer** (not on HuggingFace) to walk through the Google Cloud setup and generate your `GDRIVE_SA_KEY`. It even base64-encodes the key file for you automatically if `service-account.json` is in the same folder.
---
## Step-by-Step Setup
### Step 1 — Upload all files to HuggingFace
1. Go to your Space: `https://huggingface.co/spaces/Gagan1322/alpha_mc`
2. Click **Files** tab → **Add file** → **Upload files**
3. Upload ALL of these files:
```
Dockerfile
README.md
prepare.sh
start.sh
run.sh
status_server.py
server.properties
allowlist.json
permissions.json
backup.sh
monitor.sh
health_check.sh
auto_restart.sh
crontab.txt
google_drive_backup.py
setup_google_drive.sh
```
4. Commit the changes
---
### Step 2 — Add your playit Secret Key
1. Go to your Space → **Settings** tab → **Repository secrets**
2. Click **New secret**
3. Name: `SECRET_KEY`
4. Value: your playit agent secret key from `https://playit.gg/account/agents`
- **Regenerate your key first!** The old one was exposed in a screenshot.
5. Click **Add secret**
---
### Step 3 — Restart the Space
1. Go to the **App** tab of your Space
2. Click the **⋮** (three dots) menu → **Restart Space**
3. Wait 2-3 minutes for the Docker image to build (first time only)
4. The Space URL will show your live status dashboard
---
### Step 4 — Get the Tunnel Address
1. Open the Space URL in your browser
2. Look at the dashboard — when the tunnel is live, the **Connect Address** section shows something like:
```
abc123.playit.gg:12345
```
3. If it shows a **claim URL** instead:
- Click that URL → sign into playit.gg → accept the tunnel
- Wait 10 seconds → the dashboard will show the live address
---
### Step 5 — Connect in Minecraft
1. Open Minecraft Bedrock Edition on your phone/PC/console
2. Go to **Play** → **Servers** tab → **Add Server**
3. Server Address: paste the `*.playit.gg` address
4. Port: paste the port number after the colon (or leave as 19132 if no port shown)
5. Click **Save** → Join!
---
## HuggingFace Secrets Reference
Add these in: Space → Settings → Repository Secrets
| Secret Name | Required? | Description |
|---|---|---|
| `SECRET_KEY` | ✅ Yes | Your playit.gg agent secret key. Without this, nobody can join. |
| `GDRIVE_SA_KEY` | ❌ Optional | Base64-encoded Google Service Account JSON. Enables Drive backups. |
---
## Google Drive Backup Setup
### Why Service Account instead of OAuth?
The old `credentials.json` approach uses OAuth's "installed app" flow which **opens a browser to sign in**. Docker containers have no browser. It can never work headlessly. A Service Account authenticates with a static JSON key — no browser, no interaction, just works.
### Step-by-Step
**1. Create a Google Cloud Project**
- Go to https://console.cloud.google.com
- Top bar → Select project → New Project → name it `alpha-mc` → Create
**2. Enable Google Drive API**
- APIs & Services → Library → search "Google Drive API" → Enable
**3. Create a Service Account**
- IAM & Admin → Service Accounts → Create Service Account
- Name: `minecraft-backup` → Done
- Click the new account → **Keys** tab → Add Key → Create new key → **JSON** → Download
- This downloads something like `alpha-mc-abc123.json` — rename it to `service-account.json`
**4. Share a Drive Folder with the Service Account**
- Open Google Drive → New folder → name it exactly: `Minecraft-Bedrock-Backups`
- Right-click the folder → Share
- Open `service-account.json` and find the `"client_email"` field — copy that email address
- Paste it in the share dialog → role: **Editor** → Share
**5. Generate the GDRIVE_SA_KEY**
On your computer (Linux/Mac terminal or Git Bash on Windows):
```bash
base64 -w 0 service-account.json
```
This prints a long string of random-looking characters. Copy ALL of it.
On Windows (PowerShell):
```powershell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("service-account.json"))
```
**6. Add to HuggingFace**
- Space → Settings → Repository Secrets → New secret
- Name: `GDRIVE_SA_KEY`
- Value: paste the base64 string
- Add secret → Restart Space
**7. Verify**
- Check `/data/logs/backup.log` after 6 hours
- Should show: `Google Drive upload successful!`
- Check your Google Drive folder — the backup `.tar.gz` should appear there
### Security Rules
- ❌ NEVER commit `service-account.json` to git
- ❌ NEVER upload credentials/key files to HuggingFace files tab
- ❌ NEVER share your service account JSON publicly
- ✅ ONLY store it as a HF Secret (encrypted, not visible in git history)
---
## How to Connect and Play
### Finding the Address
The address is shown in two places:
1. **Status Dashboard** — open the Space URL in any browser
2. **Space Logs** — in the App tab logs, look for `TUNNEL IS LIVE`
### Sharing with Friends
Just give them the `*.playit.gg:PORT` address. They need:
- Minecraft Bedrock Edition (any platform — mobile, PC, Xbox, PlayStation, Switch)
- Add Server → paste address → join
### Adding Friends to Allowlist (optional)
If you want only specific people to join:
1. Set `white-list=true` in `server.properties`
2. Edit `allowlist.json` to add their gamertags and XUIDs
3. Re-upload both files and restart the Space
---
## Troubleshooting
### Space shows "Paused"
- Click the Space → click **Run** or **Restart**
- Make sure `SECRET_KEY` is set in secrets
- The status dashboard on port 7860 should prevent future pausing
### "Tunnel not found" / no address shown
- Check that `SECRET_KEY` is correct (regenerate on playit.gg if needed)
- Open Space logs → look for playit errors
- If you see a claim URL → click it and accept the tunnel on playit.gg website
### Build fails (Docker build error)
- Check that ALL files listed in Step 1 are uploaded
- The most common cause: a file is missing so `COPY` fails
- Check the build logs for which `COPY` line failed
### Server starts but nobody can join
- Make sure you're using the playit.gg address (NOT the HuggingFace URL)
- The HF URL is HTTP only — Minecraft needs the playit.gg address
- Check `online-mode` in server.properties — if `true`, players need a valid Microsoft account
### Minecraft crashes (server goes offline)
- `health_check.sh` should auto-restart it within 30 seconds
- Check `/data/logs/minecraft.log` for the crash reason
- Common causes: out of RAM (HF free tier has limited RAM), corrupted world
### Google Drive backup fails
- Check that `GDRIVE_SA_KEY` is set in HF Secrets
- Verify the Drive folder is named exactly `Minecraft-Bedrock-Backups`
- Verify the folder is shared with the service account email
- Check `/data/logs/backup.log` for the specific error message
### Dashboard not loading / Space gets paused
- `status_server.py` might have crashed
- It should auto-recover but if not, restart the Space
- Check `/data/logs/status_server.log` for Python errors
---
## FAQ
**Q: Is this free?**
A: Yes! HuggingFace Spaces (free tier) + playit.gg (free tier) = $0/month. The limitation is HF's free tier has limited RAM (~16GB shared) and CPU.
**Q: Will the world be lost if the Space restarts?**
A: No! HuggingFace persistent storage keeps `/data` between restarts. Your world is safe. Backups are extra insurance.
**Q: How many players can join?**
A: Up to 20 (set in server.properties). The actual limit depends on the HF server's available RAM — more players = more RAM.
**Q: Can I use mods / behaviour packs?**
A: Yes! Upload your pack files to the Space and place them in the correct Minecraft Bedrock folder under `/data/bedrock-server/`. This requires a bit of manual setup.
**Q: How do I update the Minecraft server version?**
A: Rebuild the Space (Settings → Factory reboot). `prepare.sh` always downloads the latest version from Minecraft.net.
**Q: Can I change the world seed?**
A: Yes — set `level-seed=` in `server.properties` to any number before the world is first created. Once a world exists, changing the seed has no effect.
**Q: How do I give myself operator (admin) permissions?**
A: Edit `permissions.json` with your XUID and set `"permission": "operator"`. Alternatively, if you're the first person to join, type your gamertag in the server console — but there's no easy console access on HF.
**Q: The playit address changes every restart — how do I get a permanent address?**
A: Upgrade to playit.gg Pro ($3/month) for a permanent subdomain. On the free tier the address changes each time.
---
*Alpha MC Setup Guide — All files written and debugged for HuggingFace Spaces + playit.gg*
|