Skip to main content
Version: Next

QMServer

Бэкенд на Go (Gin) и MySQL (GORM). Единая точка для QMLauncher, QMAdmin и QMWeb: аутентификация, профили серверов, моды, новости, скины, настройки лаунчера и облачных пользователей.

Платформа: официально только Linux x86_64 (GOOS=linux, GOARCH=amd64). Docker-образы и цель make build-release рассчитаны на amd64; ARM / AArch64 не поддерживаются.

Документация API

На развёрнутом сервере:

  • Swagger UI: /swagger/index.html (редирект с /docs)
  • ReDoc: /redoc
  • OpenAPI: /swagger/doc.json

В репозитории QMServer: каталог docs/ (swagger.yaml, swagger.json). Генерация: make swagger или swag init -g docs.go -o docs.

Модули и клиентские интеграции

Часть API управляется флагами в таблице settings. При первом запуске QMServer создаёт записи со значением 0 (выключено); пустое значение для этих ключей нормализуется в «выкл». Управление из QMAdmin: разделы «Модули» и «Интеграции».

Состав модулей и интеграций зависит от варианта сборки (публичная без Go-тега cloud и Cloud с -tags cloud — один и тот же Git-репозиторий, см. BUILD.md в QMServer).

Модули

МетодПутьОписание
GET/admin/modulesСписок модулей и флагов
PATCH/admin/modules/:idJSON {"enabled": true} или {"enabled": false}

QMServer Cloud

id (PATCH)Ключ в БДОписание
qmbillingmodule_qmbillingБиллинг и подписки (/api/v1/modules/qmbilling/…). Нельзя включить без включённой интеграции Removed auth stack; при выключении интеграции Removed auth stack модуль QMBilling выключается автоматически.
dedicatedmodule_dedicatedВыделенные хосты и агент QMClient
minecraftmodule_game_minecraftПрофили Minecraft и связанные API
counter_strike_16module_game_counter_strike_16Профили CS 1.6 / HLDS

В Cloud нет модуля legacy-auth: встроенный стек Removed auth stack (OAuth, JWT для входа «через Removed auth stack») управляется интеграцией legacy-auth (см. ниже).

QMServer Free

id (PATCH)Ключ в БДОписание
dedicatedmodule_dedicatedВыделенные хосты и агент QMClient
minecraftmodule_game_minecraftПрофили Minecraft и связанные API
counter_strike_16module_game_counter_strike_16Профили CS 1.6 / HLDS

В Free нет встроенного Removed auth stack и нет модуля QMBilling (соответствующие маршруты отсутствуют). Доверие к JWT внешнего IdP при необходимости настраивается через окружение (LEGACY_ENV_ и связанные параметры) — без встроенного OAuth Removed auth stack на стороне QMServer.

При выключенном модуле соответствующие маршруты отвечают 404 с полем detail (например, отключён модуль Minecraft или Dedicated).

Интеграции (QMLauncher, QMWeb; в Cloud — ещё Removed auth stack)

МетодПутьОписание
GET/admin/integrationsСписок интеграций
PATCH/admin/integrations/:idJSON {"enabled": true} или {"enabled": false}

Общие для Cloud и Free: qmlauncherintegration_qmlauncher, qmwebintegration_qmweb.

Только QMServer Cloud: legacy-authintegration_cloud_auth — встроенный OAuth/JWKS Removed auth stack на стороне QMServer (маршруты вида /api/v1/modules/legacy-auth/… для входа и выдачи токенов). В Free этой интеграции нет.

