No description
  • Python 53.7%
  • JavaScript 18.2%
  • CSS 13.6%
  • HTML 8.3%
  • Shell 6.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-14 10:54:08 +01:00
apache Fixing the status not hooking into the standard hookups. And making the installer more customisable. 2026-08-08 14:55:40 +01:00
config Cleaned up the instances so it starts blank and added uninstall all flag 2026-08-07 23:11:14 +01:00
fail2ban Adding failtoban coverage 2026-08-08 00:28:17 +01:00
nginx Fixing the status not hooking into the standard hookups. And making the installer more customisable. 2026-08-08 14:55:40 +01:00
public/dashboard Improve desktop dashboard rendering performance 2026-08-13 11:52:41 +01:00
runtime Release Nexus Game Fleet 1.7.0 with trusted-device sessions 2026-08-14 10:54:08 +01:00
scripts Release Nexus Game Fleet 1.7.0 with trusted-device sessions 2026-08-14 10:54:08 +01:00
systemd Adding the ability to add instances from web frontend and allow you upload themes 2026-08-07 22:11:08 +01:00
tests Release Nexus Game Fleet 1.7.0 with trusted-device sessions 2026-08-14 10:54:08 +01:00
README.md Release Nexus Game Fleet 1.7.0 with trusted-device sessions 2026-08-14 10:54:08 +01:00
RELEASE_NOTES_1.7.0.md Release Nexus Game Fleet 1.7.0 with trusted-device sessions 2026-08-14 10:54:08 +01:00

Nexus Game Fleet

A private production control centre for game-server dashboards. Nexus provides live status, start/stop controls, and direct links for Palworld, Final Fantasy XI, Minecraft, and any future dashboard that implements the standard hooks.

Production design

Browser over HTTPS
  -> Apache or Nginx
  -> Nexus on 127.0.0.1:8780
  -> base registry + server-managed operator state
  -> approved dashboard adapter
  -> existing game dashboard API

Routine controls supply only a saved instance ID and one of start, stop, or restart. Dashboard credentials are accepted only in the authenticated add form, sent over the existing HTTPS session, written to the private Nexus state directory, and never returned by an API.

Features

  • Live normalized state for every configured dashboard.
  • An eight-second shared status cache avoids duplicate probes from simultaneous fleet requests. If an upstream dashboard briefly misses a response, Nexus can display its last successful status for at most two minutes while clearly marking the response as stale; after that it reports the connection unavailable.
  • Player counts, uptime, version, and connection health when supplied upstream.
  • Offline and stopped cards show dashes for player and uptime metrics, avoiding stale or misleading values while the game service is not running.
  • Start and stop actions, with optional restart support.
  • Direct links to the complete game dashboards.
  • Authenticated add/edit/remove lifecycle for dashboard-managed instances, with an upstream connection test before additions or edits are saved.
  • Standard hooks plus built-in Palworld, Final Fantasy XI, and Minecraft compatibility profiles.
  • Shared fleet appearance controls for presets, two accent colours, background colour, spacing density, and corner style.
  • Built-in illustrated realm themes and server-saved custom themes with their own card palettes.
  • Per-card symbol, frame, and corner-light controls. The light can follow the selected theme, use a fixed colour, or be removed entirely.
  • Custom PNG, JPEG, or WebP artwork with the Nexus gradient treatment applied automatically above every image, plus optional local palette extraction.
  • Dashboard login with scrypt password hashing and throttling.
  • Optional Fail2ban protection for repeated login failures through the systemd journal.
  • Signed, expiring sessions with HTTPS-only cookies and CSRF checks.
  • Optional trusted-device sessions for native clients, expiring after 180 days.
  • Strict host validation, content security policy, and browser security headers.
  • Loopback-only Python service with no third-party Python packages.
  • systemd hardening plus optional Apache/Nginx HTTPS installer support.

Requirements

  • Ubuntu or another systemd-based Linux distribution.
  • Python 3.10 or newer.
  • Network access from the Nexus host to every linked dashboard API.
  • A DNS hostname for the public Nexus address.
  • For browser access, an HTTPS reverse proxy and TLS certificate. The installer can configure Apache or Nginx, use an existing proxy, or leave proxy setup to the operator.
  • Fail2ban is recommended for an Internet-facing login but is not required for the Nexus service itself.

Verify the package

From the extracted directory:

