- Python 44.6%
- Shell 22.7%
- JavaScript 14.7%
- CSS 12.5%
- HTML 5.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| apache | ||
| fail2ban | ||
| helpers | ||
| nginx | ||
| systemd | ||
| tests | ||
| web | ||
| install.sh | ||
| README.md | ||
| server.py | ||
| uninstall.sh | ||
Minecraft Server Dashboard
A localhost-only web dashboard for a systemd-managed Minecraft Java Edition Vanilla server. It provides live status, version and resource information, player totals, start/stop/restart controls, an authenticated RCON admin console, extended journal history, official stable-release checks, verified upgrades, backups, and automatic rollback after a failed upgrade.
Release 2026-08-07.2 adds the player-presence panel, interactive command
console, and a separate 300-line service-history panel. Existing installations
can be upgraded by rerunning the installer; the dashboard and Minecraft service
are restarted so the protected RCON credential and new interface take effect.
Release 2026-08-07.3 replaces the oversized overview hero with a compact
operator strip, uses game-neutral Minecraft wording, and removes operating-system
details from the browser interface. Installation documentation remains explicit
about supported server platforms because administrators still need that detail.
Release 2026-08-08.1 adds bundled voxel realm artwork behind the operator
interface. A dark readability veil, translucent forest-glass panels, block-like
green edge lighting, and a matching login surface give the dashboard a stronger
Minecraft identity without changing any controls or making external requests.
The dashboard listens on 127.0.0.1:8765 by default. Put Apache, Nginx, Caddy,
or another HTTPS reverse proxy in front of it; the application never needs to
own ports 80 or 443.
What the installer supports
This is an adoption installer for an existing Vanilla server. It does not download a first Minecraft server, accept the EULA, or create a world.
The existing server must have:
- Linux with systemd (Ubuntu and Debian are the primary targets).
- An existing
.serviceunit that starts Minecraft with Java. - A non-root Linux account for Minecraft.
- A regular
server.propertiesfile in the service working directory. - An existing readable server JAR.
- Python 3, Java, and
sudo.
On Ubuntu, install the dashboard-side prerequisites with:
sudo apt update
sudo apt install python3 sudo unzip
mcrcon is recommended but optional. When available, players receive the
shutdown warning and the helper sends save-all flush and stop. Without it,
systemd sends SIGTERM after the helper exits; Vanilla still performs its normal
save and shutdown, but players receive no RCON warning. The web admin console
does not require mcrcon; it uses the dashboard's built-in native RCON client.
The installer supports custom service names, Linux accounts, directories, JAR names, Java paths, heap sizes, game/RCON addresses, RCON ports, backup locations, staging locations, additional JVM flags, and dashboard ports. For predictable systemd and environment-file handling, managed paths must be absolute and cannot contain whitespace.
Before installing
Identify the current service and inspect it:
sudo systemctl status minecraft-vanilla.service
sudo systemctl cat minecraft-vanilla.service
sudo systemctl show minecraft-vanilla.service \
--property=User,Group,WorkingDirectory,ExecStart
Replace minecraft-vanilla.service with the real unit name. Take a filesystem
or VM-level backup of the Minecraft directory before adopting it. The installer
also saves the original unit file at:
/etc/minecraft/dashboard-original-units/<service>.before-dashboard
The installer will stop and restart Minecraft when it must change RCON settings, migrate data, or activate its wrapper-based systemd unit. Players should be told about the maintenance window.
Install: common layout
If the existing unit is named minecraft-vanilla.service, already declares
its User=, Group=, WorkingDirectory=, Java command, heap settings, and a
versioned JAR such as minecraft_server.26.2.jar, no customization is needed:
unzip minecraft-dashboard.zip
cd minecraft-dashboard
chmod +x install.sh
sudo ./install.sh
The installer prompts for an admin dashboard password of at least 12 characters. An optional, separate user password can be added for friends who should retain normal monitoring and server controls without access to RCON. The installer keeps the existing Minecraft directory in place; data is never moved merely because the directory has a version in its name.
Install: non-standard server
Supply only the values that cannot be detected. For example, this adopts
minecraft.service, which runs as mcserver, uses /srv/minecraft, and has an
unversioned server.jar:
sudo ./install.sh \
--minecraft-service minecraft.service \
--minecraft-user mcserver \
--minecraft-group mcserver \
--minecraft-dir /srv/minecraft \
--server-jar /srv/minecraft/server.jar \
--minecraft-version 26.2 \
--java-bin /usr/bin/java \
--xmx 4G \
--xms 2G \
--java-arg '-XX:+UseG1GC' \
--rcon-port 25575 \
--dashboard-port 8766
An unversioned JAR does not contain enough information to identify the current
release, so --minecraft-version is required in that case. The original JAR is
left in place and copied to the managed name
minecraft_server.<version>.jar. Future official JARs use the same convention.
Run sudo ./install.sh --help for the complete option list.
Optional data migration
Changing --minecraft-dir never moves data implicitly. To deliberately move
an existing working directory to a stable location, provide both the target and
the explicit migration flag:
sudo ./install.sh \
--minecraft-service minecraft-vanilla.service \
--minecraft-dir /opt/minecraft/vanilla \
--migrate-data
The target must not already exist. The installer stops Minecraft before the move and refuses broad or unsafe paths.
Installer options
| Option | Purpose | Default |
|---|---|---|
--minecraft-service NAME |
Existing Minecraft systemd unit | Saved value or minecraft-vanilla.service |
--minecraft-user USER |
Non-root runtime account | Existing unit User= |
--minecraft-group GROUP |
Runtime group | Existing unit Group= or user's primary group |
--minecraft-dir PATH |
Managed server directory | Existing WorkingDirectory= |
--server-jar PATH |
Existing JAR to adopt | JAR parsed from ExecStart= |
--minecraft-version VER |
Current installed release | Marker, JAR name, or directory name |
--migrate-data |
Permit moving data to --minecraft-dir |
Disabled |
--java-bin PATH |
Java executable | Saved/detected path or /usr/bin/java |
--xmx SIZE / --xms SIZE |
Java heap limits | Saved/detected values or 4G/2G |
--java-arg ARG |
Additional JVM argument; repeat for each argument | Existing saved list or none |
--clear-java-args |
Remove the saved additional JVM arguments | Disabled |
--minecraft-host HOST |
Game-port health-check address | 127.0.0.1 |
--rcon-host HOST |
Graceful-stop RCON address | 127.0.0.1 |
--rcon-port PORT |
RCON port | Saved value or 25575 |
--backup-dir PATH |
Pre-upgrade backups | backups/<server-name> beside the server directory |
--staging-dir PATH |
Root-only JAR staging | .dashboard-updater beside the server directory |
--dashboard-port PORT |
Local web listener | Saved value or 8765 |
--reset-dashboard-password |
Prompt for a replacement admin password | Disabled |
--dashboard-password-file FILE |
Read a new admin password without exposing it in shell history | Disabled |
--reset-dashboard-user-password |
Prompt for a restricted user password | Disabled |
--dashboard-user-password-file FILE |
Read or replace the restricted user password | Disabled |
--disable-dashboard-user |
Remove the restricted user login | Disabled |
--rotate-rcon-password |
Generate and activate a new RCON password | First install only |
--insecure-http-cookie |
Permit login over HTTP for local testing | Disabled |
The equivalent environment variables listed by --help are available for
automated installation. Prefer --dashboard-password-file over putting a
password directly in a command or shell history.
Only -Xmx and -Xms are automatically extracted from the old Java command.
If the existing service has flags such as garbage-collector or logging options,
pass each one with a separate --java-arg. Arguments containing whitespace are
intentionally unsupported; use equivalent JVM options that do not require an
embedded space.
What installation changes
The installer:
- Validates the selected service, account, paths, JAR, Java, ports, and package files before moving data.
- Preserves the current directory unless
--migrate-datais supplied. - Saves the original service unit on first adoption.
- Creates a managed versioned copy of an unversioned current JAR.
- Generates a protected RCON password on first installation and synchronizes
it with
server.properties. - Replaces the selected Minecraft unit with a wrapper-based unit using the same selected unit name, account, directory, Java, and heap settings.
- Installs the unprivileged dashboard and the root-owned one-shot updater.
- Creates exact sudo rules for only the selected Minecraft service, updater, and journal streams.
- Restarts services that were running before installation.
The installed unit deliberately ignores an unexpected nonzero exit from the
optional RCON stop helper. A missing or moved mcrcon binary therefore cannot
mark a normal stop as failed or activate Restart=on-failure.
The selected Minecraft unit name stays stable across release upgrades. Its
systemd description changes to show the active release, for example
Minecraft Server (vanilla-26.3).
Resulting layout
Paths marked “selected” reflect installer options rather than fixed values:
<selected Minecraft directory>/
.minecraft-version active release marker
minecraft_server.<version>.jar managed current/previous JARs
<selected backup directory>/ consistent pre-upgrade backups
<selected staging directory>/ root-only verified-download staging
/etc/minecraft/vanilla.env root-owned selected runtime settings
/etc/minecraft/java-args optional additional JVM arguments
/etc/minecraft/credentials/rcon_password
/etc/minecraft/dashboard-original-units/
/var/lib/minecraft-dashboard/minecraft-version
/etc/systemd/system/<selected service>
/etc/systemd/system/<selected service>.d/10-version.conf
/etc/systemd/system/minecraft-dashboard.service
/etc/systemd/system/minecraft-dashboard-upgrade.service
/etc/minecraft-dashboard.env dashboard login/listener configuration
/opt/minecraft-dashboard/ installed web application
Verify installation
Substitute the selected service and dashboard port:
sudo systemctl status minecraft-vanilla.service
sudo systemctl status minecraft-dashboard.service
systemctl show minecraft-dashboard.service --property=NoNewPrivileges
sudo grep '^MINECRAFT_DIR=' /etc/minecraft/vanilla.env
curl -I http://127.0.0.1:8765/
Expected results:
- The dashboard is
active (running). - Minecraft is running if it was running before installation.
NoNewPrivileges=nofor the dashboard because its exact sudo rules require the setuid transition.- The HTTP check returns
HTTP/1.1 200 OK.
HTTPS reverse proxy
Secure cookies are enabled by default, so normal dashboard login requires an HTTPS reverse proxy. The backend remains on localhost and cannot conflict with other services on ports 80/443.
Apache
The included example supports both long-running server-sent event streams:
sudo cp apache/minecraft-dashboard.conf.example \
/etc/apache2/sites-available/minecraft-dashboard.conf
sudo nano /etc/apache2/sites-available/minecraft-dashboard.conf
sudo a2enmod proxy proxy_http headers ssl
sudo a2ensite minecraft-dashboard.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
Replace the hostname, certificate paths, and every occurrence of port 8765
when a different --dashboard-port was selected.
Nginx
An equivalent example is included at
nginx/minecraft-dashboard.conf.example. Replace its hostname, certificate
paths, and dashboard port before enabling it.
For another proxy, forward / to http://127.0.0.1:<dashboard-port> and avoid
buffering or short timeouts on /api/events and /api/update-events.
For temporary localhost testing without HTTPS, reinstall with
--insecure-http-cookie. Do not expose that configuration to an untrusted
network.
Roles and password management
The existing dashboard password is the admin credential. Admin sessions can
monitor and control the server, manage updates, read logs, and use the RCON
console. The optional user credential has the same dashboard access except
that the RCON panel is not rendered, RCON capability is reported as unavailable
to API clients, and direct /api/console requests are rejected with HTTP 403.
Change the dashboard password interactively:
cd /path/to/minecraft-dashboard
sudo ./install.sh --reset-dashboard-password
Or use a root-readable password file:
sudo ./install.sh --dashboard-password-file /root/dashboard-password.txt
Create or replace the restricted user login with a separate root-readable file:
sudo ./install.sh --dashboard-user-password-file /root/dashboard-user-password.txt
The admin and user passwords must each contain at least 12 characters and must be different. Remove the user login and return to admin-only access with:
sudo ./install.sh --disable-dashboard-user
Show the generated RCON password when manual administration requires it:
sudo cat /etc/minecraft/credentials/rcon_password
Use it with mcrcon without copying the password into command history:
sudo sh -c '
export MCRCON_PASS="$(cat /etc/minecraft/credentials/rcon_password)"
export MCRCON_HOST="$(sed -n "s/^RCON_HOST=//p" /etc/minecraft/vanilla.env)"
export MCRCON_PORT="$(sed -n "s/^RCON_PORT=//p" /etc/minecraft/vanilla.env)"
exec mcrcon "list"
'
Rotate the RCON password and keep server.properties synchronized:
sudo ./install.sh --rotate-rcon-password
Player presence and admin console
The dashboard reads the standard Minecraft Java status response every two seconds. It displays the current and maximum player totals and, when the server provides a status sample, the visible player names. A server can omit the name sample while still reporting an accurate total.
The Admin console sends commands over Minecraft's native RCON protocol.
Enter commands such as list, say Server maintenance in ten minutes,
whitelist list, or help without the leading /. Up and Down recall commands
entered during the current browser session. Console output remains in the page
until it is cleared or reloaded.
The console is visible only to an admin session. Console requests require an admin dashboard login and a valid CSRF token; user-role requests are rejected server-side even if they bypass the browser interface. The RCON password is supplied to the unprivileged dashboard as a read-only systemd credential; it is never returned to the browser or written into the dashboard environment. Commands are sent directly to RCON and are never passed to a shell. Because RCON has full Minecraft administrator authority, restrict dashboard access as carefully as SSH administration.
The dashboard deliberately does not attach its web process to the server's
screen session. A web-to-screen bridge would mix terminal state, quoting, and
session ownership. RCON provides request/response command handling without
disrupting an existing screen session.
The Service history panel beneath the main dashboard loads the latest 300 Minecraft and upgrade journal lines, then follows both journals live. The browser retains up to 1,200 lines during the current session and supports copy, clear, and follow controls.
Release checks and upgrades
The dashboard reads .minecraft-version and checks Mojang's official Java
Edition manifest. Only latest.release is considered; snapshots,
pre-releases, and release candidates are ignored.
The Upgrade button starts a fixed root-owned one-shot service. The browser cannot provide a URL, version, path, command, user, or unit name. The updater:
- Resolves Mojang's latest stable release and required Java version.
- Downloads only from approved Mojang/Minecraft Services HTTPS hosts.
- Verifies the published byte count and SHA-1.
- Checks disk space while Minecraft remains online.
- Warns players, saves, and stops Minecraft through RCON.
- Backs up the world and important configuration files.
- Atomically activates the new release and starts the selected service.
- Waits for its configured game endpoint to become reachable.
If the new release fails its health check, the updater preserves the failed state, restores the pre-upgrade world/configuration, reactivates the previous JAR, and starts the old release again. Old JARs are retained.
If a new Minecraft version requires newer Java, the upgrade aborts before
stopping the server. Install that Java runtime, rerun the installer with
--java-bin /path/to/java, then retry.
Reinstalling or updating the dashboard package
Copy/extract a newer package and rerun the installer. Saved custom settings and the dashboard password are detected automatically:
unzip -o minecraft-dashboard.zip
cd minecraft-dashboard
chmod +x install.sh
sudo ./install.sh
If the original installation used a custom service name, it is read from
/etc/minecraft-dashboard.env; the same flags do not need to be repeated.
Uninstall
The normal uninstall removes the dashboard and restores the exact Minecraft systemd unit saved before installation. It preserves integration settings, credentials, release state, and the original-unit backup for recovery:
sudo bash ./uninstall.sh
For an explicit complete dashboard purge, including dashboard-owned configuration, credentials, state, unit backup, and service account:
sudo bash ./uninstall.sh -a
# --all is equivalent
Both modes refuse to run during an active upgrade or when the original unit backup is unavailable. Neither mode stops the running Minecraft process. The restored unit is used on its next restart.
Minecraft worlds, server JARs, server.properties, upgrade backups, and
staging downloads are never deleted. A full purge removes the dashboard-created
.minecraft-version marker but leaves all server content intact.
Logs and troubleshooting
Read the selected service name if it is not known:
sudo grep '^MINECRAFT_SERVICE=' /etc/minecraft-dashboard.env
Then inspect the relevant journals:
sudo journalctl -u minecraft-dashboard.service -n 100 --no-pager
sudo journalctl -u minecraft-vanilla.service -n 100 --no-pager
sudo journalctl -u minecraft-dashboard-upgrade.service -n 100 --no-pager
If a stop log still mentions an inline /bin/bash command or a fixed
/usr/bin/mcrcon, the old Minecraft unit is still installed or loaded. Rerun
this package's installer, then verify the repaired stop helper:
sudo systemctl cat minecraft-vanilla.service | grep ExecStop
The installed line should reference
-/usr/local/libexec/minecraft-dashboard-stop, not an inline RCON command.
Follow frontend access and authentication events live:
sudo journalctl -u minecraft-dashboard.service -f -o cat
The dashboard writes structured lines without passwords or cookies:
[access] ip=203.0.113.20 method=POST path=/api/login status=401
[auth] event=login_failed ip=203.0.113.20 reason=invalid_password attempts=1
[auth] event=login_blocked ip=203.0.113.20 reason=rate_limit attempts=5
Fail2ban
Ready-made systemd-journal filter and jail examples are included. Install them on Ubuntu with:
sudo apt install fail2ban
sudo cp fail2ban/filter.d/minecraft-dashboard.conf \
/etc/fail2ban/filter.d/minecraft-dashboard.conf
sudo cp fail2ban/jail.d/minecraft-dashboard.local.example \
/etc/fail2ban/jail.d/minecraft-dashboard.local
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status minecraft-dashboard
The example bans after five failed or locally blocked login requests in ten
minutes for one hour. Adjust maxretry, findtime, and bantime in the copied
jail file if desired.
Fail2ban receives the client address reported by the trusted local reverse
proxy. Keep the dashboard bound to 127.0.0.1, and ensure any replacement proxy
appends or replaces X-Forwarded-For; never allow clients to reach the backend
directly while trusting that header.
Confirm the dashboard is localhost-only, changing the port when necessary:
sudo ss -ltnp | grep ':8765'
The expected listener is 127.0.0.1:8765, not 0.0.0.0:8765.
Security boundaries
- The installer rejects root as the Minecraft runtime account and refuses broad or unsafe managed paths.
- Data migration is explicit and the target must not exist.
- Dashboard authentication uses an HTTP-only, same-site cookie and CSRF token.
- Admin and user roles are stored in the server-side session. Only admins receive the RCON capability; user status payloads also report the console unavailable.
- Every console command is separately authenticated and CSRF-protected; command text is sent only to the configured Minecraft RCON endpoint, never a shell.
- Five failed logins from one address cause a five-minute lockout.
- Dashboard sessions expire after 12 hours and are cleared by a restart.
- The dashboard account has no shell and cannot edit Minecraft data.
- Sudo permissions name only the installer-selected services and exact journal commands.
- Upgrade configuration is root-owned and checked again by the root updater.
- The dashboard reads a root-published version marker, so it does not need permission to browse a protected Minecraft home or data directory.
- RCON is stored as a protected systemd credential, not in the service unit or runtime environment file.
- Upgrade backups and staging are root-only and outside the live server tree.
- Journal output can contain player names and IP addresses. Prefer a VPN, private DNS, proxy authentication, or an IP allow-list.
Sharing the package
You can give another administrator the ZIP unchanged. They should read this README, identify their existing service values, take a backup, and use either the common installation command or the non-standard example. They should not edit Python, shell, HTML, systemd, or sudoers files for normal layouts; all supported differences are installer options.