--- title: Minecraft Server emoji: 🧱 colorFrom: green colorTo: blue sdk: docker app_port: 7860 pinned: false --- # Minecraft Server (Java Edition 1.21.11) [Paper](https://papermc.io) server (1.21.11, build 132) bundled with the [playit.gg](https://playit.gg) agent so it can be reached from a normal Minecraft client, plus a small web control panel that runs in the same container. ## How the networking works A Minecraft Java client speaks raw TCP and the Space only routes HTTPS to `app_port` (7860), so the two cannot meet directly. The playit agent fixes this without any inbound connectivity: it dials **out** to playit's relays and they proxy the public address back down that same connection. The Space only ever makes outbound requests. ``` Minecraft client ──TCP──> playit relay <──outbound──> playitd ──> java server :25565 ``` Port 7860 hosts the **control panel** (live console, commands, stop/restart), which also keeps the Space reporting as running. ## Control panel Open the Space URL in a browser (keep it private if you want - accessing the panel is separate from joining the game): - Live server console with auto-scroll - Send commands (`say hi`, `list`, `whitelist ...`, `/stop`) via the input or quick buttons - **Stop** (graceful, saves the world) and **Restart** - Status badges: server state, RAM/uptime, playit tunnel state - Reading logs/status is open; commands and stop/restart require a password when one is configured ## Panel / API over HTTP From a browser the panel page (`/`) already uses the API below. The public `.hf.space` gateway only reliably forwards **GET** requests (POST bodies get rejected or stripped of their JSON quotes), so the panel talks to the API with GET + query parameters: ```sh # status / logs curl https://USER-SPACE.hf.space/api/status curl "https://USER-SPACE.hf.space/api/log?after=-10" # run a server command curl --get --data-urlencode "cmd=list" https://USER-SPACE.hf.space/api/command curl --get --data-urlencode "cmd=say hello" https://USER-SPACE.hf.space/api/command # stop (graceful) / restart curl --get --data-urlencode "action=stop" https://USER-SPACE.hf.space/api/action curl --get --data-urlencode "action=restart" https://USER-SPACE.hf.space/api/action ``` If a `CONTROL_PASSWORD` is set, add the header `X-Token: ` where the token is `sha256("panel-control:" + CONTROL_PASSWORD)`, and log in first via `POST /api/login` for a panel session. JSON/form POST endpoints also exist (`/api/command`, `/api/action`, `/api/login`) for callers that can reach the container directly (e.g. from inside the Space). ## Setup 1. Create a Space with the **Docker** SDK and push this repo. 2. Generate a playit **secret key** (link in the playit dashboard, "new agent"). 3. Add it in the Space settings under **Variables and secrets** as a **Secret** named `PLAYIT_SECRET`. Do not commit it. 4. (Recommended) Add a second Secret named `CONTROL_PASSWORD` to lock the panel's command/stop/restart actions. Leave it unset only while testing. 5. In the playit dashboard, create a tunnel of type **Minecraft Java** targeting `localhost:25565`, then claim it with this Space's agent. 6. Copy the assigned address and port into the Minecraft client's *Direct Connect* / *Add Server*. ## Configuration | Variable | Default | Notes | | ----------------- | ------- | -------------------------------------------- | | `PLAYIT_SECRET` | unset | Required for the tunnel; server still boots without it | | `CONTROL_PASSWORD`| unset | Gives the panel Open Console / Stop / Restart a password. Leave unset = unlocked (testing only) | | `MC_MEM` | `4G` | Both `-Xmx` and `-Xms` | | `STATUS_PORT` | `7860` | Control panel; must match `app_port` | Server tuning lives in `server.properties` aboard the container. ## Caveats worth knowing - **World persistence depends on your storage.** Fresh Spaces use ephemeral storage and are reset on restart; this space mounts a Storage Bucket at `/data` so the world/`server.properties` survive rebuilds and playit/client count resets only with a rebuild. - **Offline mode is on** (`online-mode=false`), so any username can join and nothing is verified with Mojang. Turn it on if you want real authentication. - **Server jar is Paper 1.21.11 (build 132, Java 21 bytecode).** The Paper bundler re-downloads the Mojang 1.21.11 server jar into `versions/` on first boot. It runs on the pinned `eclipse-temurin:25-jre-jammy` (Java 25) base image since newer JVMs run older class files. Swap `server.jar` and reuse `MC_JAR` if you change versions. - The server auto-restarts on crash (3s backoff) and restarts if the container is recreated, so a failed boot loops in the logs - read the newest trace.