docs: add server runtime audit #1

Open
jann wants to merge 2 commits from jann/m2dev-server:claude/server-runtime-audit into main
Showing only changes of commit f2b55949de - Show all commits

89
docs/server-topology.md Normal file
View File

@@ -0,0 +1,89 @@
# Server topology
Companion diagram + port table for `docs/server-runtime.md`. Describes the
*intended* production layout of the Debian VPS m2 stack. What is live today is
only a subset (see the runtime audit for the actual state).
## ASCII diagram
```
┌─────────────────────────────┐
│ Players │
│ (Metin2.exe + launcher) │
└──────────────┬──────────────┘
│ TCP (11000 auth, 11011..11013
│ channel1, 11991 channel99)
════════════════════════════ mt2.jakubkadlec.dev ════════════════════════════
║ ║
║ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ ║
║ │ metin-auth │ │ metin-game@ch1_c1│ │ metin-game@ │ ║
║ │ (game_auth) │ p2p │ (channel1_core1) │ p2p │ ch99_c1 │ ║
║ │ :11000 client │◄────►│ :11011 client │◄────►│ :11991 client │ ║
║ │ :12000 p2p │ │ :12011 p2p │ │ :12991 p2p │ ║
║ └────────┬─────────┘ └────────┬─────────┘ └────────┬───────┘ ║
║ │ │ metin-game@ch1_c2/c3 │ ║
║ │ │ :11012/12012 :11013/12013 ║
║ │ │ │ ║
║ │ DB proxy/cache layer │ │ ║
║ └────────────┐ ┌─────────┴─────────────┐ ┌────────┘ ║
║ ▼ ▼ ▼ ▼ ║
║ ┌──────────────────────────────────┐ ║
║ │ metin-db (db) │ ║
║ │ bind 0.0.0.0:9000 │ ║
║ │ (gated by metin-db-ready.svc) │ ║
║ └──────────────┬───────────────────┘ ║
║ │ SQL ║
║ ▼ ║
║ ┌──────────────────────────────────┐ ║
║ │ mariadbd 11.8.6 │ ║
║ │ 127.0.0.1:3306 │ ║
║ │ DBs: account, player, common, │ ║
║ │ log, hotbackup │ ║
║ └──────────────────────────────────┘ ║
║ ║
║ systemd orchestration: ║
║ metin-server.service (oneshot umbrella, PartOf everything) ║
║ ├─ Requires mariadb.service ║
║ └─ metin-db → metin-db-ready → metin-auth + metin-game@<instance> ║
║ ║
║ Secrets: ║
║ /etc/metin/metin.env (root:root 600, EnvironmentFile= for all units) ║
║ ║
════════════════════════════════════════════════════════════════════════════
```
## Process / port table
| Process name | systemd unit | Client port | P2P port | Binds to | Role | Config file |
| ---------------- | ------------------------------------- | ----------- | -------- | ---------- | ----------------------------------------------------- | ----------------------------------------------------- |
| `db` | `metin-db.service` | 9000 | — | `0.0.0.0` | DB proxy/cache; talks to MariaDB, serves auth+game | `share/conf/db.txt` (+ `/etc/metin/metin.env`) |
| `game_auth` | `metin-auth.service` | 11000 | 12000 | (default) | account login, token handoff to channels | `channels/auth/CONFIG` |
| `channel1_core1` | `metin-game@channel1_core1.service` | 11011 | 12011 | (default) | ch1 core1, MAP_ALLOW 1 4 5 6 3 23 43 112 107 67 68 72 208 302 304 | `channels/channel1/core1/CONFIG` |
| `channel1_core2` | `metin-game@channel1_core2.service` | 11012 | 12012 | (default) | ch1 core2, same channel different core | `channels/channel1/core2/CONFIG` |
| `channel1_core3` | `metin-game@channel1_core3.service` | 11013 | 12013 | (default) | ch1 core3 | `channels/channel1/core3/CONFIG` |
| `channel99_core1`| `metin-game@channel99_core1.service` | 11991 | 12991 | (default) | ch99 core1, event/test channel. MAP_ALLOW 113 81 100 101 103 105 110 111 114 118 119 120 121 122 123 124 125 126 127 128 181 182 183 200 | `channels/channel99/core1/CONFIG` |
| `mariadbd` | `mariadb.service` (distro pkg) | 3306 | — | `127.0.0.1`| relational store | `/etc/mysql/mariadb.conf.d/*` |
Supporting, not a process:
| Unit | Type | Purpose |
| -------------------------- | ------- | ---------------------------------------------------------------- |
| `metin-server.service` | oneshot | umbrella. Restarting it cycles all sub-units via `PartOf=`. |
| `metin-db-ready.service` | oneshot | `metin-wait-port 127.0.0.1 9000 30` — gates auth+game on db up. |
## Data flow
1. Player connects to `mt2.jakubkadlec.dev:11000` (auth).
2. `game_auth` authenticates against `account` via `db` (`127.0.0.1:9000`)
which proxies to MariaDB.
3. `game_auth` hands the player a token and the channel pick.
4. Player connects to e.g. `:11011` (channel1 core1). The core reads player
state via `db` from `player` + `common`, loads maps per `MAP_ALLOW` and
quest binaries from `share/locale/`.
5. Cross-core traffic (channel switch, whisper, guild) uses the P2P ports
(`12000`, `12011`..`12013`, `12991`) on loopback.
6. `db` persists to MariaDB asynchronously (`AsyncSQL` pools, batch-writes
at `SAVE_EVENT_SECOND_CYCLE=180`s from `game.txt`).
7. `log` DB receives audit/event rows (item trades, combat, etc.) through
a dedicated `AsyncSQL` connection.