panel v0.9.1 — open-source game server manager

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 23:25:11 -07:00
commit 03a281d009
2161 changed files with 300880 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
# Rust — panel-native module
Panel-native Rust dedicated server, native-Linux (no Wine), debian:12-slim base.
- **Image:** `panel-rust:latest` — built from `./Dockerfile`.
- **Game files:** downloaded by the panel's SteamCMD updater sidecar (app 258550) into the `panel-<id>-game` named volume. Fresh install is ~7 GB; first-ever boot additionally generates a ~500 MB map on the save volume depending on `SERVER_WORLD_SIZE`.
- **Saves:** `panel-<id>-saves` at `/game-saves`. Entrypoint symlinks `<game>/server` into `/game-saves/server/` so SteamCMD validate can't wipe worlds.
- **RCON:** **WebSocket RCON** (Facepunch dropped Source RCON years ago). Panel speaks this via the `websocket_rcon` adapter — `ws://<ip>:28016/<password>` with JSON-framed `{Identifier, Message, Name}` requests. Authenticated via the password in the URL path, not headers.
## Ports
| Port | Proto | Purpose |
|------|-------|---------|
| 28015 | UDP | Main game traffic |
| 28016 | TCP | WebSocket RCON (internal) |
| 28082 | TCP | Rust+ push notifications (optional — only needed for the companion app) |
## RCON commands wired
- `list``playerlist`
- `broadcast {msg}``say {msg}`
- `kick {player}``kick "{player}"`
- `ban {player}``banid {player}`
- `save``server.save`
- `shutdown``quit`
## Log events captured
- **Join:** `<name>[<pid>/<steamid>] has entered the game`
- **Leave:** `<steamid>/<name> disconnecting: <reason>`
## Environment vars
| Var | Default | Notes |
|-----|---------|-------|
| `SERVER_NAME` | `panel Rust` | Shown in the Rust server browser |
| `SERVER_DESCRIPTION` | `Powered by panel` | Browser description / tooltip |
| `SERVER_IDENTITY` | `panel-rust` | Save-tree subdirectory name |
| `SERVER_SEED` | `12345` | Procedural-gen seed |
| `SERVER_WORLD_SIZE` | `3000` | 10006000; smaller = faster |
| `MAX_PLAYERS` | `50` | |
| `RCON_PASSWORD` | `panel_rcon` | RCON auth (URL path) |
| `SERVER_LEVEL` | `Procedural Map` | Map preset |
| `SERVER_URL` | `` | Website URL shown in the browser |
| `SERVER_HEADER_IMAGE` | `` | 512×256 banner image URL |
## Known gotchas
- First-ever boot takes 25 min to generate the world. No players can connect until generation finishes (log: `Server startup complete` is the signal).
- RCON port is published on the container only (panel talks to it over the Docker bridge). Don't expose 28016 externally — password in URL means anyone who sees the URL has full server control.
- If you change `SERVER_WORLD_SIZE` or `SERVER_SEED` on a running server, the next boot wipes the existing world. Rust ties the world to a seed+size pair per identity.
- `libgl1` + a handful of X libs are installed in the image even though the server runs headless; Rust's Unity runtime `dlopen`s them at startup.