CI / test (push) Successful in 2m15s
Downloads the release for this machine and verifies its checksum (or builds from source), creates the service user and folders, writes and opens the environment file, installs the hardened unit and prints the first-run admin password. Re-running upgrades; --uninstall [--purge] removes it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
182 lines
9.2 KiB
Markdown
182 lines
9.2 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).
|
|
|
|
## 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)).
|