Kris 1ff8aecd1a fix(admin): stop maps dump flooding console; cache map list; deeper history
`maps *` ran on every panel open, dumping ~350 .bsp lines into the feed and
evicting real messages. Filter bare .bsp lines from the feed, cache the map list
per server (30 min TTL), and backfill 2500 raw log lines on start so history
shows prior messages after filtering noise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 19:15:28 +03:00
2026-07-04 15:08:26 +03:00
2026-07-04 15:08:26 +03:00
2026-07-04 15:08:26 +03:00

CS 1.6 ReHLDS — self-contained image for many servers on Dokploy

A single reusable Docker image that runs ReHLDS by itself — engine (ReHLDS) + gamedll (ReGameDLL_CS) + Metamod-r + ReUnion (non-steam) are baked in. Deploy it as many times as you want; each server boots a working non-steam CS 1.6 server on first launch, then you upload that server's plugins / maps / configs over SFTP.

Layout

File Purpose
rehlds/ the self-contained image (Dockerfile + baked configs)
docker-compose.yml one game server (rehlds + fastdl + sftp) — deploy per server
docker-compose.infra.yml shared MariaDB + Adminer + fastdl + autoheal — deploy once
docker-compose.admin.yml web admin UI (dashboard + RCON console + live feed) — deploy once
admin/ the admin UI service (Node)
.env.example / .env.infra.example / .env.admin.example per-server / shared / admin settings
fastdl/nginx.conf fastdl (asset-only, secrets denied)
rehlds/compress-fastdl.sh pre-compress fastdl assets to .bz2 (baked into image)

Each server = its own isolated cstrike volume + its own ports. Admin = Dokploy (deploy/logs/CPU/restart) + Adminer (DB) + your in-game AMXX menu once you add AMXX.

Baked versions (pinned)

ReHLDS 3.15.0.896 · ReGameDLL 5.30.0.814 · Metamod-r 1.3.0.149 · ReUnion 0.2.0.25 Base: hldsdocker/cstrike:steam_legacy. Bump the *_URL ARGs in rehlds/Dockerfile to update.


One-time setup

Both stacks attach to dokploy-network (Dokploy creates this automatically). For a plain (non-Dokploy) host, create it once: docker network create dokploy-network.

cp .env.infra.example .env.infra   # set DB passwords
docker compose -f docker-compose.infra.yml up -d   # shared DB + Adminer

On Dokploy: deploy docker-compose.infra.yml as a Compose app (git source, compose path docker-compose.infra.yml).

Add a server

cp .env.example .env               # set SERVER_NAME + unique PORT/FASTDL_PORT/SFTP_PORT
docker compose up -d --build       # first app build tags cs16-rehlds:latest

On Dokploy: Create → Compose per server, same repo, different env:

Server PORT FASTDL_PORT SFTP_PORT
1 27015 27080 2222
2 27016 27081 2223
3 27017 27082 2224

Each app gets its own cstrike volume automatically. To avoid rebuilding the image in every app, build once and push to a registry (GHCR/Docker Hub), then set image: <registry>/cs16-rehlds:latest and drop the build: block.

Add your files (per server, over SFTP)

Connect: sftp -P <SFTP_PORT> csadmin@YOUR_VPS_IP (password from .env). You land in cstrike/. Upload:

  • AMX Mod Xaddons/amxmodx/…, then uncomment its line in addons/metamod/plugins.ini.
  • Plugins (.amxx) → addons/amxmodx/plugins/ + list them in addons/amxmodx/configs/plugins.ini.
  • Mapsmaps/, custom wads/models/sounds → their dirs.
  • Server-specific server.cfg, mapcycle.txt, motd.txt, ban files — overwrite as needed.

Restart the server (Dokploy button) to load new metamod modules.

Database (per server)

AMXX plugins that use MySQL read addons/amxmodx/configs/sql.cfg. Point it at the shared DB:

amx_sql_host "db"
amx_sql_user "amx"
amx_sql_pass "<DB_PASSWORD>"
amx_sql_db   "amx_1"      # give each server its own DB (create it in Adminer), or share one
amx_sql_type "mysql"