python3 -m unittest discover -s tests -p 'test_*.py'
bash -n ./scripts/install.sh ./scripts/uninstall.sh ./scripts/package-production.sh
python3 -m json.tool ./config/instances.json.example >/dev/null

Install

For a minimal install that does not change a reverse proxy, run:

sudo bash ./scripts/install.sh --public-host games.example.com

The default --proxy none leaves Apache and Nginx untouched. The default --fail2ban auto installs the Nexus jail when Fail2ban is already present and otherwise continues without it.

For a new Internet-facing host with an existing Let's Encrypt certificate, the installer can install/configure the selected components:

sudo bash ./scripts/install.sh \
  --public-host games.example.com \
  --proxy apache \
  --fail2ban install

Use --proxy nginx for Nginx. Selecting Apache/Nginx authorizes installation of that package through apt-get when missing. --fail2ban install likewise authorizes Fail2ban installation. Nexus never obtains a certificate itself; the default paths are /etc/letsencrypt/live/HOST/fullchain.pem and privkey.pem. Override them with --tls-cert PATH --tls-key PATH.

Use --fail2ban skip when protection is supplied elsewhere or for an isolated test deployment. That choice leaves any existing Fail2ban configuration untouched. See ./scripts/install.sh --help for the complete option list.

The first installation prompts for the Nexus login passphrase and opens with a blank fleet. Sign in and use Add instance to choose only the dashboards you want to monitor. Re-running the installer upgrades the application, explicitly restarts the running service, and preserves production configuration and managed state.

Release 1.2 adds server-managed instances and custom themes. The installer creates /var/lib/nexus-game-fleet; reinstall and uninstall preserve it. Existing instances in /etc/nexus-game-fleet/instances.json remain available and can use uploaded themes too.

Release 1.2.1 adds safe editing and removal for instances created through the dashboard, plus deletion for uploaded themes. Built-in themes and root-managed base instances remain protected from browser deletion.

Release 1.3 makes new installations game-neutral. The initial registry contains no instances or game-specific credential placeholders. Palworld, Final Fantasy XI, Minecraft, and Standard Nexus remain available as add-instance profiles, and their built-in visual themes remain available. Upgrades preserve every existing base and dashboard-managed instance.

Release 1.4 adds an automatically installed nexus-game-fleet Fail2ban jail. The installer validates the existing Fail2ban configuration before changing it, rolls back the service-specific files if the new jail fails validation, enables Fail2ban at boot, and confirms the jail is active. Its default policy is five failed login requests within ten minutes followed by a one-hour ban.

Release 1.4.1 fixes a startup race seen on slower hosts: after restarting Fail2ban, the installer now waits up to 30 seconds for its control socket and the Nexus jail before reporting a genuine failure.

Release 1.4.2 repairs player totals for the production Final Fantasy XI and Minecraft dashboards. Minecraft's flat players_online and players_max fields are normalized automatically. Final Fantasy XI population is read from its authenticated /api/players endpoint without allowing a player-query failure to mark an otherwise healthy realm unavailable. The compatibility fallback also covers preserved dashboard-managed instances and the older profile-less base registry, so no instance needs to be removed or re-added. When a running or unreachable instance supplies no trustworthy population, the fleet summary now displays an unknown value instead of a misleading zero.

Release 1.5 makes the Standard profile accept the common state, overall, or status lifecycle fields. This fixes arbitrary game-labelled cards using the standard hooks against an otherwise compatible dashboard without coupling the adapter to the card's game name. Explicit advanced mapping paths still take priority. It also adds an optional one/two-character card symbol and selectable theme-default, stable-random, circle, diamond, square, or hexagon frame. Finally, Fail2ban and reverse-proxy setup are explicit installer choices instead of unconditional prerequisites.

Release 1.6 makes stopped and offline cards consistently hide player and uptime values. It also adds a shared fleet appearance editor with presets, primary and gradient accents, page background colour or artwork, density, and corner controls. Reusable uploaded themes now carry an explicit three-colour card palette and can derive a safe starting palette locally from their selected image.

Release 1.6.2 redraws card frames inside an unclipped symbol canvas so circle lights and hexagon points remain intact. It also adds a server-persisted dot colour selector with theme-aware, fixed-colour, and None choices.

Release 1.6.3 keeps the Symbol optional marker inside its heading row so the Symbol, Frame, and Dot colour controls share the same baseline.

Release 1.6.4 names the fleet's foundational violet preset Nexus, places it first with GameOps second, and removes surplus empty space from the custom theme editor. Existing saved violet appearance state is migrated to nexus when it is read.

