Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Necesse Server + Web UI

License: MIT Docker Compose Node.js React GitHub last commit

A self-hosted Necesse dedicated game server, plus a small password-protected web dashboard to manage it: start/stop the server, edit its settings (world, slots, password, port, MOTD, ...), watch who's online, kick/ban players, and browse logs and world saves — all without touching the command line after initial setup.

Dashboard

Acknowledgments

The Necesse dedicated server Docker image (Dockerfile) that this project runs on top of is BrammyS/necesse-docker-server — all credit for the server containerization itself goes there. This repo adds a web UI (ui/ and control/) alongside it; none of that would exist without BrammyS's original work. If you just want the game server without a UI, use their repo directly.

Why a web UI?

The Necesse dedicated server has no RCON, no HTTP API, and no config file you can hot-reload — every setting is baked into the launch command from environment variables, and changing anything means recreating the container. This UI exists to make that whole cycle (and the day-to-day "who's playing, is it up, show me the logs" questions) a few clicks instead of a docker-compose edit + recreate + tail -f.

Screenshots

Dashboard — status, uptime, CPU/RAM, start/stop/restart Dashboard
Players — live online count, per-player kick/ban, ban list Players
Config — edit server settings, stage → apply (restart) Config
Logs — parsed join/leave events + raw log tail Logs
Saves — world save files and their settings Saves

Features

  • Password-protected — a single admin password (bcrypt-hashed), session cookies, CSRF protection, rate-limited login.
  • Start / stop / restart the game server container.
  • Edit server config — world name, slots, owner, MOTD, password, pause-when-empty, and the host port — staged to a .env file and applied via an explicit "Apply" step that recreates the container.
  • Live player list — real online/max count straight from the server's own console, plus kick and ban/unban.
  • Log-derived "online now" + event history — join/leave events parsed from the server's session logs.
  • World saves browser — lists save files with their parsed worldSettings.cfg.

Architecture

Three containers, one docker-compose.yaml:

 necesse   — the game server itself (BrammyS's image, unmodified)
 control   — small internal sidecar; the ONLY thing holding /var/run/docker.sock,
             exposes a fixed set of operations (start/stop/status/config/kick/ban/...)
             over an internal Docker network — never reachable from outside
 ui        — Express + React, password login, talks to `control` over HTTP

control is split out from ui deliberately: the backend needs Docker-socket access to manage the game server (which is effectively root on the host), and the UI is meant to be reachable from the internet if you want it to be. Keeping the socket out of the internet-facing process means a bug or vulnerability in the web app can't be used to take over the host.

Quick start

  1. Set your admin password.

    cd ui/server
    node scripts/hash-password.js "your-real-password"

    Copy the printed hash into .env as UI_PASSWORD_HASHdouble every $ in it (Docker Compose's own variable interpolation mangles single $ characters, e.g. $2a$12$abc$$2a$$12$$abc).

  2. Copy .env.example to .env (if you haven't already) and fill in the rest — SESSION_SECRET (any long random string), and whatever PASSWORD/SLOTS/WORLD/etc. you want the game server to start with.

  3. Start everything:

    docker compose up -d --build
  4. Open http://<your-host>:3000 (default UI_PORT=3000) and log in.

Configuration

All settings live in the root .env file (see .env.example for the full list with defaults):

Variable Purpose
WORLD, SLOTS, OWNER, MOTD, PASSWORD, PAUSE, GIVE_CLIENTS_POWER, LOGGING, ZIP Passed straight through to the Necesse server (same as BrammyS's image)
HOST_PORT The host-side UDP port players connect to (container-internal port is always 14159)
UI_PASSWORD_HASH bcrypt hash of the admin password (see Quick start above)
SESSION_SECRET Random secret for signing session cookies
UI_PORT Host port the web UI listens on
TRUST_PROXY Set to 1 only if running behind a reverse proxy (e.g. Cloudflare Tunnel) that terminates TLS

Changing the game-server settings through the UI's Config page stages them into .env and only takes effect once you click Apply, which recreates the necesse container (disconnecting any connected players).

Reaching it from the internet

By default the UI is only as exposed as UI_PORT is (i.e. your LAN, unless you port-forward it). If you want to reach it from outside your network, put it behind something like Cloudflare Tunnel with Cloudflare Access in front of it, rather than forwarding a port directly — the backend has Docker-level control over the game server, so it's worth keeping it off the open internet even with a password gate.

Security notes

  • Player identifiers used for kick/ban are always the game's own client id, validated server-side — never a raw shell/console command.
  • JVMARGS is intentionally not editable from the UI (arbitrary JVM flags are a code-execution vector).
  • The control service is the only container with Docker socket access, and its HTTP API only exposes a fixed set of operations — no endpoint accepts an image, bind mount, or command from the caller.

License

MIT — see LICENSE. The base Dockerfile is © BrammyS (necesse-docker-server); the ui/ and control/ additions are new work built on top of it.

About

Self-hosted Necesse dedicated game server with a password-protected web dashboard (Docker Compose: game server + control sidecar + Express/React UI)

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages