Self-hosted control panel for Steam dedicated game servers running on a Windows host. Manage Windrose, Satisfactory, Valheim, Palworld, ARK, Rust, and more from a native dark-themed WPF UI — start, stop, backup, update, edit config, and apply live changes over Tailscale from anywhere.
┌────────── your laptop / phone (over Tailscale) ──────────┐
│ │
│ GameServerController.exe (native WPF client) │
│ │ │
│ HTTPS + Bearer token + SignalR (live status push) │
│ │ │
└─────────────┼────────────────────────────────────────────┘
│
┌──────────▼──────────── your gaming server ───────────┐
│ GameServerControl.Agent (ASP.NET Core service) │
│ │ │
│ │ PowerShell SDK in-process │
│ ▼ │
│ Hyper-V cmdlets PowerShell Direct schtasks │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ [Hyper-V VM] [Hyper-V VM] [bare-metal] │
│ game servers game servers game servers │
└──────────────────────────────────────────────────────┘
- Bare-metal and Hyper-V VM hosting — single UI manages both. Bare-metal servers run via Windows Task Scheduler with auto-restart-on-crash wrappers; VM servers use Hyper-V cmdlets + PowerShell Direct.
- 🔍 Auto-discover installed servers — one click scans Steam libraries (via
libraryfolders.vdf+appmanifest_*.acf) and common SteamCMD paths, matches against 11+ known dedicated-server presets, marks already-configured installs. - Per-game config editor — curated schemas (with units, sliders, dropdowns, tooltips) for Valheim · Palworld · Windrose · Satisfactory · ARK · Rust · 7DTD · Terraria · DST · Project Zomboid · Minecraft.
- Auto-discovered settings — when a game ships a defaults file or admin API (Palworld's
DefaultPalWorldSettings.ini, Satisfactory'sGetAdvancedGameSettings), the editor surfaces every setting beyond the curated ones. Palworld jumps from 53 curated fields to 109 total. - Live Satisfactory Admin API integration — claim server, rename, set client password, toggle all 13 Advanced Game Settings (NoPower, GodMode, FlightMode, StartingTier, …) without restarting. Applies instantly.
- Backups — Hyper-V checkpoints for VMs, zipped save-dir archives for bare-metal, with optional scheduled cadence.
- SteamCMD updates — one button validates + updates any Steam-app-ID server.
- Live status + log tail via SignalR.
- RCON — Source-engine RCON for Palworld; pluggable
IGameRconfor adding more. - Audit log — every authenticated mutation lands in
Logs/audit/audit-YYYY-MM-DD.jsonl. - First-run API token auto-generation — no shipped default credentials.
- Tailscale-friendly — designed to bind to a tailnet IP, exposing nothing to the public internet.
| Game | Steam App ID | Curated schema | Auto-discovery |
|---|---|---|---|
| Windrose | 4129620 |
✅ 16 fields (server + world rules) | — |
| Valheim | 896660 |
✅ 27 fields (modifiers, world rules) | — |
| Satisfactory | 1690800 |
✅ 21 fields (incl. live API + AGS) | ✅ via Admin API |
| Palworld | 2394010 |
✅ 53 fields (game mode, pals, players, base, items) | ✅ +56 from DefaultPalWorldSettings.ini |
| ARK: Survival Ascended | 2430930 |
basic preset (Discover finds it) | — |
| ARK: Survival Evolved | 376030 |
basic preset | — |
| Rust | 258550 |
basic preset | — |
| Project Zomboid | 380870 |
basic preset | — |
| 7 Days to Die | 294420 |
basic preset | — |
| Terraria | 105600 |
basic preset | — |
| Don't Starve Together | 343050 |
basic preset | — |
| Minecraft (Java) | n/a | basic preset | — |
Adding a new game with a curated schema is ~30 lines in Shared/ConfigSchema.cs plus an optional IGameConfig implementation to read/write its config file.
src/
GameServerControl.Shared/ DTOs, ConfigSchema, RconModels, DiscoveryModels
GameServerControl.Agent/ ASP.NET Core service (Windows). Talks to Hyper-V and game-server processes.
Auth/ TokenAuthHandler, FirstRunTokenGenerator, AuditLogger
Admin/ SatisfactoryAdminClient (HTTPS Admin API)
Config/ IGameConfig + per-game read/write + dynamic schema providers
Discovery/ Steam library scan + appmanifest parser
Hyperv/ VM control + PowerShell Direct + local process service
Rcon/ Source-engine RCON + Palworld glue
Servers/ Registry, store, orchestrator, status tracker
GameServerControl.Client/ WPF dashboard (the "GameServerController")
.github/workflows/build.yml CI (windows-latest, dotnet 8)
SECURITY.md Threat model + deployment checklist
LICENSE MIT
| Windows | Linux | |
|---|---|---|
| Bare-metal hosting (start/stop/restart/backup/update) | ✅ | ✅ |
| Hyper-V VM hosting | ✅ | ❌ (Hyper-V doesn't exist on Linux) |
| Auto-restart of agent on crash | ✅ (Windows Service) | ✅ (systemd Restart=on-failure) |
| Auto-start of game servers on boot | ✅ (built-in Task Scheduler wrapper) | ✅ (user-written systemd unit — recipe in README) |
| Live status + log tail (SignalR) | ✅ | ✅ |
| RCON (Source-engine + Palworld) | ✅ | ✅ |
| Satisfactory Admin API (AGS, server identity) | ✅ | ✅ |
| Per-game curated config editors | ✅ (4 games × dozens of fields) | ✅ (identical) |
| Auto-discovered config fields | ✅ (Palworld + Satisfactory) | ✅ (identical) |
| 🔍 Auto-discover installed servers | ✅ (registry + Steam library + C:\GameServers) | ✅ (~/.steam, ~/.local/share/Steam, Flatpak, ~/gameservers, /srv, /opt) |
| File-zip backups | ✅ | ✅ |
| Hyper-V checkpoint backups | ✅ | ❌ (Hyper-V only) |
| SteamCMD updates (one-click) | ✅ (uses steamcmd.exe on PATH) |
✅ (uses steamcmd on PATH or Agent:SteamCmdPath) |
| First-run API token auto-generation | ✅ | ✅ |
| Audit log of mutations | ✅ | ✅ |
| HTTPS with self-signed cert | ✅ | ✅ |
| Web UI | ✅ | ✅ |
| Native WPF client | ✅ | ❌ (WPF is Windows-only — use web UI or remote Windows client over Tailscale) |
| Scheduled maintenance (daily restart / weekly update / hourly backup) | ✅ (Windows Task Scheduler) |
- Windows 10 / 11 / Server 2019+
- .NET 8 SDK to build (or grab artifacts from Actions)
- Tailscale recommended
- Hyper-V role only needed if hosting servers inside VMs
git clone https://github.com/tyrus2244/GameServerControl.git
cd GameServerControl
dotnet build -c Release
copy src\GameServerControl.Agent\appsettings.json.example src\GameServerControl.Agent\appsettings.json
copy src\GameServerControl.Agent\servers.json.example src\GameServerControl.Agent\servers.json
dotnet publish src\GameServerControl.Agent -c Release -o C:\GameServerControl\Agent
sc.exe create GameServerControlAgent binPath= "C:\GameServerControl\Agent\GameServerControl.Agent.exe" start= auto
sc.exe start GameServerControlAgent
dotnet publish src\GameServerControl.Client -c Release -o C:\GameServerControl\Client
C:\GameServerControl\Client\GameServerControl.exeOn first agent start, the API token is printed once to the console / Event Log — paste it into the client's Settings.
- Any modern Linux (Debian/Ubuntu, Fedora/RHEL, Arch)
- .NET 8 SDK (install guide)
systemd(standard on all the above)
git clone https://github.com/tyrus2244/GameServerControl.git
cd GameServerControl
sudo bash deploy/linux/install.shThat script:
- Builds + publishes the agent for
linux-x64(framework-dependent) - Installs it to
/opt/gameservercontrol/agent - Creates a system user
gscwith no login shell - Installs the systemd unit
gameservercontrol-agent.serviceand enables/starts it - Tails journalctl long enough to capture the auto-generated API token and prints it for you
After install:
- Service status:
systemctl status gameservercontrol-agent - Live logs:
journalctl -u gameservercontrol-agent -f - Web UI:
http://<this-host>:5099/ - Config:
/opt/gameservercontrol/agent/appsettings.json - Server defs:
/opt/gameservercontrol/agent/servers.json
git clone https://github.com/tyrus2244/GameServerControl.git
cd GameServerControl
dotnet publish src/GameServerControl.Agent -c Release -r linux-x64 --self-contained false -o ~/gsc-agent
cd ~/gsc-agent
cp appsettings.json.example appsettings.json
./GameServerControl.AgentThe agent prints its generated API token on first run. Use that with the web UI at http://localhost:5099/ (or a Windows client over Tailscale).
- VM hosting mode is unsupported. Use
"HostingMode": "BareMetal"only. - Autostart-on-boot for game servers should be done with your own systemd unit per server, e.g.:
The agent's
[Unit] Description=Satisfactory dedicated server After=network-online.target [Service] User=gsc WorkingDirectory=/srv/gameservers/satisfactory ExecStart=/srv/gameservers/satisfactory/FactoryServer.sh -log -unattended Restart=on-failure RestartSec=15s [Install] WantedBy=multi-user.target
ScheduledTaskNamefield is ignored on Linux (it's Task-Scheduler-only). - Auto-discover picks up Steam libraries under
~/.steam/steam,~/.local/share/Steam, and Flatpak Steam installs, plus bare-metal installs under~/gameservers,/srv/gameservers,/opt/gameservers,/var/lib/gameservers. - Scheduled maintenance (the
MaintenanceSchedulerAPI) is Windows-only because it drives Windows Task Scheduler. To get the same effect on Linux, write systemd timers that POST to the agent's own API. Example for a nightly restart at 04:00:# /etc/systemd/system/gsc-windrose-restart.service [Unit] Description=Nightly restart of Windrose via GameServerControl [Service] Type=oneshot ExecStart=/usr/bin/curl -fsS -X POST -H "Authorization: Bearer <YOUR-TOKEN>" http://127.0.0.1:5099/api/servers/windrose-main/restart
Then# /etc/systemd/system/gsc-windrose-restart.timer [Unit] Description=Nightly restart of Windrose [Timer] OnCalendar=*-*-* 04:00:00 Persistent=true [Install] WantedBy=timers.target
sudo systemctl enable --now gsc-windrose-restart.timer. Same pattern for hourly backups (/backup) and weekly updates (/update).
The WPF client only runs on Windows. Linux users use the web UI. On Windows:
dotnet publish src\GameServerControl.Client -c Release -o C:\GameServerControl\Client
C:\GameServerControl\Client\GameServerControl.exeOpen Settings, paste the agent URL (http://100.x.y.z:5099) and the API token, save. Click 🔍 Discover to auto-detect installed servers.
- Auto-detect: click 🔍 Discover → click Add on the row you want → review pre-filled fields → Save.
- Manual: click + Add server, pick a preset for defaults, fill in your install paths, Save.
- Click the Config button on a server's card. The editor shows curated sections at the top (polished labels, dropdowns, sliders) and an "All settings (auto-discovered)" section at the bottom for everything the game exposes that we haven't hand-curated.
- For Satisfactory, the Server identity (live via Admin API) and Advanced Game Settings sections apply instantly — no restart. INI-backed fields require a restart.
- Backup — Hyper-V checkpoint (VM) or zip of
SaveDirs(bare-metal). - Update — runs SteamCMD
+app_update <SteamAppId> validate. - Restart — graceful stop then start.
Every endpoint under /api/* requires Authorization: Bearer <token>. JSON bodies, JSON responses.
| Method | Path | Notes |
|---|---|---|
| GET | /api/health |
Liveness check (no body). |
| GET | /api/discover |
Scan host for installed servers. |
| GET | /api/servers |
List configured servers. |
| POST | /api/servers |
Add a server. |
| PUT | /api/servers/{id} |
Update. |
| DELETE | /api/servers/{id} |
Remove. |
| POST | /api/servers/reload |
Re-read servers.json without restarting the agent. |
| GET | /api/servers/{id}/status |
Live status (Hyper-V state + process state). |
| POST | /api/servers/{id}/start · /stop · /restart · /backup · /update · /apply |
Actions. |
| GET | /api/servers/{id}/config |
Returns merged curated + dynamic schema and current values. |
| PUT | /api/servers/{id}/config |
Save edits. Body: {key: value, ...}. |
| GET/POST | /api/servers/{id}/autostart |
Read or toggle the scheduled-task autostart flag. |
| GET | /api/servers/{id}/rcon/players |
List players via RCON. |
| POST | /api/servers/{id}/rcon/command |
Run an RCON command. |
| GET | /api/download/client |
Download GameServerController.zip (publishes the client zipped). |
SignalR hub at /hubs/status emits statusChanged + logLine events.
Read SECURITY.md before deploying anywhere your friends will touch. Short version:
- No default credentials — token is generated on first boot
- Every mutation is audit-logged
- Bind to Tailscale, not 0.0.0.0
servers.jsoncontains plaintext game-server passwords — protect file permissions- HTTPS is supported but optional; required if exposed outside Tailscale/LAN
PRs welcome. Particularly interested in:
- New game presets (
GamePresets.cs+ConfigSchema.cs+ optionalIGameConfigimpl) - New
IGameRconimplementations - New
IDynamicSchemaExtensionproviders (auto-discover settings for more games) - Hardening items called out as TODO in
SECURITY.md(DPAPI encryption, rate limiting, role-based tokens) - Cross-platform support — agent is Windows-only by design (uses Hyper-V + Task Scheduler + DPAPI), but a Linux variant using systemd + Docker would be neat
MIT — see LICENSE.