This guide explains how to deploy a Quake Live dedicated server using Docker. This method avoids the manual installation of 32-bit Linux dependencies and simplifies file management. The setup includes minqlx admin plugins, Steam Workshop downloads and QLStats integration.

We use a pre-configured Docker image maintained by jaysson. The example below configures a Team Deathmatch (TDM) server using the popular House of Quake (HoQ) competitive presets.

Step 1: VPS Hardware Requirements

Rent a Virtual Private Server (VPS) from a provider such as Hetzner, Selectel or DigitalOcean. The minimum specifications are:
  • CPU: 2 vCPUs. The Quake Live server process (qzeroded) is single-threaded. One core handles game physics and tickrate, while the second core manages the OS and Docker processes.
  • RAM: 2 GB RAM. A fully loaded 16-slot server with Python minqlx plugins and Redis consumes approximately 512 MB of RAM. The container is capped at 1 GB RAM via the compose file.
  • OS: Ubuntu 22.04 LTS or Ubuntu 24.04 LTS (minimal installation).
  • Location: Choose a data center closest to your player base for optimal ping.

Step 2: Preparing the Server Environment

Connect to your VPS via SSH as root. Update the system, install Docker and create a working directory for the configuration files:
Code:
# Update the system apt update && apt upgrade -y # Install Docker and Docker Compose apt install docker.io docker-compose-v2 -y # Create a project folder and navigate into it mkdir ~/qlserver && cd ~/qlserver
If your VPS has a firewall enabled, open the required Quake Live ports:
Code:
ufw allow 27960/udp ufw allow 27960/tcp
Step 3: Installing Custom Gametype Scripts (HoQ Factories)

Instead of relying entirely on the Steam Workshop on the server side for gametype files, we will load the HoQ `.factories` files directly. This allows for quick edits and full control over match rules.

To get the necessary files, first subscribe to the House of Quake Workshop item on your local PC. Once subscribed, Steam will automatically download the contents to your local Workshop directory. You can find the file within your Steam library at this exact path:
Code:
...\steamapps\workshop\content\282440\547440642\baseq3\scripts\
First, create a `scripts` folder inside your server directory on the VPS:
Code:
mkdir ~/qlserver/scripts
Next, upload the houseofquake.factories file from your local Steam Workshop folder directly into the `~/qlserver/scripts` directory on your VPS.

💡 Pro Tip: We highly recommend using an SSH client like Termius. It includes a built-in SFTP file manager, allowing you to simply drag and drop your `.factories` files directly into the remote folder. You can also use Termius to easily edit the `docker-compose.yaml` file in the next step visually, without relying on console text editors.

To ensure your server uses competitive weapon settings, we need to load the standard NoHMG fix (ID: 543197560). Instead of downloading it manually, Quake Live can fetch it directly from Steam on startup if we provide a Workshop list file.

Run this command to create the file and add the mod ID:
Code:
echo "543197560" > workshop.txt
Step 4: The Docker Compose Configuration

Create the main configuration file:
Code:
nano docker-compose.yaml
Paste the following configuration. All server settings are driven by environment variables:
Code:
services: qlserver: container_name: qlserver image: registry.gitlab.com/jayssonq/qlserver:latest restart: always environment: CLOUDCONTAINER: false FQDN: "none.if.no.container" QLSVCFG: | set quakelive_host "0.0.0.0" set net_port "27960" // ZeroMQ / QLStats Setup set zmq_stats_enable "1" set zmq_stats_ip "0.0.0.0" set zmq_stats_port "27960" set zmq_stats_password "CHANGE_THIS_ZMQ_PASSWORD" // Server Info set sv_hostname "My Awesome QL Server" set sv_tags "custom,tdm" set sv_mappoolfile "mappool.txt" set sv_maxclients "16" set g_password "tdm" set sv_servertype "2" set sv_master "1" set sv_fps "40" // Admin Setup (MinQLX) set qlx_owner "YOUR_STEAM64_ID" set qlx_plugins "plugin_manager, essentials, balance, ban, motd, names, branding, elocheck, player_info, sets" set qlx_serverbrandbottomfield "My Awesome QL Server" set qlx_countdownMessage "Prepare to Fight!" set qlx_elocheckpermission "1" set qlx_elocheckreplychannel "public" set qlx_pinfo_display_auto "1" set qlx_pinfo_show_deactivated "1" set qlx_sets_maximum "5" // Startup Map and Mode set serverstartup "map bloodrun hoq_tdm" MAPPOOL: | bloodrun|hoq_tdm campgrounds|hoq_tdm devilish|hoq_tdm hiddenfortress|hoq_tdm almostlost|hoq_tdm ports: - "27960:27960/udp" - "27960:27960/tcp" volumes: - ./scripts:/home/steam/qlds/baseq3/scripts - ./workshop.txt:/home/steam/qlds/baseq3/workshop.txt mem_limit: 1g

