Развёртывание
Деплой через Makefile
# Первый раз: сгенерировать пароли
make generate-passwords
# Деплой всего стека (QMServer Cloud, QMAdmin, QMWeb, QMDocs)
make deploy
Синхронизация каталогов проекта на сервер в $(DEPLOY_PATH) (по умолчанию /opt/qmserver) выполняется через rsync с --delete: файлы и папки, которые вы удалили в репозитории, удаляются и на хосте (внутри зеркалируемого дерева). Исключение — копирование конфигов в /etc/nginx/: там --delete не используется, чтобы не трогать сторонние файлы в conf.d и sites-available.
QMServer в Docker: образ ghcr.io/<GHCR_OWNER>/qmserver (Cloud-сборка, -tags cloud), подставляется из .env.cloud / .env (GHCR_OWNER — владелец пакетов на GitHub). При таргете make deploy на сервер зеркалируются исходники QMServer/ (и др.) для отладки и Swagger, а контейнер qmserver поднимается с уже собранного образа (make build-all-cloud делает pull для QMServer и build для QMAdmin/QMWeb/QMDocs). Платформа образа — Linux x86_64 (amd64) (platform: linux/amd64).
Публичная сборка в Docker: docker-compose.yaml → образ ghcr.io/<GHCR_OWNER>/qmserver:free-latest (тот же пакет qmserver, что и Cloud; workflow build-qmserver-public-image).
Без Docker: один исполняемый qmserver и systemd — см. QMServer — Запуск и deploy/systemd/ в репозитории QMServer. Сценарий install.sh (нативно или Docker Compose): QMServer.
Репозиторий mindevis/QMServer — единый код; варианты сборки описаны в BUILD.md в том репозитории. Один пакет GHCR ghcr.io/<owner>/qmserver: теги latest (Cloud) и free-latest (публичная сборка).
Только QMAdmin без монорепозитория: образ ghcr.io/<owner>/qmadmin, релизы со статикой qmadmin-*-dist.tar.gz, сценарий install.sh (QMAdmin) — репозиторий mindevis/QMAdmin.
Только QMWeb без монорепозитория: образ ghcr.io/<owner>/qmweb, релизы qmweb-*-dist.tar.gz, install.sh (QMWeb) — mindevis/QMWeb.
Отдельные цели deploy-qmadmin, deploy-qmweb, deploy-qmserver, deploy-qmdocs, deploy-images используют тот же принцип для своих деревьев под DEPLOY_PATH.
QMDocs — статический сайт: в каталоге QMDocs выполняется npm ci (или npm install) и npm run build; артефакты каталога build/ отдаются через Nginx на хосте (порт 8243 в таблице ниже). Для Kubernetes используйте образ со статикой, например ghcr.io/<owner>/qmdocs:<tag>, собранный из Dockerfile в репозитории QMDocs — в Helm-чарте QMDeploy задайте образ и хосты через values.yaml (см. репозиторий QMDeploy).
Фронтенды QMAdmin и QMWeb (Vite): базовый URL API задаётся переменной QMSERVER_API_URL на этапе npm run build / docker build (вшивается в статику). В docker-compose.cloud.yaml в оба образа передаётся build-arg QMSERVER_API_URL=${QMSERVER_PUBLIC_URL}/api/v1 (см. env.cloud.example). Локально — файлы .env в каталогах QMAdmin и QMWeb (образцы: .env.example). В vite.config у обоих приложений указано envPrefix: ['VITE_', 'QMSERVER_'], поэтому QMSERVER_* и прежние VITE_* (например ссылки QMClient, лаунчер в QMWeb) доступны в import.meta.env.
Стек согласован так: QMAdmin, QMWeb и (при облачных настройках) QMLauncher обращаются к QMServer по одному базовому URL API. После развёртывания в QMAdmin обычно включают нужные модули (в Cloud — в т.ч. QMBilling; во Free — без биллинга) и интеграции (QMLauncher, QMWeb; в Cloud при необходимости Removed auth stack). Иначе часть API для клиентов будет недоступна (см. QMServer). Синхронизация инвентаря (POST /api/v1/inventory, QXSync, coming soon) на QMServer действует при модуле Minecraft и интеграции QMWeb — см. Синхронизация инвентаря. В env.cloud.example кратко описаны флаги по умолчанию.
Компоненты на сервере
| Сервис | Порт | Домен |
|---|---|---|
| QMServer | 8240 | api.qx-dev.ru |
| QMAdmin | 8241 | admin.qx-dev.ru |
| QMWeb | 8242 | web.qx-dev.ru |
| QMDocs | 8243 | qm.qx-dev.ru |
| Removed auth stack (Auth) | (Ingress) | auth.qx-dev.ru — отдельный сервис OAuth2/JWKS в кластере; см. AUTH_HOST в values Helm (QMDeploy) |
| Nginx (на хосте) | 80, 443 | Reverse proxy → 127.0.0.1:8240–8243 |
Nginx (на хосте)
Nginx устанавливается на хост, не в Docker. При деплое конфиги из nginx/sites-available/ копируются в /etc/nginx/sites-available/, в /etc/nginx/sites-enabled/ создаются симлинки на них.
api.qx-dev.ru.conf→ 127.0.0.1:8240admin.qx-dev.ru.conf→ 127.0.0.1:8241web.qx-dev.ru.conf→ 127.0.0.1:8242qm.qx-dev.ru.conf→ 127.0.0.1:8243
Kubernetes (K3s)
Развёртывание в кластере (K3s или любой Kubernetes) выполняется через Helm из отдельного репозитория QMDeploy: чарт qm-project, скрипт scripts/install-k3s-helm.py (при необходимости ставит K3s, затем helm upgrade --install). В корне монорепозитория qm-project каталог QMDeploy/ — то же содержимое (после публикации репозитория — git submodule, см. QMDeploy/PUBLISH.md). Пути по умолчанию kubectl apply / render.py / миграция migrate-from-kubectl не поддерживаются.
Кратко:
- Клонируйте QMDeploy (или откройте
QMDeploy/в монорепо). - Подготовьте
values.yaml(образыghcr.io/<owner>/…, Ingress-хосты,AUTH_HOSTдля Removed auth stack и т.д.). - Выполните
sudo python3 scripts/install-k3s-helm.py -f my-values.yaml(нужны Helm 3 и доступ к API кластера).
Секреты qm-mysql и qm-app чарт не создаёт — создайте их в namespace qm до или после установки. Приватный GHCR: imagePullSecrets в values.
Подробности — QMDeploy/README.md, deploy/README.md в монорепозитории.
Синхронизация с GitHub без полного клона (sync-from-github.py)
Скрипт QMDeploy/scripts/sync-from-github.py скачивает в кэш (по умолчанию /opt/qm у root, иначе ~/.cache/qm) чарт qm-project, файл VERSION и скрипты из QMDeploy. Переменные: QM_HELM_BASE_URL (raw .../helm), QM_DEPLOY_BASE_URL (корень репозитория), QM_HELM_CACHE, QM_DEPLOY_ROOT. Затем: helm upgrade --install с путём к чарту в кэше.
Опционально: Argo CD и MinIO S3 (Helm)
QMDeploy/scripts/install-optional-addons.py: --argocd, --s3 (внешние chart’ы argo/argo-cd, bitnami/minio). Нужны Helm и kubectl с доступом к кластеру. Для Argo CD по умолчанию задаётся домен k3s.qx-dev.ru (Ingress traefik; переопределение: --argocd-host). Значения Helm: QMDeploy/helm/argocd/values-k3s.yaml.
Версионирование
В QMDeploy: VERSION (semver бандла), helm/qm-project/Chart.yaml (version, appVersion) — согласуются при релизе.
Обновление образов (например QMWeb)
helm upgrade qm ./helm/qm-project -n qm --reuse-values --set imageTag=<тег>
# из каталога QMDeploy; или полный ref образа:
helm upgrade qm ./helm/qm-project -n qm --reuse-values --set images.qmweb=ghcr.io/<GHCR_OWNER>/qmweb:<тег>
Образы должны быть доступны в реестре (для приватного GHCR — pull-secret на ноде).
Релизы QMWeb и текст из CHANGELOG на GitHub
В репозитории QMWeb workflow CI подставляет в описание GitHub Release содержимое секции ## [<версия>] из CHANGELOG.md (номер версии совпадает с package.json). Автогенерация заметок только по коммитам для этого шага отключена. Как задаётся версия и теги образов — см. QMWeb/CHANGELOG.md и комментарии в workflow .github/workflows/build-qmweb-image.yml.
DNS
Настроить A-записи для доменов на IP сервера:
- api.qx-dev.ru
- admin.qx-dev.ru
- web.qx-dev.ru
- qm.qx-dev.ru
- auth.qx-dev.ru (портал Removed auth stack в кластере;
AUTH_HOSTв values Helm, см. QMDeploy) - k3s.qx-dev.ru (опционально Argo CD, если ставите
install-optional-addons.py --argocd)
Removed auth stack Auth
Публичный URL портала Removed auth stack в продакшене (пример): https://auth.qx-dev.ru. Он не заменяет redirect_uri для PKCE у QMAdmin/QMWeb/QMDocs: те URL задаются при сборке (VITE_LEGACY_ENV_) и должны быть перечислены в LEGACY_ENV_ на QMServer. Подробности — QMServer — Removed auth stack OAuth2 PKCE.
Swagger / ReDoc
Документация API доступна по адресам:
- Swagger UI: https://api.qx-dev.ru/docs (редирект на /swagger) или https://api.qx-dev.ru/swagger/index.html
- ReDoc: https://api.qx-dev.ru/redoc
SSL и CloudFlare
Nginx настроен для работы с CloudFlare:
- Редирект HTTP → HTTPS
- Real IP из заголовка CF-Connecting-IP
- Gzip сжатие
- Кэширование статики (JS, CSS, изображения)
Сертификаты Let's Encrypt в /etc/letsencrypt/live/DOMAIN/:
fullchain.pem,privkey.pem
Выпустите сертификаты заранее (certbot) для каждого домена. В каждом конфиге указан путь по имени домена.
Ely.by OAuth (привязка аккаунта Ely.by)
Для использования скинов Ely.by пользователям нужно привязать аккаунт Ely.by. Настройка:
- Зарегистрировать приложение на account.ely.by/dev/applications/new (тип: Website).
- Указать Redirect URI:
https://api.qx-dev.ru/api/v1/auth/ely/callback(или ваш домен API). - Добавить в
.env.cloud(передаётся в QMServer при deploy):ELY_CLIENT_ID— Client ID из приложенияELY_CLIENT_SECRET— Client SecretELY_REDIRECT_URI— тот же URL, что в п.2 (напримерhttps://api.qx-dev.ru/api/v1/auth/ely/callback)ELY_FRONTEND_REDIRECT—https://web.qx-dev.ru(куда редиректить после OAuth)