Files
m2dev-server/docs/healthchecks.md
2026-04-14 13:58:13 +02:00

5.4 KiB

Healthchecks

This repository contains the operational wrapper for the headless login healthcheck. The underlying smoke client lives in m2dev-server-src.

What Exists

Source repository:

  • tests/login_smoke.cpp
  • binary target: metin_login_smoke

Runtime repository:

  • deploy/healthcheck/metin-login-healthcheck.sh

Installed on the VPS:

  • /usr/local/sbin/metin-login-healthcheck

What The Headless Healthcheck Verifies

The installed wrapper supports two modes:

  • --mode ready
  • --mode full

The full mode performs two headless passes against the live server:

  1. a select-screen create/delete pass
  2. a full auth + channel + ENTERGAME + mall pass

Together they perform the real two-step Metin login flow without a GUI client and cover both character lifecycle and in-game mall open behavior:

  1. Connect to the auth socket.
  2. Complete the secure handshake.
  3. Send login credentials.
  4. Receive AUTH_SUCCESS and the login key.
  5. Open a second connection to the channel socket.
  6. Complete the secure handshake again.
  7. Send LOGIN2 with login + login_key.
  8. Verify EMPIRE.
  9. Verify LOGIN_SUCCESS4.
  10. Create a temporary character on an empty account.
  11. Delete that temporary character on the select screen using the account private code path.
  12. Create a fresh temporary character again.
  13. Select a character slot.
  14. Send ENTERGAME.
  15. Verify MAIN_CHARACTER, PHASE_GAME, TIME, and CHANNEL.
  16. Send /mall_password 000000 through the encrypted chat path.
  17. Verify MALL_OPEN.

This is an end-to-end gameplay-path verification, not just a TCP port check.

How The Wrapper Works

metin-login-healthcheck.sh --mode full does the following:

  • creates two temporary accounts in MariaDB
  • runs metin_login_smoke once in create/delete mode on the select screen
  • runs metin_login_smoke again for the full auth + channel + ENTERGAME flow
  • uses separate temporary accounts because the server enforces a per-account character-create cooldown
  • verifies that the shared safebox/mall DB load bootstrap can open the mall with the default empty password
  • deletes both temporary accounts and any temporary character rows on exit
  • passes the configured client version expected by the server

metin-login-healthcheck.sh --mode ready is intentionally lighter:

  • creates one temporary account in MariaDB
  • runs one headless login flow through auth + channel + character create + select + ENTERGAME
  • does not run the delete pass
  • does not open the mall

This mode is the right readiness probe immediately after a service restart. It verifies that the server is login-ready without depending on the deeper post-login mall path.

It is intended for manual admin use on the VPS.

Usage

On the VPS:

ssh mt2
/usr/local/sbin/metin-login-healthcheck

Readiness-only mode:

/usr/local/sbin/metin-login-healthcheck --mode ready

The smoke binary can also be run directly:

sudo -iu mt2.jakubkadlec.dev \
  /home/mt2.jakubkadlec.dev/metin/build/server-src/bin/metin_login_smoke \
  173.249.9.66 11000 11011 <login> <password>

Or with password passed through the environment:

sudo -iu mt2.jakubkadlec.dev env METIN_LOGIN_SMOKE_PASSWORD='<password>' \
  /home/mt2.jakubkadlec.dev/metin/build/server-src/bin/metin_login_smoke \
  173.249.9.66 11000 11011 <login> --password-env=METIN_LOGIN_SMOKE_PASSWORD

If you want the smoke client to create a temporary character when the account is empty:

sudo -iu mt2.jakubkadlec.dev env METIN_LOGIN_SMOKE_PASSWORD='<password>' \
  /home/mt2.jakubkadlec.dev/metin/build/server-src/bin/metin_login_smoke \
  173.249.9.66 11000 11011 <login> --password-env=METIN_LOGIN_SMOKE_PASSWORD \
  --create-character-name=smoketestchar \
  --client-version=1215955205 \
  --mall-password=000000

Useful direct flags:

  • --json returns a machine-readable summary including timings and emitted events
  • --expect-auth-failure=STATUS treats an auth failure such as NOID or WRONGPWD as a successful negative test
  • --expect-channel-failure=STATUS treats a channel failure as a successful negative test
  • --delete-private-code=CODE creates or reuses a character slot, sends CHARACTER_DELETE, and verifies PLAYER_DELETE_SUCCESS
  • --mall-password=PASSWORD after ENTERGAME, opens the in-game mall via encrypted chat command and verifies MALL_OPEN

Operational CLI:

metinctl healthcheck --mode full
metinctl healthcheck --mode ready
metinctl wait-ready

metinctl wait-ready now uses the lighter ready mode on purpose. The deeper full mode remains available as an explicit admin healthcheck.

Example negative auth test:

sudo -iu mt2.jakubkadlec.dev env METIN_LOGIN_SMOKE_PASSWORD='wrongpass' \
  /home/mt2.jakubkadlec.dev/metin/build/server-src/bin/metin_login_smoke \
  173.249.9.66 11000 11011 someuser --password-env=METIN_LOGIN_SMOKE_PASSWORD \
  --expect-auth-failure=WRONGPWD --json

Security Notes

This does not open a new public network surface. It is a local operational tool.

Current guardrails:

  • no new listening port
  • root-only installed wrapper (/usr/local/sbin/metin-login-healthcheck, mode 700)
  • temporary credentials
  • cleanup trap removes the test account
  • wrapper passes the password through environment instead of command-line plaintext
  • secrets are not committed to git

Remaining trust boundary:

  • anyone with effective root access can still inspect or run the check
  • therefore this tool assumes root is already trusted