Important: Replace CHANGE_THIS_ZMQ_PASSWORD with a secure password and YOUR_STEAM64_ID with your 17-digit Steam community ID. Press Ctrl+O, Enter to save and Ctrl+X to exit.

Step 5: Launching the Server

Start the container. Docker will automatically pull the image from GitLab, download SteamCMD, the server files, Workshop mods and minqlx dependencies:
Code:
docker compose up -d
Maintenance Commands
  • Start/Apply config changes:
    Code:
    docker compose up -d
  • Stop the server:
    Code:
    docker compose down
  • Restart the server:
    Code:
    docker compose restart
  • View console logs (Press Ctrl+C to exit):
    Code:
    docker compose logs -f
Note: Steam throttles anonymous downloads. If the deployment fails with "ERROR! Failed to install app '349090'", run the start command again.

Step 6: Connecting and QLStats Integration
  1. Launch Quake Live, open the game console (~) and connect via your VPS IP address:
    Code:
    /connect YOUR_SERVER_IP:27960; password tdm
  2. Link your server to QLStats: Go to qlstats.net, log in via Steam and navigate to Add Server. Enter your VPS IP, the ZMQ Port (27960) and the ZMQ password defined in the configuration.
  3. Complete one match. The server sends its custom name to QLStats with the final Match Report. The custom server name will replace the "None" placeholder on the website after the post-match scoreboard appears.
Note: New servers may take time to appear in the global tracked list. The QLStats database synchronizes new server additions daily.

Bonus: Running Multiple Servers on One Machine

To host multiple servers (for example, one for TDM and one for Duel) on the same machine, you can define multiple services within the same docker-compose.yaml file. You must assign a unique container name, a unique port (both for net_port and zmq_stats_port), and lower the memory limits to prevent the OS from killing the processes.

Here is an example of a dual-server configuration:
Code:
services: qlserver-tdm: container_name: qlserver-tdm image: registry.gitlab.com/jayssonq/qlserver:latest restart: always environment: CLOUDCONTAINER: false FQDN: "none.if.no.container" QLSVCFG: | set quakelive_host "0.0.0.0" set net_port "27960" set zmq_stats_enable "1" set zmq_stats_ip "0.0.0.0" set zmq_stats_port "27960" set zmq_stats_password "CHANGE_THIS_ZMQ_PASSWORD" set sv_hostname "My Awesome TDM Server" set sv_maxclients "16" set sv_fps "40" set serverstartup "map bloodrun hoq_tdm" // ... add your other standard settings here ... ports: - "27960:27960/udp" - "27960:27960/tcp" volumes: - ./scripts:/home/steam/qlds/baseq3/scripts - ./workshop.txt:/home/steam/qlds/baseq3/workshop.txt mem_limit: 512m qlserver-duel: container_name: qlserver-duel image: registry.gitlab.com/jayssonq/qlserver:latest restart: always environment: CLOUDCONTAINER: false FQDN: "none.if.no.container" QLSVCFG: | set quakelive_host "0.0.0.0" set net_port "27961" set zmq_stats_enable "1" set zmq_stats_ip "0.0.0.0" set zmq_stats_port "27961" set zmq_stats_password "CHANGE_THIS_ZMQ_PASSWORD" set sv_hostname "My Awesome Duel Server" set sv_maxclients "16" set sv_fps "40" set serverstartup "map bloodrun duel" // ... add your other standard settings here ... ports: - "27961:27961/udp" - "27961:27961/tcp" volumes: - ./scripts:/home/steam/qlds/baseq3/scripts - ./workshop.txt:/home/steam/qlds/baseq3/workshop.txt mem_limit: 512m

Managing Multiple Servers

When you have multiple services in one file, standard Compose commands apply to all of them at once. However, you can manage them individually by specifying the service name:
  • Start all servers:
    Code:
    docker compose up -d
  • Restart only the Duel server:
    Code:
    docker compose restart qlserver-duel
  • Stop only the TDM server:
    Code:
    docker compose stop qlserver-tdm
  • View live logs for the Duel server:
    Code:
    docker compose logs -f qlserver-duel
⚠️ Performance Notice: Each active game instance requires 1 dedicated CPU core. Running two populated 16-slot servers concurrently on a 2 vCPU machine will cause severe physics and tickrate degradation. Upgrade to a minimum of 4 vCPUs for multiple populated instances.