Skip to content

Install QLSM

There are three ways to get QLSM running, from easiest to most hands-on.

Option 1 — Vultr Startup Script (No Terminal Required)

The easiest path. Requires a Vultr account.

  1. Log in to Vultr and go to Manage → Startup Scripts.
  2. Create a new startup script and paste the Vultr QLSM startup script.
  3. Deploy a new VM. Under the Configure Software tab, select that startup script from the drop-down menu. Choose Debian 12 as the OS — Ubuntu is supported too, but 99k LAN rate is not compatible with it. For the plan, vc2-1c-1gb ($5/month) works fine.
  4. Wait approximately 10 minutes after the VM boots.
  5. QLSM will be running at the VM's IP address on port 80.

You never open a terminal. The startup script handles everything.

Custom domain (optional): If you have a domain pointing to the VM's IP, find this line in the startup script before saving it:

export SITE_ADDRESS=":80"

Replace :80 with your domain:

export SITE_ADDRESS="qlsm.custom-domain.com"

QLSM will obtain a free HTTPS certificate automatically via Let's Encrypt. Your domain's A record must point to the VM's IP before it boots.

Vultr API key (optional): If you want to provision additional Vultr-hosted QLDS game servers from within the UI, create a Vultr API key, then find this line in the startup script and uncomment it before saving it:

# export VULTR_API_KEY=""

Paste your key between the quotes before saving the script.

Option 2 — One-Line Install Script

For any Debian 12 machine where you have SSH access:

curl -fsSL https://raw.githubusercontent.com/dngrtech/qlsm/main/qlsm-install.sh | bash

With a custom domain (enables automatic HTTPS via Caddy):

SITE_ADDRESS=qlsm.example.com bash <(curl -fsSL https://raw.githubusercontent.com/dngrtech/qlsm/main/qlsm-install.sh)

With Vultr provisioning enabled from the start:

VULTR_API_KEY=your_vultr_api_key bash <(curl -fsSL https://raw.githubusercontent.com/dngrtech/qlsm/main/qlsm-install.sh)

With both a custom domain and Vultr provisioning:

SITE_ADDRESS=qlsm.example.com VULTR_API_KEY=your_vultr_api_key bash <(curl -fsSL https://raw.githubusercontent.com/dngrtech/qlsm/main/qlsm-install.sh)

The script: 1. Creates ~/qlsm/ with the required directory structure 2. Downloads docker-compose.yml and Caddyfile 3. Generates a .env file with secure random secrets 4. Pulls the Docker image and starts all services

QLSM will be available at the server's IP (or your domain) when it finishes.

Option 3 — Docker Compose (Full Control)

Clone the repo and configure everything yourself:

git clone https://github.com/dngrtech/qlsm.git && cd qlsm
cp .env.example .env
# Edit .env — set SITE_ADDRESS, REDIS_PASSWORD, VULTR_API_KEY if using Vultr
docker compose up -d

First Login

Default credentials: admin / admin

You will be prompted to change your password on first login.

Configuration (.env)

All options are set via environment variables. When using the install script, a .env file is generated at ~/qlsm/.env. When using Docker Compose directly, copy .env.example to .env and edit it.

After editing .env, restart the stack:

cd ~/qlsm && docker compose up -d

Core

Variable Description Default
SITE_ADDRESS Domain name or :port. A bare domain enables automatic HTTPS via Let's Encrypt. Use :80 for HTTP-only. :80
SECRET_KEY Signs JWT tokens and session cookies. Auto-generated on first run and persisted to disk. auto-generated
DEFAULT_ADMIN_USER Username of the bootstrap admin account created on first run. admin
FLASK_ENV Runtime profile: production or development. production

Redis

Variable Description Default
REDIS_PASSWORD Password for the Redis task queue. Auto-generated by the installer. auto-generated
REDIS_URL Full Redis connection URI. Override when pointing at an external Redis instance. redis://redis:6379/0

Database

Variable Description Default
DATABASE_URL SQLAlchemy connection URI. Override to use an external database. sqlite:////app/data/qlds_ui.db

Authentication

Variable Description Default
JWT_EXPIRATION_HOURS How long a login session lasts before the user must re-authenticate. 24
FORCE_HTTPS Set to true to force HTTPS cookies when QLSM sits behind a TLS-terminating reverse proxy but SITE_ADDRESS is set to a port (e.g. :443). false
CORS_ORIGINS Comma-separated list of allowed CORS origins. Leave blank when the frontend and API are served from the same origin. (blank)

Logging

Variable Description Default
LOG_LEVEL Logging verbosity: DEBUG, INFO, WARNING, or ERROR. INFO
LOG_FORMAT Log output format: text (human-readable) or json (structured, useful for log aggregators). text
LOG_FILE Optional file path to write logs to. If unset, logs go to stdout/stderr. (blank)

Cloud Provisioning

Variable Description Default
VULTR_API_KEY Vultr API key. Required only if you want QLSM to provision game server VMs via the Vultr provider. (blank)

Self-Host Provider

Variable Description Default
QLSM_HOST_USER SSH username used when QLSM connects back to the host machine for self-hosted game servers. root
QLSM_HOST_IP Pre-fills the "Server address" field when adding a self-host entry in the UI. (blank)
QLSM_SELF_HOST_SSH_TARGET Override the auto-detected SSH management target for the self-host provider. Only needed in non-standard network setups. auto-detected

Grafana (optional logging profile)

Variable Description Default
GRAFANA_PASSWORD Grafana admin password. Only used when starting the stack with --profile logging. admin

Logging Stack (Optional)

QLSM ships an optional observability stack — Loki + Promtail + Grafana — for browsing and searching structured application logs. It is disabled by default and opt-in via a Docker Compose profile.

Components

Container Role
Loki Log aggregation and storage. Receives log streams and indexes them for querying.
Promtail Log collection agent. Reads container stdout/stderr (or systemd journal) and ships them to Loki.
Grafana Web UI for querying and visualising logs. Pre-configured with Loki as a data source.

Starting the Logging Stack

Add --profile logging to any docker compose command:

cd ~/qlsm
docker compose --profile logging up -d

Set the Grafana admin password before starting (or in .env):

GRAFANA_PASSWORD=yourpassword docker compose --profile logging up -d

Accessing Grafana

Grafana listens on port 3000 of the server. Because this port is typically not exposed to the internet, access it through a secure tunnel (VSCode port forwardingm Tailscale VPN, etc.) rather than opening it in a firewall.

Next Steps