Перейти к основному содержимому
Версия: 1.0.2

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

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

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

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

Состав модулей и интеграций зависит от сборки (QMServerCloud и QMServerFree отличаются).

Модули

МетодПутьОписание
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 не обслуживает соответствующую интеграцию.

Базовый путь

Все перечисленные ниже маршруты (кроме /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 для Free, .../qmserver для 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: Free.github/workflows/build-qmserver-image.yml в корне монорепозитория; Cloud.github/workflows/build-qmserver-image.yml в репозитории QMServerCloud (корень того Git remote). У сервиса 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 в каталоге репозитория Cloud/Free.
Вручнуюmake build-release → один статический исполняемый файл под x86_64; на сервере QMSERVER_DATA_PATH (например /opt/qmserver/data).

Скрипт install.sh (только QMServer Cloud)

Для отдельного сервера под Linux x86_64 без сборки из исходников в репозитории mindevis/QMServerCloud есть install.sh (см. также сырой URL для curl):

РежимЧто делает
--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/QMServerCloud/main/install.sh | sudo bash -s -- --native
curl -fsSL https://raw.githubusercontent.com/mindevis/QMServerCloud/main/install.sh | bash -s -- --docker

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

Скрипт install.sh (QMServer Free)

Аналогичный сценарий в публичном репозитории mindevis/QMServerFree (raw): --native / --docker, образ по умолчанию ghcr.io/mindevis/qmserver-free:latest, каталог Compose по умолчанию ~/qmserver-free. Переменные QMSERVER_GITHUB_REPO, QMSERVER_GHCR_IMAGE, DOCKER_INSTALL_DIR — как у Cloud, но с дефолтами под Free.

curl -fsSL https://raw.githubusercontent.com/mindevis/QMServerFree/main/install.sh | sudo bash -s -- --native
curl -fsSL https://raw.githubusercontent.com/mindevis/QMServerFree/main/install.sh | bash -s -- --docker

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

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

# Монорепозиторий: только qmserver из QMServerFree (docker compose)
make run-qmserver

# Локальная отладка в каталоге репозитория
cd QMServerCloud && go run . --server
# или
cd QMServerFree && 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 задаётся интеграцией, не этой переменной.
ELY_CLIENT_ID, ELY_CLIENT_SECRET, ELY_REDIRECT_URI, ELY_FRONTEND_REDIRECTEly.by OAuth

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

Репозитории

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

В монорепозитории-песочнице оба каталога могут лежать рядом; в отдельных Git remote политика видимости такая же. Краткие README в проектах ведут в QMDocs.