Files
Megalodon/README.md
T
VeillaxandClaude Sonnet 5.5 0d2cb31abf
CI / test (push) Successful in 2m26s
Release / release (push) Successful in 2m36s
Megalodon: manage ARK servers over RCON from a web dashboard
Watches any number of ARK:SE servers (RCON for players and chat, the query
port for map, version and player cap), records joins, leaves, chat and an
audit trail, and keeps a player database across servers.

Control: save, broadcast, chat, whisper, kick, time of day, MOTD, wild dino
wipe, a raw console with history and macros, restarts with timed warnings and
a world save, optional start command and auto-start. Bans are kept by
Megalodon: timed, cluster-wide and re-enforced when the player returns.

Automation: schedules (every N or at times of day), Discord/ntfy/webhook
notifications, welcome message, chat word filter.

Access: viewer, moderator and admin roles, API tokens, Prometheus metrics.
cmd/fakeark simulates a server for trying it out.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 23:36:13 -06:00

167 lines
8.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.
## Running it
```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).
## 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)).