Поведение:

  • GET /news: доступен, если включена хотя бы одна интеграция (QMLauncher или QMWeb). Иначе 404.
  • GET /servers без прав администратора: если обе интеграции выключены — ответ с пустым server_profiles. Администраторы получают полный список для управления.
  • Интеграция QMWeb: при выключении недоступны публичные GET /settings/referral и GET /settings/inventory-sync (404), а также приём инвентаря с игрового сервера POST /inventory (QXSync): для него дополнительно должен быть включён модуль Minecraft (иначе 404 по отключённому модулю раньше в цепочке).
  • Интеграция QMLauncher: при выключении недоступны, в частности: игровые аккаунты, скины и прокси, публичный GET /settings/skin-providers, GET /settings/qmlauncher-msa-client-id, GET /servers/:id/mod-config, маршруты /launcher/*, а в сборке Cloud — POST /check/server, GET /check/data/..., GET /download/... (404 с detail).

Админские PATCH настроек (скины, CurseForge, MSA, inventory-sync и т.д.) не блокируются отключёнными интеграциями: можно настроить сервис до включения клиентов.

Клиенты QMLauncher и QMWeb при 404 и тексте detail про отключённую интеграцию показывают сообщение, что выбранный QMServer не обслуживает соответствующую интеграцию.

Removed auth stack OAuth2 PKCE (только QMServer Cloud)

Встроенный модуль Removed auth stack поддерживает OAuth2 Authorization Code с PKCE для веб-клиентов (QMAdmin, QMWeb, QMDocs): обмен email/пароля Removed auth stack на одноразовый code и редирект на redirect_uri клиента, затем обмен code + code_verifier на JWT (access_token тот же, что у POST /modules/legacy-auth/auth/login).

На стороне QMServer должны быть заданы:

  • LEGACY_ENV_ — через запятую список точных URL redirect_uri (например https://web.qx-dev.ru/login для QMWeb, https://admin.qx-dev.ru/ для QMAdmin, https://qm.qx-dev.ru/login/callback для QMDocs — как в сборке фронтов).
  • LEGACY_ENV_ — опционально; по умолчанию допускаются идентификаторы вроде qmadmin, qmweb, qmdocs.
МетодПуть (под /api/v1)Описание
POST/modules/legacy-auth/oauth/pkce/authorizeТело JSON: email, password, client_id, redirect_uri, state, code_challenge, code_challenge_method: "S256"redirect_url с параметрами code и state
POST/modules/legacy-auth/oauth/tokengrant_type=authorization_code, code, redirect_uri, client_id, code_verifieraccess_token

Без LEGACY_ENV_ эндпоинты отвечают 404 с пояснением в detail.

Подробнее о входе в UI: QMAdmin, QMWeb.

Базовый путь

Все перечисленные ниже маршруты (кроме /health и /swagger) находятся под префиксом /api/v1.

Система

МетодПутьОписание
GET/healthHealth check
GET/api/v1/statusКраткий статус API

Аутентификация (JWT)

Используется QMAdmin и QMWeb. Заголовок: Authorization: Bearer <token>.

МетодПутьОписание
POST/auth/loginВход
POST/auth/registerРегистрация
GET/auth/meТекущий пользователь
PATCH/auth/profileПрофиль
GET/auth/ely/oauth-urlСтарт привязки Ely.by
GET/auth/ely/callbackOAuth callback (без JWT)
DELETE/auth/ely/linkОтвязать Ely.by

Администрирование: пользователи облака

Требуются JWT и флаг администратора.

МетодПутьОписание
GET/admin/usersСписок пользователей
PATCH/admin/users/:idИзменение пользователя (в т.ч. премиум)

Выделенные хосты и агент QMClient

Реестр машин (VPS / железо) для учёта и сканирования каталогов агентом QMClient. Требуются JWT, админ и включённый модуль Dedicated (см. Модули и клиентские интеграции).

МетодПутьОписание
GET/admin/dedicated-serversСписок
POST/admin/dedicated-serversСоздание; в ответе — dedicated_server и одноразовый agent_enrollment_envelope (Base64, RSA-OAEP по публичному ключу из сборки QMClient); открытый токен в JSON не отдаётся
PATCH/admin/dedicated-servers/:idОбновление полей (IP, имя, ОС, work_dir, локация, провайдер); токен агента не меняется
DELETE/admin/dedicated-servers/:idУдаление; у связанных игровых профилей сбрасываются dedicated_server_id и data_subdir
GET/admin/dedicated-servers/:id/discoveryПоследний отчёт скана (папки, тип, порт, сопоставление с профилями)
POST/admin/dedicated-servers/:id/agent-tokenНовый токен агента (старый перестаёт действовать); в ответе — новый agent_enrollment_envelope

Публичный ключ для конверта вшит в QMServer (routes/embedded/qmclient_enrollment_public.pem) или задаётся переменной QMCLIENT_ENROLLMENT_PUBLIC_KEY_PEM; он должен соответствовать приватному ключу в сборке QMClient (enrollment/keys/enrollment_private.pem).

Агент вызывает API не с JWT админа, а с заголовком Authorization: Bearer и проверяемым токеном (после установки — расшифрованным на стороне агента из конверта; в API по-прежнему формат qm_...):

МетодПутьОписание
GET/agent/dedicated-servers/:idПроверка токена; ответ: work_dir, имя хоста
POST/agent/dedicated-servers/:id/scanТело JSON { "entries": [ { "subdir", "game_type", "port", "version_hint" } ] } — сохранение и слияние с профилями по IP/порту
GET/agent/dedicated-servers/:id/supervisorОчередь задач для агента: объекты с id, server_id, action (start / stop / restart / install_cs16 / provision_mc / remove_instance), data_subdir, port, при необходимости remove_steamcmd (для remove_instance). Плюс список console_pull для выгрузки хвоста лога Minecraft (пока админ опрашивает консоль). Задачи при выдаче переводятся в статус processing
POST/agent/dedicated-servers/:id/supervisor/tasks/:task_id/resultТело { "ok": bool, "message": string } — завершение задачи (done / failed)
POST/agent/dedicated-servers/:id/supervisor/consoleТело { "server_id", "content" } — фрагмент лога в буфер для GET …/minecraft/console

Задачи хранятся в таблице agent_supervisor_tasks (связь с профилем сервера и dedicated_server_id; для remove_instance путь инстанса дублируется в instance_subdir, т.к. строка профиля может быть уже удалена). Буфер консоли для опроса из админки — в памяти процесса QMServer.

Админ (JWT): управление процессом Minecraft только для профилей с game_kind: minecraft, привязанных к выделенному хосту и с заполненным data_subdir:

МетодПутьОписание
POST/admin/servers/:id/minecraft/processТело { "action": "start" | "stop" | "restart" } — постановка задачи в очередь для агента этого хоста
GET/admin/servers/:id/minecraft/consoleПоследний сохранённый текст лога; продлевает «интерес» к выгрузке лога агентом

Игровые аккаунты (Minecraft)

Требуются модуль Minecraft и интеграция QMLauncher (и JWT там, где указано ниже).

МетодПутьОписание
GET/game-accountsСписок
POST/game-accountsСоздание
POST/game-accounts/syncСинхронизация
GET/game-accounts/:idКарточка
PATCH/game-accounts/:idОбновление
DELETE/game-accounts/:idУдаление
PATCH/game-accounts/:id/linkПривязка Mojang/Microsoft
GET/game-accounts/:id/inventoryИнвентарь в облаке

Инвентарь с сервера (мод)

Отдельная авторизация API-ключом — см. раздел Синхронизация инвентаря. В Free и в Cloud работает только при включённом модуле Minecraft и интеграции QMWeb.

МетодПутьОписание
POST/inventoryПриём данных от игрового сервера (QXSync); требуются модуль Minecraft, QMWeb, ключ API — иначе 404/ошибки авторизации

Скины и косметика

МетодПутьОписание
GET/skins/proxyПрокси URL скина (обход CORS)
GET/skinsСписок
GET/skins/:usernameВыдача PNG
POST/skins/:usernameЗагрузка (JWT)
POST/capes/:usernameЗагрузка плаща
POST/elytras/:usernameЗагрузка элитры

Настройки (публичные GET / админские PATCH)

ПутьНазначение
/settings/skin-providersПровайдеры скинов
/settings/referralРеферальная программа
/settings/inventory-syncВкл/выкл и параметры sync инвентаря
/settings/curseforge-api-keyКлюч CurseForge для каталога модов
/settings/inventory-sync/generate-keyPOST — новый API-ключ для модов
/settings/qmlauncher-msa-client-idClient ID Microsoft для QMLauncher

QMLauncher (вспомогательные API)

МетодПутьОписание
GET/launcher/create-instance/minecraft-versionsСписок версий MC
GET/launcher/create-instance/loader-versionsВерсии Forge/Fabric/…
GET/launcher/curseforge-api-keyКлюч CurseForge для премиум/админа (JWT)

Новости

МетодПутьОписание
GET/newsПубличная лента
POST / PATCH / DELETE/news, /news/:idУправление (админ)

Профили Minecraft-серверов

МетодПутьОписание
GET/serversСписок профилей + players / max_players (Server List Ping); админ видит отключённые; при наличии выделенного хоста и data_subdir — поля agent_setup_status / agent_setup_detail (состояние последней задачи установки агентом). Публичный список (не админ): пустой server_profiles, если выключены обе интеграции QMLauncher и QMWeb
PATCH/servers/:idВключение/выключение профиля
DELETE/servers/:idУдаление профиля. Тело JSON (опционально): remove_from_host — снять данные на машине; для профиля на dedicated ставится задача remove_instance (агент удаляет каталог инстанса). Для не-dedicated при true удаляется каталог профиля под корнем данных (QMSERVER_DATA_PATH, в Docker по умолчанию /app); при false — только запись в БД. Для профилей не Minecraft дополнительно remove_steamcmd — удалить общий SteamCMD на хосте (через агент) или под тем же корнем данных на стороне QMServer.
POST/admin/serversСоздание профиля на выделенном хосте: dedicated_server_id, data_subdir, имя, порт, version, опционально game_kind: minecraft (по умолчанию) или counter_strike_16; загрузчик модов только для Minecraft
GET/servers/:id/mod-configJSON для лаунчера до синхронизации

У профиля могут быть поля dedicated_server_id и data_subdir (папка относительно work_dir на хосте). Такие профили не требуют полного набора локальных data-каталогов на стороне QMServer — игровые файлы живут на выделенной машине. UUID профиля и этот каталог данных всегда соответствуют одному игровому экземпляру (одна запись в БД — одна директория под work_dir выделенного хоста).

Управление файлами на стороне облака (админ, JWT):

  • /servers/:id/mods, mod-presets, resourcepacks, shaderpacks — списки, метаданные, загрузка/удаление, парсинг зависимостей.

Только QMServer Cloud / Premium

Если APP_NAME содержит cloud или premium:

МетодПутьОписание
POST/check/serverПроверка регистрации сервера
GET/check/data/:server_idМанифест файлов data.json
GET/download/:server_id/*file_pathОтдача файлов модпака и скинов

Запуск

Поставляется один исполняемый файл qmserver: интерактивный режим по умолчанию, для продакшена — qmserver --server (HTTP + Gin).

СпособДетали
DockerГотовые образы GitHub Container Registry — пакет ghcr.io/<владелец>/qmserver: ...:free-latest (публичная сборка) и ...:latest (Cloud), linux/amd64; в контейнере WORKDIR=/app, по умолчанию корень данных задаётся через QMSERVER_DATA_PATH; для продакшена API — ./qmserver --server. В корне монорепозитория docker-compose.yaml и docker-compose.cloud.yaml тянут образы по GHCR_OWNER (и опционально IMAGE_TAG) — см. .env.example; CI: образы собираются из репозитория QMServer (пакет GHCR qmserver; workflows build-qmserver-image, build-qmserver-public-image). У сервиса qmserver задано platform: linux/amd64. При приватном пакете на хосте нужен docker login ghcr.io.
systemdЮнит qmserver: исполняемый файл /opt/qmserver/qmserver, конфиг /opt/qmserver/qmserver.conf, данные /opt/qmserver/data, логи /var/log/qmserver.log (StandardOutput/StandardError → append), симлинк /usr/local/bin/qmserver; make install-systemd в каталоге репозитория QMServer.
Вручнуюmake build-release → один статический исполняемый файл под x86_64; на сервере QMSERVER_DATA_PATH (например /opt/qmserver/data).

Скрипт install.sh (образ Cloud)

Для отдельного сервера под Linux x86_64 без сборки из исходников в репозитории mindevis/QMServer есть install.sh, ориентированный на Cloud-бинарник и образ ghcr.io/.../qmserver (см. сырой URL):

РежимЧто делает
--native (от root)Берёт архив qmserver-*-linux-amd64*.tar.gz из GitHub Releases, ставит бинарник в /opt/qmserver, подтягивает qmserver.service и пример qmserver.conf, включает systemd.
--dockerПроверяет curl, Docker, Compose (docker compose или docker-compose), тянет ghcr.io/mindevis/qmserver:latest, создаёт каталог с .env и docker-compose.yml (по умолчанию ~/qmserver-cloud, см. DOCKER_INSTALL_DIR).
curl -fsSL https://raw.githubusercontent.com/mindevis/QMServer/main/install.sh | sudo bash -s -- --native
curl -fsSL https://raw.githubusercontent.com/mindevis/QMServer/main/install.sh | bash -s -- --docker

Опционально: QMSERVER_RELEASE_TAG (конкретный тег релиза), GITHUB_TOKEN / GH_TOKEN если репозиторий или пакеты приватные, QMSERVER_GHCR_IMAGE — другой образ для Docker. Справка: install.sh --help.

Публичная сборка (free-latest)

Публичная сборка публикуется как ghcr.io/<owner>/qmserver:free-latest (тот же пакет GHCR, что и Cloud; сборка без -tags cloud, см. BUILD.md). Поднять можно через docker-compose.yaml в корне qm-project (make run-qmserver) или вручную. Отдельного install.sh под старый репозиторий QMServerFree больше нет: для нативной установки публичной сборки соберите make build-release в QMServer или используйте только Docker/GHCR.

Каталог данных на диске: QMSERVER_DATA_PATH (в Docker по умолчанию /app, в unit systemd по умолчанию /opt/qmserver/data). Скины по умолчанию: <корень>/skins, либо SKINS_STORAGE_DIR.

# Монорепозиторий: облачный стек (образ qmserver)
make run-qmserver-cloud

# Монорепозиторий: публичная сборка (тег free-latest)
make run-qmserver

# Локальная отладка в каталоге субмодуля QMServer
cd QMServer && go run -tags cloud . --server # Cloud
cd QMServer && go run . --server # публичная сборка

Переменные окружения (основные)

ПеременнаяОписание
PORTПорт HTTP (по умолчанию 8080)
DB_DSNСтрока подключения MySQL
QMSERVER_DATA_PATHКорень для .servers/, манифестов и каталога скинов по умолчанию (Docker — /app, native systemd — /opt/qmserver/data)
APP_NAMEИмя приложения; для premium-эндпоинтов — должно содержать cloud или premium
LEGACY_ENV_(В основном QMServer Free) URL JWKS внешнего IdP Removed auth stack для проверки Bearer JWT; если пусто, отдельный путь авторизации по таким токенам не активируется. В Cloud встроенный Removed auth stack задаётся интеграцией, не этой переменной.
LEGACY_ENV_(Cloud, PKCE) Список разрешённых redirect_uri для OAuth2 (см. Removed auth stack OAuth2 PKCE).
LEGACY_ENV_(Cloud, опционально) Разрешённые client_id для PKCE; по умолчанию включает клиентов вроде qmadmin / qmweb / qmdocs.
ELY_CLIENT_ID, ELY_CLIENT_SECRET, ELY_REDIRECT_URI, ELY_FRONTEND_REDIRECTEly.by OAuth

Подробнее: разделы выше; шаблон переменных — deploy/systemd/qmserver.conf.example в репозитории QMServer (systemd: /opt/qmserver/qmserver.conf; локально можно скопировать в .env).

Репозиторий и сборки

Один репозиторий mindevis/QMServer:

  • Публичная сборка (без Go-тега cloud): API без маршрутов check / download, без облачного манифеста данных, без встроенных модулей Removed auth stack и QMBilling (см. модули и интеграции).
  • Cloud-сборка (go build -tags cloud, образ qmserver): полная облачная / premium конфигурация (APP_NAME с cloud или premium), Removed auth stack как интеграция, QMBilling как модуль.

Репозиторий может быть публичным или приватным на GitHub — от этого зависит только доступ к git clone и к приватным пакетам GHCR. Подробности по флагам сборки — BUILD.md и README.md в QMServer.