Import an existing dump via Adminer (:8081) or: gunzip < dump.sql.gz | docker compose -f docker-compose.infra.yml exec -T db mysql -uamx -p amx_1

Fast download

Set FASTDL_URL in each server's .env. Pre-compress assets so clients download faster:

docker compose exec rehlds compress-fastdl

(fastdl serves only game assets — server.cfg, sql.cfg, addons/, logs are denied.)

Firewall (per server)

  • PORT/udp — game (public)
  • FASTDL_PORT/tcp — fastdl (public or behind Traefik)
  • SFTP_PORT/tcp — sftp (restrict to your IP)
  • 8081/tcp — adminer (restrict to your IP)
  • 3306 — never expose (DB internal only)

Reusing files from your old backup

Your cs-qgs-backup tar holds a full working server. To seed a server with it, just SFTP the relevant pieces (its addons/, maps/, *.cfg, *.wad) into that server's volume — no need to mount the whole 3.6 GB tree. The baked engine already matches (ReHLDS/ReGameDLL/Metamod-r/ReUnion), so your compiled .amxx plugins keep working.

Health & auto-restart

Each game container has an A2S healthcheck (healthcheck.sh) — it's healthy only while the engine answers queries, so a hung server (not just a crashed one) is caught. restart: unless-stopped handles crashes; the autoheal service in the infra stack watches every container labeled autoheal=true and restarts any Docker marks unhealthy. Check state: docker psSTATUS column shows (healthy) / (unhealthy).

Admin UI (all servers)

One web dashboard for every server — live status (map, players, ping), a per-server RCON console with a real-time in-game feed (chat, connects, kills, map changes), one-click kick / ban / change map / broadcast, and a player-stats page (unique players per server per day, date-pickable, with the exact nickname list). Node service in admin/, deploy once. It auto-discovers the running ReHLDS containers and the MariaDB via the Docker socket — no server list to maintain.

cp .env.admin.example .env.admin   # set ADMIN_USER/PASS, ADMIN_RCON_PASSWORD, DB_PASSWORD
docker compose -f docker-compose.admin.yml up -d --build

On Dokploy: Create → Compose, compose path docker-compose.admin.yml. In the app's Environment set ADMIN_USER, ADMIN_PASS, ADMIN_RCON_PASSWORD, DB_PASSWORD. Add domain admin.thealphaspot.com → HTTPS, container port 3000.

  • Discovery: the backend lists containers over the mounted docker.sock (read-only), matches the cs16-rehlds image, and reaches each one by its dokploy-network IP + internal port. New servers appear automatically (~20s). The MariaDB is discovered the same way.
  • Live feed: the console streams each game container's stdout straight off the Docker socket (docker logs -f, same as a game panel) — full history + live chat/kills/map changes, no logaddress. The RCON password echoed in that stdout is redacted before it reaches the browser. Set DEBUG_FEED=1 to log received console lines on the admin.
  • Player stats: every 5 min it samples each server's status, skips bots, and UPSERTs each nickname into admin_player_seen (one row per server+player+day) in the amx DB.
  • Auth: built-in HTTP Basic (ADMIN_USER/ADMIN_PASS) covers HTTP + the WebSocket; put HTTPS in front via the Dokploy domain. RCON/DB passwords never reach the browser.
  • Security note: mounting docker.sock grants the container control of the Docker daemon (root-equivalent). It's read-only and only used for GET calls here, but keep the UI locked.

Notes

  • Non-steam works out of the box (ReUnion, cid_NoSteam47/48 = 3). Override reunion.cfg via SFTP if you want a different auth scheme.
  • Skip Pterodactyl/Pelican/cstrikeCP — they bring their own daemon that fights Dokploy for the Docker socket. Here Dokploy is the only orchestrator.
Description
No description provided
Readme 192 KiB
Languages
JavaScript 70.1%
CSS 10.4%
Shell 8.9%
Dockerfile 5.6%
HTML 5%