Release 1.6.5 adds a lightweight touch-device rendering profile, pauses fleet polling while the page is hidden, and prevents overlapping refresh requests. The visual design is retained while mobile browsers avoid repeatedly painting off-screen cards, fixed glow layers, and live backdrop blurs during scrolling.

Release 1.6.6 applies the same rendering discipline to desktop browsers. Card hover feedback now uses a short compositor-friendly lift and opacity highlight, while fixed blurred glows, live glass filters, image-filter transitions, and large animated shadow changes are removed from the scrolling surface.

Release 1.7 adds opt-in trusted-device sessions for Nexus Mobile. A client may send "trusted_device": true with the normal /api/login JSON body to receive a signed session that expires 180 days after login. Browser logins and clients that omit the field keep the existing 12-hour lifetime. Signing out invalidates the local cookie immediately; rotating NEXUS_SESSION_SECRET invalidates every outstanding session.

The default listener is 127.0.0.1:8780. To choose another loopback port or operator name on first installation:

sudo bash ./scripts/install.sh \
  --public-host games.example.com \
  --port 8780 \
  --username operator

Add an instance from Nexus

Sign in, select Add instance, and provide:

  • Game and world names, used as the card labels.
  • A host label for your own reference.
  • The public dashboard URL opened by Open dashboard.
  • An optional internal control URL reachable by the Nexus server. If omitted, Nexus uses the public dashboard URL.
  • A compatibility profile and the dashboard login details.
  • An initial built-in or custom theme.
  • An optional one/two-character card symbol, frame, and dot colour. Leave the symbol blank to derive it from the game name. The random frame is deterministic for that instance, so it does not jump between shapes after a refresh. The dot can follow either theme accent, use a fixed colour, or be hidden with None.

Nexus logs into the dashboard and reads its status before saving the new instance. A failed login, unreachable URL, or incompatible response leaves no instance or password behind. A successful instance is available immediately; no service restart or backend file edit is required.

Instances created through this form display an Edit control on their card. It reopens the saved details without exposing the stored password. Leave the password field blank to retain it, or enter a replacement. Nexus verifies the updated connection before committing the changes, and the stable instance ID is retained even when the display name changes. Select the symbol itself on a fleet card to change its one/two-character symbol, frame, and dot colour. This visual change does not require the dashboard connection to be verified again.

The edit panel also provides Remove instance. Removal unregisters the instance and deletes its Nexus-managed credential and appearance override. It does not stop, uninstall, or delete the game server or its linked dashboard. Instances supplied by /etc/nexus-game-fleet/instances.json intentionally do not expose browser edit/remove controls; change those in the configuration file.

Use a separate, least-privileged service account or passphrase where the game dashboard supports one. Managed credentials are protected by the Nexus service account and 0700/0600 filesystem permissions. They are not returned to the frontend, but they are not application-level encrypted at rest, so protect backups of the state directory as secrets.

Standard dashboard hooks

Choose Standard Nexus hooks for any new dashboard that implements the following contract on its control URL.

Login:

POST /api/login
Content-Type: application/json

{ "password": "..." }

If a username is entered, Nexus also sends a username property. A successful login must set an HTTP session cookie and return a CSRF token:

{ "csrf": "token-value" }

Status uses the authenticated session:

GET /api/status
{
  "state": "running",
  "players": { "online": 4, "capacity": 32 },
  "uptime_seconds": 93784,
  "version": "1.2.3"
}

The lifecycle property may be named state, overall, or status; state is recommended for new integrations. Its value may be running, stopped, starting, stopping, degraded, online, offline, or failed. Player data, uptime, and version are optional. This field-name tolerance applies only to the Standard profile's default mapping; an explicit advanced registry mapping is always authoritative.

Controls use the session cookie and login token:

POST /api/action
Content-Type: application/json
X-CSRF-Token: token-value

{ "action": "start" }
{ "action": "stop" }
{ "action": "restart" }

Return any JSON object with an HTTP 2xx status after accepting an action. Keeping this contract in future game dashboards means they can be added from the Nexus UI without changing Nexus code or configuration.

Built-in compatibility profiles

The Palworld, Final Fantasy XI, and Minecraft choices use the same login, status, and action paths but normalize their existing response fields. Final Fantasy XI requires its operator username. The other two profiles use their password-only logins.

All three expect:

Login:   POST /api/login
Status:  GET  /api/status
Action:  POST /api/action  { "action": "start|stop|restart" }

The Final Fantasy XI profile additionally reads its existing authenticated GET /api/players endpoint. A failure of this supplemental request leaves the realm state and uptime available while showing population as unknown.

Advanced base instance registry

The installer creates:

/etc/nexus-game-fleet/instances.json

It begins as a valid empty registry. This root-managed registry remains useful for advanced or non-standard adapters that cannot use the dashboard form:

  • dashboard_url: the HTTPS address opened by the card.
  • control.base_url: the address Nexus can reach from the server.
  • control.auth: none, bearer, basic, or session authentication.
  • control.status: the existing dashboard status endpoint.
  • control.actions: the existing start/stop/restart endpoints.
  • control.mapping: dot-separated paths from the response into Nexus fields.

It is merged with instances added through the UI and reloaded after a valid file change. Invalid changes are rejected and reported in the service journal.

Base-registry credentials live in /etc/nexus-game-fleet.env and are referenced by environment-variable name rather than embedded in JSON. Restart Nexus after editing that environment file:

sudo systemctl restart nexus-game-fleet.service

Fleet appearance

Select Appearance in the Nexus header to change the shared fleet shell. Choose a preset or set the primary accent, secondary gradient accent, and page background directly. Select a colour swatch to use the built-in RGB mixer, or enter an exact six-digit hexadecimal value beside it. Comfortable and Compact adjust page gaps, card padding and modal spacing. Soft, Square, and Round apply a coherent corner treatment to the fleet bar, cards, dialogs, inputs, and controls.

An optional fleet background can be uploaded in the same panel. Nexus accepts PNG or JPEG artwork from 320 x 180 through 4096 x 4096 pixels, up to 5 MiB and 12 megapixels. The preview shows the crop before saving, while the three suggested swatches and Use suggested colours action offer an editable palette derived locally in the browser. The Remove image action returns to the selected background colour. A fixed dark overlay and the Nexus grid remain above artwork to preserve legibility.

Appearance and fleet artwork are saved by Nexus, not in a single browser, so every signed-in operator sees the same result. Reset defaults returns to the standard Nexus appearance and removes the fleet background. Card artwork and its card-specific palette remain part of the reusable theme selected for each instance.

Custom themes

Open an instance's Theme panel to choose a built-in or previously uploaded theme. Select Create theme only when you want to define a new reusable theme. Uploaded themes include an Edit action for changing their name, colours, or background artwork; bundled themes remain read-only. Theme choices are saved on the Nexus server, so every signed-in operator sees the same cards.

The theme editor creates a reusable theme from an image:

  • Recommended: 1200 x 1200 pixels, square, with the main subject around the centre or right side.
  • Suggested minimum: 800 x 800 pixels.
  • Accepted: PNG, JPEG, or WebP, up to 8 MB.
  • Other dimensions still work; Nexus centre-crops the image to fill the card.
  • Window accent, gradient accent, and card background colours can be selected explicitly before upload using the built-in RGB mixer or exact #RRGGBB fields; no operating-system colour dialog is required.
  • Extract from image samples the selected local file in the browser to suggest those three colours. Automatic extraction can be disabled and every suggestion remains editable before the theme is saved.

Nexus always renders its soft horizontal and vertical gradients above custom artwork. This retains the existing visual style and protects text contrast. Image analysis stays in the browser; the file is uploaded only when the theme is submitted. Palette values are validated as six-digit hexadecimal colours and applied through Nexus's authenticated, same-origin stylesheet.

Uploaded themes show a delete control in the theme selector. Deletion requires confirmation, removes the stored artwork and catalogue record, and moves every affected instance to the Nexus fallback theme. Built-in themes cannot be deleted.

Apache reverse proxy

The recommended automated route is:

sudo bash ./scripts/install.sh --public-host games.example.com --proxy apache

For manual setup, copy the included example and replace @@PUBLIC_HOST@@, @@TLS_CERT@@, @@TLS_KEY@@, and @@UPSTREAM@@:

sudo cp ./apache/nexus-game-fleet.conf.example \
  /etc/apache2/sites-available/games.example.com.conf
# Edit the four @@...@@ placeholders before enabling the site.
sudo a2enmod ssl proxy proxy_http headers
sudo a2ensite games.example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

Only reload Apache after Syntax OK.

Nginx reverse proxy

