Перейти к основному содержимому

Установка через Docker Compose

Это самый быстрый путь к работающему control plane Planeon: Docker Compose, один файл окружения и несколько команд — от начала до первого входа меньше чем за 30 минут.

Предварительные требования

  • Docker Engine версии 24 или новее, с плагином Compose (docker compose version показывает версию Compose v2).
  • DNS-имя, которое указывает на хост, где будет работать Planeon, — для веб-консоли, API и gateway из примера ниже. В этом руководстве для всех трёх используется один адрес, vdi.example.com, с маршрутизацией по пути или поддомену на вашем обратном прокси — замените на свой домен.
  • Обратный прокси с терминацией TLS перед веб-консолью, API и gateway. Контейнеры Planeon общаются друг с другом и с прокси по обычному HTTP и WebSocket; терминация TLS и маршрутизация к каждому сервису настраиваются на вашем прокси, а не в этом руководстве. Точные порты и протоколы для каждого пути смотрите в разделе Требования → Сетевые пути.
  • Уже настроенный OIDC-провайдер идентификации с созданным приложением/клиентом для Planeon (issuer URL, audience/client ID и пользователь, которого вы планируете сделать первым администратором). Planeon делегирует аутентификацию вашему провайдеру идентификации и не поставляется со встроенным — поддерживаемые провайдеры перечислены в разделе Что такое Planeon.
  • Сетевой доступ к Docker Hub для скачивания публичных образов planeon/*, указанных ниже, — либо их зеркало в вашем приватном registry, если у хоста установки нет доступа в интернет.

Если вы ещё не сделали этого, перед тем как продолжить, прочитайте раздел Требования — там описан размер управляющего контура, поддержка браузеров и поддержка ОС шаблонов.

compose.yaml

Скопируйте это в файл compose.yaml в пустом каталоге на хосте установки.

name: planeon

services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
env_file: planeon.env
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
# Держите пользователя/БД здесь синхронизированными с
# POSTGRES_USER/POSTGRES_DB в planeon.env, если меняете значения по
# умолчанию ниже.
test: ["CMD-SHELL", "pg_isready -U planeon -d planeon"]
interval: 5s
timeout: 3s
retries: 10

redis:
image: redis:7-alpine
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10

# Одноразовый сервис применения миграций. Он никогда не запускается как
# часть `docker compose up` — только когда вы явно выбираете профиль
# "migrate" (см. «Применение миграций базы данных» и «Обновление» ниже).
migrate:
image: planeon/migrate:v1.0.0
profiles: ["migrate"]
env_file: planeon.env
depends_on:
postgres:
condition: service_healthy

api:
image: planeon/api:v1.0.0
restart: unless-stopped
env_file: planeon.env
ports:
- "8080:8080"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy

worker:
image: planeon/worker:v1.0.0
restart: unless-stopped
env_file: planeon.env
# Должно превышать WORKER_SHUTDOWN_TIMEOUT в planeon.env, чтобы Compose
# не убивал сигналом SIGKILL задание, которое ещё корректно завершается.
stop_grace_period: 45s
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy

# guacd, собранный Planeon с включённым декодированием H.264. В
# стандартном образе сообщества этого декодирования нет, из-за чего
# сессии современных Windows (10/11, Server 2019+) отображаются чёрным
# экраном с одним лишь живым курсором.
guacd:
image: planeon/guacd:v1.0.0
restart: unless-stopped
environment:
# Собственный уровень логов демона guacd (trace|debug|info|warning|error).
# Переопределяется через GUACD_LOG_LEVEL в окружении shell или файле .env
# рядом с compose.yaml; по умолчанию info. См. справочник по конфигурации.
LOG_LEVEL: ${GUACD_LOG_LEVEL:-info}

gateway:
image: planeon/gateway:v1.0.0
restart: unless-stopped
env_file: planeon.env
ports:
- "8081:8081"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
guacd:
condition: service_started

web:
image: planeon/web:v1.0.0
restart: unless-stopped
env_file: planeon.env
ports:
- "3000:3000"
depends_on:
- api

volumes:
postgres_data:
redis_data:

postgres и redis не публикуются на хост — до них достаточно достучаться только внутри сети compose. api (8080), gateway (8081) и web (3000) опубликованы, чтобы до них мог достучаться ваш обратный прокси; направьте на эти три порта его виртуальные хосты или пути и терминируйте там TLS.

planeon.env

Скопируйте это в файл planeon.env рядом с compose.yaml, затем замените все плейсхолдеры перед запуском стека.

# ---------------------------------------------------------------------------
# Метка развёртывания. Только информационная.
# ---------------------------------------------------------------------------
APP_ENV=production
LOG_LEVEL=info

# ---------------------------------------------------------------------------
# PostgreSQL — источник истины Planeon. Первые два блока ниже настраивают
# встроенный контейнер postgres; DATABASE_URL — то, как каждый сервис
# Planeon подключается к нему, поэтому держите учётные данные в обоих
# местах синхронизированными.
# ---------------------------------------------------------------------------
POSTGRES_DB=planeon
POSTGRES_USER=planeon
# Сгенерировать: openssl rand -base64 32
POSTGRES_PASSWORD=change-me

# Должно совпадать с POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB выше.
# "postgres" — имя сервиса внутри сети compose.yaml — оставьте как есть,
# если не переименовываете этот сервис.
DATABASE_URL=postgres://planeon:change-me@postgres:5432/planeon?sslmode=disable
DATABASE_MAX_CONNS=10

# ---------------------------------------------------------------------------
# Redis — очередь заданий, кэширование и короткоживущие токены подключения
# к рабочим столам.
# ---------------------------------------------------------------------------
REDIS_ADDR=redis:6379
REDIS_PASSWORD=
REDIS_DB=0

# ---------------------------------------------------------------------------
# Сервис API.
# ---------------------------------------------------------------------------
API_ADDR=0.0.0.0:8080
API_SHUTDOWN_TIMEOUT=10s
# Зашито в файловую структуру образа planeon/api — оставьте как есть.
OPENAPI_PATH=/usr/local/share/proxmox-vdi-admin/openapi.yaml
# Публичный адрес веб-консоли, до которого доходят через ваш обратный
# прокси.
API_CORS_ALLOWED_ORIGINS=https://vdi.example.com
# Внутренний ops-listener (Prometheus /metrics, /healthz, /readyz) для api
# и worker. Не публикуйте его через обратный прокси.
METRICS_ADDR=0.0.0.0:9090

# ---------------------------------------------------------------------------
# OIDC — Planeon аутентифицирует пользователей и администраторов через
# ваш существующий провайдер идентификации. Защищённые маршруты API
# возвращают 503, пока не заданы одновременно AUTH_OIDC_ISSUER_URL и
# AUTH_OIDC_AUDIENCE.
# ---------------------------------------------------------------------------
AUTH_OIDC_ISSUER_URL=https://idp.example.com/application/o/planeon/
AUTH_OIDC_AUDIENCE=planeon
AUTH_OIDC_GROUPS_CLAIM=groups
AUTH_OIDC_ROLES_CLAIM=roles

# Bootstrap первого администратора (см. «Первый вход» ниже): этому адресу
# автоматически выдаётся роль platform_admin при первом входе с этой
# личностью. Используйте только для первого доступа или аварийного
# восстановления.
AUTH_BOOTSTRAP_ADMIN_EMAILS=admin@example.com
AUTH_BOOTSTRAP_ADMIN_SUBJECTS=
AUTH_BOOTSTRAP_OIDC_GROUP_BINDINGS=

# ---------------------------------------------------------------------------
# Веб-консоль — настройка OIDC-клиента на стороне браузера. Образ
# planeon/web применяет эти значения NEXT_PUBLIC_* при старте контейнера,
# так что изменение здесь вступает в силу при следующем
# `docker compose up -d` — пересборка образа не нужна.
# ---------------------------------------------------------------------------
NEXT_PUBLIC_API_BASE_URL=https://vdi.example.com
NEXT_PUBLIC_OIDC_AUTHORITY=https://idp.example.com/application/o/planeon/
NEXT_PUBLIC_OIDC_CLIENT_ID=planeon
NEXT_PUBLIC_OIDC_SCOPE=openid profile email groups offline_access
# Оставьте пустым, чтобы использовать стандартный end_session_endpoint
# вашего провайдера идентификации из OIDC discovery. Задавайте явно, только
# если вашему провайдеру нужен отдельный URL выхода/инвалидации.
NEXT_PUBLIC_OIDC_LOGOUT_URL=

# ---------------------------------------------------------------------------
# Gateway — туннель браузерного доступа к рабочим столам.
# ---------------------------------------------------------------------------
GATEWAY_ADDR=0.0.0.0:8081
GUACD_ADDRESS=guacd:4822
# Публичный WSS-адрес gateway через ваш обратный прокси. Возвращается
# браузеру сервисом api в ответе с токеном подключения.
GATEWAY_PUBLIC_WS_URL=wss://vdi.example.com/tunnel

# ---------------------------------------------------------------------------
# Шифрование секретов в состоянии покоя — защищает хранимые токены
# кластеров Proxmox, учётные данные гостевых ОС и токены подключения
# Guacamole. Обязательно. Без ключа gateway отказывается запускаться (ключ
# нужен ему для обмена токенов подключения); api и worker запускаются в
# деградированном режиме, пока зашифрованных данных ещё нет (секреты
# сохранять нельзя), и отказываются запускаться, как только они появятся.
# Одно и то же значение на api, worker и gateway.
# ---------------------------------------------------------------------------
# Сгенерировать: openssl rand -base64 32
SECRETS_MASTER_KEY=change-me
# Задавайте только на время окна ротации ключа; в остальное время оставляйте
# пустым.
SECRETS_MASTER_KEY_PREVIOUS=

# ---------------------------------------------------------------------------
# Worker — реконсиляция пулов и обработка заданий. Значения ниже совпадают
# со встроенными по умолчанию; для первой установки можно оставить как
# есть.
# ---------------------------------------------------------------------------
WORKER_POLL_INTERVAL=1m
POOL_RECONCILE_INTERVAL=30s
POOL_RECONCILE_BATCH_SIZE=50
GUEST_AGENT_WAIT_TIMEOUT=10m
WINDOWS_READY_WAIT_TIMEOUT=30m
WORKER_LEASE_DURATION=5m
WORKER_SHUTDOWN_TIMEOUT=30s
AUDIT_RETENTION_MONTHS=0
AUDIT_MAINTENANCE_INTERVAL=24h

Сам кластер Proxmox VE настраивается не через planeon.env — вы подключите его из веб-консоли после первого входа, и именно с этого начинается быстрый старт.

Справочник по конфигурации описывает каждую переменную выше — значение по умолчанию, обязательность, является ли она секретом и что она делает.

Установка

1. Скачайте образы

docker compose pull

2. Примените миграции базы данных

Миграции — отдельный, явный шаг: Planeon никогда не применяет их автоматически при старте контейнера. Это делает изменения схемы видимыми и проверяемыми, не даёт нескольким репликам одновременно гонять миграции наперегонки и гарантирует, что неудачная миграция остановит выкладку до того, как новая версия начнёт обслуживать трафик.

docker compose --profile migrate run --rm migrate

3. Запустите платформу

docker compose up -d

Это запускает postgres, redis, api, worker, guacd, gateway и web. migrate остаётся остановленным — он запускается только когда вы явно передаёте --profile migrate. Убедитесь, что все сервисы в состоянии Up, а postgres и redis дополнительно показывают (healthy):

docker compose ps

Если какой-то сервис не запускается или остаётся нездоровым, см. раздел Устранение неполадок.

4. Первый вход

Откройте веб-консоль по публичному адресу, на котором вы опубликовали сервис web (в этом примере https://vdi.example.com), и войдите через вашего провайдера идентификации.

У Planeon нет встроенного хранилища локальных паролей — доступ администратора начинается с механизма bootstrap: адресу, который вы указали в AUTH_BOOTSTRAP_ADMIN_EMAILS (или, если использовали его вместо этого, AUTH_BOOTSTRAP_ADMIN_SUBJECTS), автоматически выдаётся роль platform_admin при первом входе с этой личностью — без ручных правок базы данных. Используйте эту bootstrap-переменную только для первого доступа или аварийного восстановления; после входа выдавайте права дальнейшим администраторам через экраны управления доступом, а не добавлением новых bootstrap-адресов.

После входа в качестве администратора платформы переходите к быстрому старту, чтобы подключить ваш кластер Proxmox, подготовить шаблон и собрать первый пул рабочих столов.

Обновление

Обновление следует тому же явному порядку, что и установка, плюс перезапуск:

# 1. Обновите теги образов в compose.yaml (и добавьте в planeon.env любые
# новые переменные) для релиза, на который вы обновляетесь.
docker compose pull
docker compose --profile migrate run --rm migrate
docker compose up -d

Порядок важен: миграции всегда выполняются до того, как новые образы начинают обслуживать трафик, — никогда не после и никогда автоматически. Запуск нового кода на ещё не мигрированной схеме или старого кода на схеме, которая уже ушла вперёд, — это ровно то рассогласование, которое призвана отлавливать проверка готовности api и worker; см. Наблюдаемость → Семантика readiness. Именно то, что шаг миграции остаётся явным и отдельным, избавляет от необходимости полагаться на эту проверку под реальной нагрузкой пользователей.