Getting started

A server in Docker

ghcr.io/amxts/server is a Docker image of a Linux Counter-Strike 1.6 server that runs amxts: HLDS with ReHLDS, ReGameDLL, Metamod-R, AMX Mod X 1.10 and ReAPI, the amxts module and its compiler. Your project is mounted into it, and the server runs your plugins with your configs and files - on Windows, macOS or Linux, with nothing to install but Docker.

Every amxts release has its image: ghcr.io/amxts/server:0.2.0 is the server of amxts 0.2.0, and ghcr.io/amxts/server (the tag latest) is the newest one. docker run downloads it the first time; docker pull ghcr.io/amxts/server takes a newer latest.

One version with the project
The server loads only plugins compiled by the same release of amxts: run the image of your project's version (@amxts/core in its package.json). A plugin built by another release is refused, and the console says which one to build again: [amxts] myplugin.aot was built for amxts 0.1.0, this is 0.2.0 - build it again. npx amxts dev --docker prints the docker run line with your project's version.

Run it

Build the plugins for Linux, then start the server with the project mounted at /project:

npx amxts build --os linux
docker run --rm -it -p 27015:27015/udp -v "${PWD}:/project" ghcr.io/amxts/server

On Windows the folder can be written as it is: -v D:\my-server:/project. The console is in the terminal, and -it lets you type into it. Without -it the server runs the same, and docker logs shows its console. Connect from the game with connect 127.0.0.1:27015.

While you work

npx amxts dev --docker

dev --docker is dev for this server. It builds the plugins for Linux into dist/ and again on every save; the running server sees the new files and reloads them by itself. Nothing is copied anywhere, and AMXTS_SERVER is not used. The server's answer shows up under the build:

✔ 14:02:11 plugins/my-plugin.ts changed: rebuilt my-plugin into dist (4.2s)
  | [amxts] my-plugin.aot changed on disk
  | [amxts] reloading
  | [amxts] loaded my-plugin.aot

The command finds the server by its mount: a running container with this project at /project. When there is none, it says so and shows the docker run line to start one. It never starts or stops a server itself.

A plugin added to the project goes into plugins.ini with the build and loads with amxts_reload in the server's console, or with the next map.

What it takes from the project

At every start the server takes these from /project, whichever exist:

from the projecton the server
dist/the plugins, and plugins.ini as the list of what runs
configs/over addons/amxmodx/configs/ - configs/myplugin/settings.ini, configs/users.ini
data/over addons/amxmodx/data/ - data/lang/myplugin.txt
maps/, models/, sound/, sprites/, gfx/, overviews/, resource/over the game folder's own
addons/over the game folder's addons/ - an AMX Mod X module, a Pawn plugin
motd.txtthe message of the day; without it, a player sees none

The plugins are read from dist/ where they are, so a new build reaches the running server at once. Everything else is copied into the server when it starts: a change to a config, a sound or a map reaches it with a restart, docker restart and the container's name. What the server writes - a config a plugin saves, a log - stays in the container.

Modules and Pawn plugins

The server has AMX Mod X's own modules and ReAPI. A module it does not have comes with the project: the Linux build (<name>_amxx_i386.so) in addons/amxmodx/modules/, and its name in configs/modules.ini:

my-server/
├── addons/amxmodx/modules/resemiclip_amxx_i386.so
└── configs/modules.ini          resemiclip

A Pawn plugin goes into addons/amxmodx/plugins/, and its name into configs/plugins.ini. A project's modules.ini and plugins.ini take the place of the server's; reapi and amxts_amxx are added back at the end of modules.ini, as the server needs them.

A plugin that calls a native of a module the server does not have gets an error on the call, and the console names the native:

[amxts] resemiclip_take_control was called, and it is not on this server: the module or plugin that provides it is not loaded

Without a project the server runs the example plugin it carries, hello.ts, which it compiles itself on the first start.

Built for Linux
A plugin built for a Windows server does not load on this one: build with --os linux, or put AMXTS_SERVER_OS=linux in the project's .env (the server's system). dev --docker always builds for Linux.

Settings

variabledefaultwhat
MAPde_dust2the first map
MAXPLAYERS16the slots
PORT27015the port the server listens on; publish the same one: -p 27016:27016/udp -e PORT=27016
RCON_PASSWORDrandomthe rcon password; when it is not set, a random one is printed at start
SERVER_NAMEamxts serverthe name in the server browser
SV_LAN11 for a server on your machine or LAN, 0 for one on the internet

They are passed with -e:

docker run --rm -it -p 27015:27015/udp -v "${PWD}:/project" -e MAP=cs_office -e MAXPLAYERS=32 ghcr.io/amxts/server

Anything after the image's name goes to the end of the server's command line:

docker run --rm -it -p 27015:27015/udp -v "${PWD}:/project" ghcr.io/amxts/server +mp_timelimit 0 +sv_cheats 1

To join from another machine on your network, connect to this machine's address and the published port: connect 192.168.1.20:27015.

In the background

docker run -dit --name myserver -p 27015:27015/udp -v "${PWD}:/project" ghcr.io/amxts/server
docker logs -f myserver     # the console
docker attach myserver      # the console to type into; Ctrl-P Ctrl-Q leaves it running
docker restart myserver     # start again, with the project's files copied anew
docker rm -f myserver       # stop and remove it