Use --proxy nginx for automated setup. For manual setup, the equivalent template is nginx/nexus-game-fleet.conf.example. Replace all four placeholders, install it in the normal Nginx site directory, run nginx -t, and reload only after validation succeeds.

Operational checks

systemctl status nexus-game-fleet.service --no-pager
sudo journalctl -u nexus-game-fleet.service -n 100 --no-pager
curl -H 'Host: games.example.com' http://127.0.0.1:8780/healthz
python3 -m json.tool /etc/nexus-game-fleet/instances.json >/dev/null

The health endpoint tests Nexus itself. Individual cards report unavailable when an upstream dashboard is unreachable, rejects credentials, or returns invalid JSON.

Security boundary

  • Nexus binds only to loopback; publish it only through an HTTPS reverse proxy.
  • Only an authenticated operator with a valid CSRF token can add a dashboard, upload a theme, change an instance theme, or change fleet appearance.
  • Appearance and theme colours are accepted only as strict six-digit hexadecimal values and rendered by a same-origin generated stylesheet. The content security policy continues to disallow inline styles and remote CSS.
  • Fleet backgrounds accept only validated PNG/JPEG headers, bounded file and pixel dimensions, and are served through an authenticated same-origin URL.
  • After an instance is saved, routine controls accept only its configured ID and an allowlisted action; they cannot override URLs, paths, or credentials.
  • Upstream responses are size-limited and requests have bounded timeouts.
  • Login failures are throttled and all mutations require CSRF verification.
  • Trusted-device sessions are opt-in bearer credentials. Store them only in a platform-protected credential store and sign out before transferring a device.
  • Failed, malformed, and rate-limited login attempts produce password-free structured journal records consumed by the Nexus Fail2ban jail.
  • Control and configuration changes are written to the system journal.
  • The service runs as an unprivileged non-login account with systemd hardening.
  • Restrict public access further with a VPN or reverse-proxy allowlist where practical.

Nexus accepts a forwarded client address only from its loopback reverse proxy and only when it is a valid IP address. Never expose port 8780 directly. Verify the protection with:

sudo fail2ban-client status nexus-game-fleet
sudo journalctl -u nexus-game-fleet.service -f -o cat

Files installed

/opt/nexus-game-fleet/                 runtime and static dashboard
/etc/nexus-game-fleet.env              login and base-registry secrets (0600)
/etc/nexus-game-fleet/instances.json   base dashboard registry (0640)
/var/lib/nexus-game-fleet/             managed instances, credentials, themes,
                                       and shared appearance
/etc/systemd/system/nexus-game-fleet.service
/etc/fail2ban/filter.d/nexus-game-fleet.conf       when enabled
/etc/fail2ban/jail.d/nexus-game-fleet.local        when enabled
/etc/apache2/sites-available/nexus-game-fleet.conf when selected
/etc/nginx/sites-available/nexus-game-fleet        when selected

Back up both /etc/nexus-game-fleet* and /var/lib/nexus-game-fleet. Treat the latter as secret data because it includes managed dashboard credentials.

Upgrade

Extract a newer production archive and rerun the installer. The preserved environment supplies the existing hostname and port when they are omitted. Application and service files are replaced; secrets, the base registry, managed instances, credentials, theme assignments, uploaded artwork, custom theme palettes, and shared appearance are preserved. The installer restarts Nexus before it completes. Proxy and Fail2ban choices are evaluated on each run; --proxy none and --fail2ban skip do not change those external services.

Uninstall

sudo bash ./scripts/uninstall.sh

The uninstaller removes the application, systemd unit, service account, its service-specific Fail2ban filter/jail, and any Nexus proxy site created under the fixed installer names. It never uninstalls Apache, Nginx, or Fail2ban, and does not touch unrelated sites or jails. It preserves /etc/nexus-game-fleet.env, the base registry, and /var/lib/nexus-game-fleet so a later reinstall does not lose configuration.

To permanently remove the application and every Nexus-owned configuration, credential, managed instance, uploaded theme, and assignment:

sudo bash ./scripts/uninstall.sh -a
# --all is equivalent

The full-purge option is deliberately explicit and cannot be undone. It removes only Nexus-owned files; it does not stop or delete any linked game server or dashboard.

Project layout

README.md
apache/
config/
fail2ban/
nginx/
public/dashboard/
runtime/
scripts/
systemd/
tests/

Only these runtime and operations files enter the production archive. Preview hosting metadata, Node dependencies, source-build caches, and example database code are explicitly rejected by the packager.