Files
m2dev-server/docs/healthchecks.md

5.7 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 public-ready
metinctl healthcheck --mode full
metinctl healthcheck --mode ready
metinctl wait-ready

metinctl public-ready verifies that every enabled client-visible public channel unit is active and that its declared listener port is actually up.

metinctl wait-ready now first waits for the public runtime to be up and only then runs the lighter ready login probe. 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