Host a server

Run a CSJS server with Docker and add it to the community server list.

You need a separate approved secret for each server. Submit the operator email below; the secret is sent to that address after approval.

Approval required

Request a server secret

Submit the operator email. Every approved server receives its own credential.

1

Server secret

Requests remain pending until they are approved. Approval generates a csjs_… secret and sends it by email. The master stores only its hash.

The credential binds to the first published host and proxy port that uses it. It cannot be reused for a second endpoint.

2

Networking

Players need UDP 27015. Browsers need a WebSocket gateway. Because CSJS is served over HTTPS, the recommended public gateway is a domain with TLS on TCP 443, reverse-proxied to local TCP 27016.

Create an A/AAAA record such as cs.example.com pointing at the host, allow UDP 27015 and TCP 80/443 through its firewall, and keep the container's port 27016 bound to localhost.

3

Run the container

Replace the secret, hostname, and CSJS_PUBLISH_HOST. The image targets linux/amd64; Docker Desktop can emulate it on Apple Silicon.

docker volume create csjs-server-state

docker run -d \
  --name csjs-server \
  --restart unless-stopped \
  --platform linux/amd64 \
  -p 27015:27015/udp \
  -p 127.0.0.1:27016:27016/tcp \
  -v csjs-server-state:/state \
  -e CSJS_MASTER_ENABLED=true \
  -e CSJS_MASTER_URL="https://master.csjs.live" \
  -e CSJS_EVENT_CLIENT_SECRET="csjs_paste-the-secret-from-your-email" \
  -e CSJS_HOSTNAME="My CSJS Server" \
  -e CSJS_MAP=de_dust2 \
  -e CSJS_MAXPLAYERS=16 \
  -e CSJS_PUBLISH_HOST=cs.example.com \
  -e CSJS_PUBLISH_PORT=443 \
  -e CSJS_SECURE=true \
  lklacar/csjs-server:latest

The named volume preserves generated config and AMXX state across container replacement. Treat the secret as a password: use your platform's secret store where available, and do not commit it.

4

TLS proxy

Point a TLS reverse proxy at 127.0.0.1:27016. Minimal Caddy configuration:

cs.example.com {
  reverse_proxy 127.0.0.1:27016
}

DNS must resolve to the host, and ports 80/443 must be reachable for automatic certificate issuance. Other proxies must forward WebSocket upgrades and preserve /ws.

5

Verify

docker logs --tail 100 csjs-server
curl -fsS http://127.0.0.1:27016/healthz
curl -fsS https://cs.example.com/healthz

Heartbeats begin after the game server and gateway are ready. A reachable authenticated server appears in the server list as Community.

6

Troubleshooting

Heartbeat returns 401

Check the full emailed secret. A revoked secret, an unknown secret, or one already bound to a different host/port is rejected.

Health works, listing is absent

Check CSJS_MASTER_URL, container logs, public DNS, and whether the master can query the advertised native endpoint.

Listed, but Join fails

Verify the TLS certificate, /ws proxying, CSJS_SECURE=true, and the advertised host/port.

Need to move the server

The credential is endpoint-bound. Ask the administrator to revoke it, then submit a new request for the replacement endpoint.

docker pull lklacar/csjs-server:latest
docker rm -f csjs-server
# Run the launch command again; keep the same volume and endpoint.

Lost or exposed secrets cannot be recovered. Revoke the credential and request a new one. The server source and additional configuration are available on GitHub.