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/:id | JSON {"enabled": true} или {"enabled": false} |
QMServer Cloud
id (PATCH) | Ключ в БД | Описание |
|---|---|---|
qmbilling | module_qmbilling | Биллинг и подписки (/api/v1/modules/qmbilling/…). Нельзя включить без включённой интеграции Removed auth stack; при выключении интеграции Removed auth stack модуль QMBilling выключается автоматически. |
dedicated | module_dedicated | Выделенные хосты и агент QMClient |
minecraft | module_game_minecraft | Профили Minecraft и связанные API |
counter_strike_16 | module_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) | Ключ в БД | Описание |
|---|---|---|
dedicated | module_dedicated | Выделенные хосты и агент QMClient |
minecraft | module_game_minecraft | Профили Minecraft и связанные API |
counter_strike_16 | module_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/:id | JSON {"enabled": true} или {"enabled": false} |
Общие для Cloud и Free: qmlauncher → integration_qmlauncher, qmweb → integration_qmweb.
Только QMServer Cloud: legacy-auth → integration_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 | /health | Health 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/callback | OAuth 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-key | POST — новый API-ключ для модов |
/settings/qmlauncher-msa-client-id | Client 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-config | JSON для лаунчера до синхронизации |
У профиля могут быть поля 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_REDIRECT | Ely.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.