Same tokens, sidebar shell, components and voice as Hammerhead: teal accent, warm neutrals, status badges with text, dialogs with focus trapping that name what they affect, empty states, skeleton loading, outline icons, 44px touch targets and a slide-in drawer on phones. The strict CSP stays: no inline styles or scripts, so icons and sizes use classes. Adds docs/design.md and scripts/lint-design.mjs (run in CI), capitalizes server error messages in one place, and rewrites interface copy to the voice rules (sentence case, buttons that name the result, no dashes). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
186 lines
9.5 KiB
Markdown
186 lines
9.5 KiB
Markdown
# Megalodon
|
|
|
|
Remote management for ARK: Survival Evolved servers over RCON. One small binary (no database, no
|
|
dependencies) that watches your servers, gives you a web dashboard to run them from, and does the
|
|
boring parts on a schedule.
|
|
|
|
It talks to the server the way the game's own admin console does, so it works with any ARK:SE
|
|
server that has RCON switched on, whether it runs in Docker, on TrueNAS, or on a plain machine.
|
|
|
|
## What it does
|
|
|
|
**Watch**
|
|
- Live status of every server: online or not, players, map, version, RCON latency, uptime, and a
|
|
24-hour player-count graph. No RCON password needed for the map/version/player cap: it also asks
|
|
the game's query port, like the Steam server browser does.
|
|
- Join/leave events, chat log, and an audit trail of everything anyone does from the dashboard.
|
|
- A player database across all servers: first and last seen, total play time, number of visits, notes.
|
|
- A watch list: get an event the moment a particular player joins.
|
|
- Prometheus metrics at `/metrics`.
|
|
|
|
**Control**
|
|
- Save the world, broadcast, chat as SERVER, whisper to one player, kick, set the time of day, set
|
|
the message of the day, wipe wild creatures.
|
|
- **Bans that behave**: with a reason, optionally for a set time, applied to every server in a
|
|
cluster at once, and enforced again whenever the player turns up (even on a server that was
|
|
offline when you banned them). Expired bans lift themselves.
|
|
- **Restarts that warn people**: a countdown with announcements at 30, 15, 10, 5, 2 and 1 minute and
|
|
30 and 10 seconds, a world save first, cancellable at any time. Optionally Megalodon starts the
|
|
server again itself (see `start_command`), and can start it automatically if it stays down.
|
|
- A raw console with history and suggestions, plus saved **macros** (named lists of commands).
|
|
- Cluster actions: broadcast or save on every server in one click.
|
|
|
|
**Automate**
|
|
- **Schedules**: a save every 30 minutes, a daily restart at 04:30 on weekdays, a broadcast every
|
|
hour, any console command on a timer.
|
|
- **Notifications** to Discord, ntfy or any webhook for the events you choose.
|
|
- **Welcome message** whispered to each player who joins.
|
|
- **Chat filter**: warn, then kick or temporarily ban, for words you list.
|
|
|
|
**Share it safely**
|
|
- Three roles: *viewer* (look), *moderator* (talk to players, kick, ban, save), *admin* (everything,
|
|
including the raw console, restarts, schedules and settings).
|
|
- API tokens with the same roles, for scripts and monitoring.
|
|
|
|
## Setting up the server side
|
|
|
|
RCON is off by default. In `GameUserSettings.ini` under `[ServerSettings]`:
|
|
|
|
```ini
|
|
RCONEnabled=True
|
|
RCONPort=27020
|
|
ServerAdminPassword=choose-something-long
|
|
```
|
|
|
|
(or add `?RCONEnabled=True?RCONPort=27020?ServerAdminPassword=...` to the launch command). The
|
|
password you set there is the RCON password.
|
|
|
|
**Do not expose the RCON port to the internet.** RCON is unencrypted and its password is the whole
|
|
admin password. Keep it on your LAN or a VPN; only Megalodon needs to reach it. If Megalodon and
|
|
the server are on the same machine or Docker network, nothing needs to be opened at all.
|
|
|
|
## Installing on Linux (systemd)
|
|
|
|
```sh
|
|
curl -fsSL https://git.veillax.com/Veillax/megalodon/raw/branch/main/deploy/install.sh | sudo sh
|
|
```
|
|
|
|
This downloads the latest release (checking its SHA-256), installs `/usr/local/bin/megalodon`,
|
|
creates a `megalodon` user, `/etc/megalodon/` (settings) and `/var/lib/megalodon/` (data), opens
|
|
`/etc/megalodon/megalodon.env` in your editor, then starts the service and prints the first-run
|
|
admin password. Run it again to upgrade; your settings are kept.
|
|
|
|
Options: `--version v0.1.0`, `--listen 0.0.0.0:8480`, `--source` (build from the repository with Go
|
|
instead), `--no-edit`, `--no-start`, and `--uninstall` (add `--purge` to delete settings and data).
|
|
Download the script and read it first if you prefer: it is [`deploy/install.sh`](deploy/install.sh).
|
|
|
|
## Running it by hand
|
|
|
|
```sh
|
|
# download a release, or: go build ./cmd/megalodon
|
|
./megalodon serve
|
|
```
|
|
|
|
On first run it writes `megalodon.json`, creates a user called `admin` and prints its password
|
|
**once** in the log. Open http://127.0.0.1:8480, sign in, and use **Add server**. Or copy
|
|
[`megalodon.example.json`](megalodon.example.json) and edit it.
|
|
|
|
By default the dashboard only listens on `127.0.0.1`. To reach it from elsewhere, put it behind an
|
|
HTTPS reverse proxy, or expose it through [Hammerhead](https://git.veillax.com/Veillax/hammerhead),
|
|
and set `"cookie_secure": true` and `"trust_proxy": true`. Don't put the dashboard on the open
|
|
internet over plain HTTP.
|
|
|
|
Docker: see [`Dockerfile`](Dockerfile) and [`deploy/docker-compose.yml`](deploy/docker-compose.yml).
|
|
Set `TZ` so scheduled times use your clock.
|
|
|
|
### Commands
|
|
|
|
```
|
|
megalodon serve [-config megalodon.json] [-listen addr]
|
|
megalodon user NAME [ROLE] add a user, or change a password (reads MEGALODON_PASSWORD or stdin)
|
|
megalodon token NAME [ROLE] create an API token (printed once)
|
|
megalodon rcon -addr host:27020 -password PW [COMMAND...]
|
|
one-off console command, or an interactive prompt without a command
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Everything is in one JSON file, and everything except `listen`, `data_dir`, `poll_seconds`,
|
|
`chat_seconds`, `trust_proxy` and `cookie_secure` can be edited from the dashboard (changes are
|
|
written back to the file). See [`megalodon.example.json`](megalodon.example.json).
|
|
|
|
| Setting | Meaning |
|
|
|---|---|
|
|
| `servers[].host`, `rcon_port`, `password` | where to reach the console |
|
|
| `servers[].query_port` | game query port (UDP, usually 27015); `0` turns it off |
|
|
| `servers[].start_command` | shell command that starts the server (`docker start ark-island`, `systemctl start ark`, a script). Runs on the machine Megalodon is on; it must return promptly |
|
|
| `servers[].auto_start` | run `start_command` when the server has been down for `auto_start_after` seconds (default 120), at most every 5 minutes. A server you **Stop** from the dashboard stays stopped |
|
|
| `jobs[]` | `action` is `save`, `broadcast`, `restart`, `command`, `destroy_wild_dinos` or `motd`; use `every` (`"30m"`) **or** `at` (`["04:30"]`, optionally with `days`) |
|
|
| `notify[]` | `kind` is `discord`, `ntfy` or `json`. No `events` list means joins, leaves, up/down, restarts, bans and errors |
|
|
| `poll_seconds` | how often each server is asked who is online (default 10) |
|
|
|
|
Files in `data_dir`: `events.jsonl` (event log, rotated at 20 MB), `players.json`, `bans.json`,
|
|
`samples-<server>.jsonl` (the graph).
|
|
|
|
## API
|
|
|
|
Everything the dashboard does goes through a JSON API. Sign in with `POST /api/login`, or send an
|
|
API token as `Authorization: Bearer mgl_…`.
|
|
|
|
```sh
|
|
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8480/api/servers
|
|
curl -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
|
|
-d '{"action":"broadcast","message":"Restart in 10 minutes"}' \
|
|
http://127.0.0.1:8480/api/servers/island/action
|
|
```
|
|
|
|
`action` is one of `save`, `broadcast`, `say`, `whisper`, `kick`, `ban`, `unban`, `allow`,
|
|
`disallow`, `destroy_wild_dinos`, `set_time`, `motd`, `exec`, `restart`, `stop`, `cancel_restart`
|
|
and `start`. `POST /api/actions` does the same on several (or all) servers. `GET /api/events`,
|
|
`GET /api/players`, `GET /api/stream` (live events, server-sent) and `GET /metrics` round it out.
|
|
|
|
Prometheus: `megalodon_server_up`, `megalodon_players`, `megalodon_players_max`,
|
|
`megalodon_rcon_rtt_ms`, `megalodon_uptime_seconds`, `megalodon_restart_pending`, all labelled by
|
|
`server`.
|
|
|
|
## Security notes
|
|
|
|
- Passwords are stored as PBKDF2-SHA256 hashes; API tokens as SHA-256 hashes. RCON passwords sit in
|
|
`megalodon.json` in plain text (they have to), so the file is written `0600`: keep it that way.
|
|
- Sessions are `HttpOnly`, `SameSite=Strict` cookies, and every change needs a custom header a
|
|
web page on another site can't send. Failed sign-ins are rate-limited per address.
|
|
- The dashboard has a strict Content-Security-Policy and never renders game text as HTML.
|
|
- Values that go into console commands (Steam IDs, messages) are validated and stripped of quotes
|
|
and line breaks, so a player name or message can't inject a second command. The raw console is
|
|
admin-only and recorded in the event log.
|
|
- Moderators can see audit entries; viewers cannot.
|
|
|
|
## Honest limits
|
|
|
|
- It has been tested against a simulated ARK server and unit tests, **not yet against a real
|
|
ARK:SE server**. The console's reply formats (`ListPlayers`, `GetChat`) are parsed leniently, but
|
|
if one differs on your version, [open an issue](https://git.veillax.com/Veillax/megalodon/issues)
|
|
with the raw reply (`megalodon rcon … ListPlayers`).
|
|
- RCON can't read or write `GameUserSettings.ini`, install mods or update the game; restarting
|
|
and updating are left to whatever runs the server (Docker, systemd, SteamCMD).
|
|
- Commands that take an in-game *player ID* rather than a Steam ID (`GiveItemToPlayer`,
|
|
`GiveExpToPlayer`) are available from the console but have no buttons, because RCON doesn't
|
|
report that ID.
|
|
- ARK:SE only (it is untested on ASA, which uses the same protocol but may differ in detail).
|
|
|
|
## Design
|
|
|
|
The dashboard follows the Lightwell design language, the same one Hammerhead uses: teal accent, warm neutrals, a sidebar, status badges with text, and dialogs that name what they affect. See [docs/design.md](docs/design.md). `node scripts/lint-design.mjs` checks the rules a machine can check.
|
|
|
|
## Development
|
|
|
|
```sh
|
|
go test ./...
|
|
go run ./cmd/fakeark & # a pretend server on :27020 (password "secret") with players and chat
|
|
go run ./cmd/megalodon serve
|
|
```
|
|
|
|
Releases are built by the Gitea workflow when a `v*` tag is pushed.
|
|
|
|
Licensed under the AGPL-3.0 (see [LICENSE](LICENSE)).
|