# 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-.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)).