# 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@ ║ ║ ║ ║ 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.