Clean up README and organize documentation

This commit is contained in:
2026-10-06 23:51:41 -04:00
parent 75b6a0a783
commit 8fcabe27fc
38 changed files with 687 additions and 1249 deletions
+50 -199
View File
@@ -1,228 +1,79 @@
# Electric Cherry
Electric Cherry manages T5 and T6 Plutonium Zombies servers through its own host
agents. Docker and Plutainer run the games; EC handles hosts, game files,
collections, configuration, campaigns, maintenance and operation history.
A self-hosted dashboard for managing Plutonium T5 and T6 Zombies servers.
Electric Cherry handles your fleet, game files, releases, and maintenance from
one web interface. Game servers run on your hosts using Docker, Plutainer, and
a small Python agent.
![Fleet overview showing sample T5 and T6 lobbies, player counts, and match rounds](docs/assets/fleet.png)
*Fleet overview with sample data.*
## Features
- Launch individual servers or saved collections of maps and lobbies.
- Monitor players, host capacity, match history, and leaderboards.
- Manage scripts, plugins, and configuration with beta testing and rollback.
- Queue maintenance around active games and scale spare lobbies with opt-in policies.
- Control access with administrator, operator, and viewer accounts.
## Getting started
Run the controller with Docker Compose behind HTTPS:
You'll need Docker Compose for the controller, an HTTPS reverse proxy, and
Debian 12 or 13 amd64 game hosts. Bring your own game files and Plutonium server keys.
```sh
cp .env.example .env
# Set EC_PUBLIC_URL, generate EC_SETUP_TOKEN, and retain EC_DATA_DIR.
openssl rand -hex 32
```
Edit `.env`: use the generated secret for `EC_SETUP_TOKEN`, set `EC_PUBLIC_URL`
to your HTTPS address, and choose a persistent `EC_DATA_DIR`. Then start the
controller and proxy your HTTPS address to port 3000:
```sh
docker compose up -d --build
```
Open EC and create the first administrator using `EC_SETUP_TOKEN` (at least 32
characters; generate it with `openssl rand -hex 32`). After setup, remove that
token from the environment. Administrators can add administrators, operators and
viewers from **Administration → Users**. See [Users and access](docs/authentication.md)
for permissions, sessions, password recovery and upgrade instructions.
Open the dashboard and create your first administrator with the setup token.
Remove the token from `.env` afterward and recreate the controller with
`docker compose up -d`.
Operator pages and management APIs require login. Enrolled agents authenticate
independently and connect outbound over HTTPS; the
controller needs no Docker socket, game-server mounts or inbound RCON access.
The default Compose data mount preserves the previous
`/root/zombies/.electric-cherry` database location. For a new installation, set
`EC_DATA_DIR` to your preferred persistent directory. Back up that directory,
including SQLite metadata and published game-file storage.
1. Upload your T5 or T6 folder, including DLC, under **Library → Game Files**.
2. Add a machine under **Fleet → Hosts** and run its generated enrollment command.
3. Save your Plutonium keys under **Administration → Keys**.
4. Wait for host setup to finish, then launch a server or collection.
1. **Library → Game Files**: upload the complete local folder under T5 or T6,
including its DLC files. There are no library names or version labels to enter.
Each upload becomes the latest files for that game after verification.
Uploads work before any host is enrolled.
2. **Fleet → Hosts → Add Host**: configure a Debian 12/13 amd64 machine and run its
generated enrollment command. The host automatically prepares its Plutainer
runtime and the latest T5 and T6 files, when available. The host page
shows setup progress. Automatic agent updates are enabled by default.
3. Add the exact Plutonium server keys in **Administration → Keys**, or supply missing keys when
launching.
4. Launch a server or collection. Collection previews show cached capacity
estimates; Apply saves the queue and opens its progress page. Provisioning
checks capacity and assigns each server a host and port when it can start.
The latest game files and default runtime are selected automatically.
CPU/memory allowances learn
from actual container usage, using temporary defaults while calibrating.
See [Native host management](docs/native-hosts.md) for installation, credentials,
storage, failure recovery, API contracts and the live-host acceptance checklist.
**Capacity** shows available CPU, memory, ports, estimated additional servers,
and the shared startup queue. Filter by host or game, inspect each host's limiting
resource, and explore up to seven days of resource headroom.
Existing hosts need the current installer once to enable automatic updates.
Generate it under **Agent access** and rerun it on the same host without
`--reenroll`; identity and game data are preserved. Thereafter hosts check their
controller about every five minutes, verify compatible releases and update agent
code between operations. Failed updates roll back; running game containers
continue. The host page shows update status and the last check.
## Fleet and operations
The sidebar groups pages into **Fleet**, **Library**, **Operations**, **Analytics**,
and **Administration** (administrators only). On small screens, open the navigation
menu in the header. The account menu contains **My account**, including your
browser's display timezone; keyboard shortcuts are available through **?**.
**Operations → Overview** combines work that needs attention, running workflows,
and recent results. Related provisioning attempts and host commands stay grouped
under their workflow. Normal waits for empty lobbies remain under **Running**;
successful routine checks remain in **Host operation history**. Full history is
available on each workflow page.
Server details use **Live**, **Matches**, **Configuration**, **Diagnostics**, and
**History** sections. Hosts use **Overview**, **Servers**, **Setup**, and **Settings**.
Contextual Back links preserve the originating filters and views, while breadcrumbs
show each page's place in the navigation. Existing URLs and server tab links work.
The fleet registry lives in SQLite, independently of host filesystems. Status
combines agent container health, fresh game telemetry and agent-local RCON.
Unreachable hosts report unknown instance state; they do not trigger duplicate
replacements. Running containers continue through controller or agent outages.
Provisioning owns Create, Start, Stop, Restart, Rebuild and Destroy. Commands and
results have durable operation IDs and immutable instance generations. Queues,
capacity reservations and history survive controller restarts. **Rebuild removes
per-instance writable files** and creates a new generation. Shared immutable game
libraries survive rebuilds and destruction.
Disruptive actions wait for a fresh empty lobby or verified stopped container.
The agent rechecks occupancy locally immediately before activation and disruption.
Long player sessions can continue indefinitely. **Drain** prevents new launches
and safely retires existing servers as they become eligible.
Collections save target maps and lobby counts. Fill missing servers adds only the
shortfall; Match collection exactly also queues safe removal of excess servers.
Launch previews use the latest verified files for each game and select an
independent runtime image. If newer game files become available before launch,
refresh the preview to confirm the updated files. Every new launch uses the
latest promoted configuration, scripts and plugins when execution starts. Saved
Plutonium keys are reused by exact server ID and retained after removal.
## Libraries and campaigns
Game Files has one upload slot each for T5 and T6. Uploads preserve the folder's
directory layout and included DLC; there is no separate DLC declaration.
EC records immutable upload IDs, file manifests, checksums and sizes automatically.
Uploads use bounded chunks, support pause/resume and verify checksums before
publication. Actual game files
use dedicated filesystem storage, never SQLite blobs. The last upload to finish
verification becomes that game's latest files, even if it started earlier.
Active hosts always prepare the latest T5 and T6 files when available, including
hosts enrolled later. Hosts first download all files with up to four concurrent
transfers, then verify all checksums in a separate pass before the files become
usable. Both steps show progress, elapsed time, measured speed and an estimated
time remaining for the current step. Interrupted transfers resume. Failed preparation
retries automatically with backoff; the host page reports any blocking condition.
Set `PLUTAINER_IMAGE` to change the default runtime prepared on hosts. Existing
servers retain their existing files and runtime without a forced restart.
Upload history and server references are preserved; unused version files follow the
configured retention policy.
Existing named libraries appear together under their game, with no renaming or
reupload required. Multiple instances on one host share read-only base files.
Scripts, plugins, configuration baselines and overlays retain their versioning,
beta, promotion and rollback workflows. Campaigns stage bytes remotely without
stopping games; activation uses the same occupancy and concurrency gates as
lifecycle operations. Agent before images preserve exact rollback bytes and
operation history.
Artifact bodies are stored once by SHA-256 in SQLite. Versions, staging plans,
rollback snapshots and launch commands reference those shared bytes. The first
startup after this upgrade backfills existing rows transactionally; preserve the
data-directory backup when upgrading. Current agents fetch assigned artifacts
from an authenticated endpoint and verify the hash. Older agents continue to
receive inline content until their automatic update completes.
T5 Zombies uses `t5sp` and `dedicated_sp.cfg`; T6 uses `t6zm` and
`dedicated_zm.cfg`. Map selection generates `electric_cherry_map.cfg`, loaded
after the main config. T6 variants retain their distinct catalog selections.
Game-file uploads and Plutonium runtime revisions are tracked independently.
Game telemetry uses its own `EC_TELEMETRY_TOKEN`; configure reporters to send it
in an authorization header. Anonymous reports are rejected before they can
affect occupancy or game history. Existing JSON payloads are unchanged.
See the [setup guide](docs/guides/getting-started.md) for telemetry, storage,
and the first launch. Host agents connect outbound over HTTPS; the controller
doesn't need a Docker socket or direct access to your game-server files.
## Documentation
- [Fleet concurrency and retention settings](docs/settings.md)
- [Native hosts, storage and operation recovery](docs/native-hosts.md)
- [Users, roles and authentication](docs/authentication.md)
- [Provisioning and safety queues](docs/provisioning.md)
- [Lobby autoscaling implementation plan](docs/lobby-autoscaling-plan.md)
- [Lobby autoscaling and pilot procedure](docs/autoscaling.md)
- [Collections and promoted launch recipes](docs/deployment-blueprints.md)
- [Maintenance](docs/maintenance.md)
- [Beta test plans and game telemetry](docs/beta-test-plans.md)
- [Plugin releases](docs/plugin-releases.md)
- [Metrics](docs/metrics.md)
- [Leaderboard and match history](docs/leaderboard.md)
- [Documentation index](docs/README.md) — setup, operations, releases, and analytics.
- [Development guide](docs/development/README.md) — architecture, checks, and diagnostics.
- [Autoscaling plan](docs/plans/lobby-autoscaling-plan.md) — design and remaining pilot work.
- [Idle CPU research](docs/research/t5-t6-idle-cpu-research.md) — experiments and tradeoffs.
## Development
The controller is SvelteKit/TypeScript with SQLite via better-sqlite3, the Node
adapter and server-sent events. The host agent is Python 3 standard-library code
installed as a systemd service. Hosts do not install Node.js or build EC.
The controller uses SvelteKit, TypeScript, and SQLite. The host agent uses the
Python 3 standard library. For local development, install Node.js 22 and Python 3:
```sh
npm install
npm ci
npm run agent:package
# Export EC_SETUP_TOKEN in your shell using the secret saved for /setup.
export EC_SETUP_TOKEN=$(openssl rand -hex 32)
export BETA_ARCHIVE_DIR=./data/beta-archive
EC_AUTH_ALLOW_HTTP=true npm run dev
```
Open `http://localhost:3000` and use the setup token from your shell. The local
database defaults to `./data/cherry.db`; keep it separate from production data.
```sh
npm run check
npm test
npm run test:agent
npm run build
```
Builds regenerate the downloadable agent, standalone updater and checksum manifest,
and bundle the metrics/leaderboard workers under `build/reports` and native launch
preparation under `build/launch`. `npm run dev` and `npm test` compile those workers
automatically. After editing a report or launch-preparation implementation during
development, restart `npm run dev` to rebuild its worker.
Reports use separate read-only SQLite connections and bounded revision-aware caches;
metrics snapshots can be reused for up to 30 seconds when their inputs are unchanged.
Set `EC_PERF_LOG=true` to log slow request timings, report computation/cache timings,
and event-loop delay. Responses include `Server-Timing`, and browser navigations
record an `ec:navigation` performance measure. `npm run benchmark:leaderboard`
uses an isolated synthetic database; pass `-- --scenario all --baseline-ref <commit>`
to compare full response parity and warm query timings with an earlier revision.
Set `EC_SLOW_SQL_MS=20` to log runtime statements taking at least 20 ms; bound
values and string literals are omitted. It is disabled by default. Before and
after database changes, capture these timings under the same fleet load and run
`npm run diagnostics:database -- /data/cherry.db` inside the controller to report
the largest tables/indexes, database and WAL sizes, and free pages. This command
opens an existing database read-only and does not run app migrations.
The controller uses a 128 MiB page cache and each reader worker uses 32 MiB.
Main-database migrations use a 16 MiB cache with memory mapping disabled; SQLite
temporary storage stays disk-backed during migrations and normal operation.
The container uses `/data/.sqlite-tmp` for SQLite scratch files so a memory-backed
`/tmp` cannot turn a database rebuild into an allocation of the whole database.
Override `SQLITE_TMPDIR` only with another writable, disk-backed directory.
Startup logs identify migration phases, elapsed time and resident memory. A
completed migration is retained across restarts; SQLite rolls back interrupted
transactions and startup retries those migrations. The one-time vacuum still needs disk space for its temporary
copy. Do not remove `cherry.db-wal` to recover from an interrupted upgrade.
For a local data disk, set `EC_SQLITE_MMAP_MB=256` to enable memory-mapped reads.
Query statistics are optimized at startup and hourly; WAL reuse is capped at
64 MiB after checkpoints (active transactions can temporarily grow it larger).
Local controller
metadata defaults to `./data/cherry.db`; use a separate test database when
exercising enrollment. Production agent transport requires HTTPS.
`src/lib/server/hosts` owns enrollment, readiness and command transport;
`src/lib/server/backends` provides instance identity and remote file access;
`src/lib/server/provisioning/native.ts` connects existing lifecycle and campaign
queues to agents; `src/lib/server/game-files` owns immutable game-file uploads and
streaming distribution; `agent/` contains the service, installer and agent tests.
Automated tests use simulated Docker/game hosts. Real Debian installer and
T5/T6 game-server validation remain deployment acceptance work; see the checklist
in the native-host guide.