--- # Конфигурация HRBox для установки в своём кластере. # # Заполните перед первой установкой: # ingress.host домен, по которому будет открываться HRBox # app.defaultTenantHostname тот же домен # app.postgres.* подключение к PostgreSQL # app.s3.* хранилище файлов # app.smtp.* почта # app.hub.token токен HRBox Hub, выдают сотрудники HRBox # secrets.* три ключа, генерируются openssl # app.chatbox.wrappingKey ключ шифрования чатов # app.nanabushPlayer.keys.* два ключа плеера курсов # # Если что-то из этого не заполнено, helm остановится и напишет, чего не # хватает. Команды генерации ключей — в README, раздел «Секреты». # Базовое имя объектов. Пусто — имя чарта: hrbox-web, hrbox-worker и т.д. # На уже работающей установке менять нельзя. nameOverride: "" # --- Образы --------------------------------------------------------------- image: # Приложение: PHP-FPM, nginx, worker, миграции. # Доступ к реестру выдают сотрудники HRBox. hrbox: "cr.yandex/crphnph9c2s776j32sjd/hrbox:latest" # Чат и вебсокеты chatbox: "cr.yandex/crphnph9c2s776j32sjd/hrbox-chatbox:5.18" # Мессенджеры, пуши, синхронизация оргструктуры goworker: "cr.yandex/crphnph9c2s776j32sjd/hrbox-goworker:3.21.2" # Электронная подпись: КЭДО, МЧД kedoca: "cr.yandex/crphnph9c2s776j32sjd/hrbox-kedoca:1.0.6" # Справочник городов, стран, часовых поясов geonames: "cr.yandex/crphnph9c2s776j32sjd/hrbox-geonames:3.3" # Конвертация документов и изображений fileProcessor: "cr.yandex/crphnph9c2s776j32sjd/hrbox-file-processor:1.4.6" # Планировщик задач по расписанию conductor: "cr.yandex/crphnph9c2s776j32sjd/hrbox-conductor:2.2.0" # Плеер курсов. Нужен конкретный тег, latest не подходит: # из тега берётся версия плеера. nanabushPlayer: "cr.yandex/crphnph9c2s776j32sjd/nanabush-player:1.0.11" # Инфраструктура dragonfly: "cr.yandex/crpnn6fi85p3dauha6nc/dragonflydb:1.15.1" nats: "nats:2.10" natsConfigReloader: "natsio/nats-server-config-reloader:0.6.2" phpFpmExporter: "cr.yandex/crpnn6fi85p3dauha6nc/php-fpm_exporter:latest" # Только для джобы миграций: ждёт готовности базы postgresClient: "postgres:14-alpine" # Только при app.tracing.enabled otelCollector: "otel/opentelemetry-collector:0.109.0" pullPolicy: IfNotPresent # Secret с доступом к реестру образов. Создаётся отдельно, см. README, шаг 1. imagePullSecrets: - name: regsecret # --- Приложение ----------------------------------------------------------- app: # Домен установки. Должен совпадать с ingress.host. defaultTenantHostname: "hrbox.example.com" # Имя установки, видно в логах и метриках instanceName: "onprem" # "1" — установка обслуживает одну компанию singleTenant: "0" # "true" — новый интерфейс, "false" — старый front2: "true" # Отдельный домен авторизации. Для on-premise обычно пусто. authHost: "" # "0" — production, "1" — отладка debug: "0" # Подставлять https во всех ссылках, которые генерирует приложение forceHttps: "true" # Число подов каждого сервиса. # web — по числу пользователей, worker — по объёму фоновых задач, # chatbox — по числу открытых вкладок, остальным обычно хватает 1-2. replicas: web: 2 worker: 2 chatbox: 2 geonames: 1 goworker: 2 kedoca: 1 fileProcessor: 1 fileProcessorVideo: 1 # Свои ссылки на политику конфиденциальности и правила использования. # false — показываются ссылки HRBox. customPolicy: enabled: false # privacyUrl: "https://example.com/privacy" # termsUrl: "https://example.com/terms" # --- PostgreSQL --------------------------------------------------------- # Нужен PostgreSQL 14 или новее. Чарт базу не разворачивает. postgres: host: "postgresql" port: "5432" database: "hrbox" user: "hrbox" # Попадает в Secret, в спеке подов пароля нет password: "" # "true", если база на Citus (шардирование) citus: "false" # --- Redis / Dragonfly -------------------------------------------------- # Сессии, кеш и очереди плеера курсов. # Пусто — используется Dragonfly из этого же релиза. # Адрес указывают, если Redis внешний (тогда обычно dragonfly.enabled: false). redis: host: "" port: "6379" # --- NATS --------------------------------------------------------------- # Пусто — используется NATS из этого же релиза. # Внешний кластер: nats://node1:4222,nats://node2:4222,nats://node3:4222 nats: url: "" # --- S3 ----------------------------------------------------------------- # Подойдёт AWS S3, MinIO, Yandex Object Storage, VK Cloud Storage. s3: # MinIO: http://minio:9000 # Yandex: https://storage.yandexcloud.net # VK: https://hb.vkcloud-storage.ru endpoint: "https://storage.example.com" bucket: "hrbox" key: "" secret: "" region: "us-east-1" version: "latest" # "true" для MinIO и своего S3, "false" для AWS S3 pathStyle: "true" multipart: "true" prefix: "" # --- Почта -------------------------------------------------------------- smtp: host: "smtp.example.com" # 25 — без шифрования, 587 — STARTTLS, 465 — SSL/TLS port: "587" user: "noreply@example.com" password: "" from: "noreply@example.com" fromHost: "example.com" # "", "tls" или "ssl" securityType: "tls" sslAllowSelfSigned: "true" sslVerifyPeer: "false" # --- Sentry ------------------------------------------------------------- sentry: dsn: "" environment: "production" # Пусто — используется общий dsn launchpadDsn: "" conductorDsn: "" # Здесь пусто означает «не отправлять» goworkerDsn: "" chatboxDsn: "" # --- Внутренние сервисы ------------------------------------------------- # Пустой url — сервис берётся из этого же релиза. # Заполняют, если сервис вынесен наружу. geonames: url: "" goworker: url: "" # Не чаще одного push одному пользователю за этот интервал pushMinInterval: "5m" kedoca: url: "" # Пароль корневого сертификата, который сервис создаёт при первом запуске rootCaPass: "hrbox" # "gost" (КриптоПро) или "openssl" engine: "gost" # "gost2012_256" для ГОСТ, "rsa" для OpenSSL algorithm: "gost2012_256" # "paramset:A" для ГОСТ, "rsa_keygen_bits:2048" для RSA pkeyopt: "paramset:A" # Служба меток времени tspUrl: "http://qs.cryptopro.ru/tsp/tsp.srf" # Secret с сертификатами УЦ. Если задан, монтируется в /ca-cert. secretName: "" fileProcessor: # Сколько документов конвертировать одновременно в одном поде docconvMaxParallelTasks: "1" # Сколько изображений обрабатывать одновременно в поде конвертации видео imageResizeMaxParallel: "20" # --- Конвертация видео -------------------------------------------------- # Отдельные поды: видео требует много CPU и диска, поэтому его выносят # на выделенные ноды. videoConverter: enabled: false # Внутренний адрес HRBox, откуда конвертер берёт и куда отдаёт файлы. # Пусто — http://<релиз>-web. internalUrl: "" # На каких нодах запускать. Пусто — на любых. # Пример: role: converter-dedicated nodeSelector: {} # Пример: # - key: dedicated # operator: Equal # value: video-converter # effect: NoSchedule tolerations: [] # --- Чат ---------------------------------------------------------------- chatbox: # Часть ключа шифрования чатов, 32 символа. # Генерация: openssl rand -hex 16 wrappingKey: "" # --- Видеозвонки -------------------------------------------------------- livekit: url: "" apiKey: "" apiSecret: "" # --- Nanabush Player ---------------------------------------------------- # Плеер учебных материалов: SCORM 1.2 и 2004, cmi5, xAPI, нативные курсы, # тесты и эссе. # # В облаке плеер стоит на отдельном поддомене, в on-premise поддомена нет, # поэтому он живёт на основном домене по пути basePath. Домен общий, значит # cookie HRBox доступны содержимому курсов. Если нужна изоляция сторонних # SCORM-пакетов, обратитесь в HRBox за схемой с отдельным поддоменом. nanabushPlayer: # false — материалы открываются старым проигрывателем enabled: true # Путь на основном домене. Корень "/" занят самим HRBox. basePath: "/nanabush-player" # Issuer launch-тикета. Пусто — https:///lms/player issuer: "" contractVersion: "v0-current" # Оба ключа обязательны и должны быть разными. # Генерация каждого: openssl rand -base64 48 keys: ticketHs256: "" sessionHs256: "" # Набор ключей для ротации без простоя, необязательный: # "kid1:секрет1,kid2:секрет2". Первым идёт ключ, которым подписывают # сейчас. Запятая внутри секрета недопустима, используйте base64url. ticketKeys: "" rollout: # Какая доля запусков идёт в новый плеер. 100 — все. percent: 100 # Открывать материал старым проигрывателем, если плеер не ответил legacyFallback: true allowedContentTypes: - document - presentation - video - audio - scorm - cmi5 - xapi - course - native - native_quiz - native_essay # "*" — все компании, включая новые allowedTenants: - "*" service: # Пусто — <релиз>-nanabush-player name: "" port: 8094 # Публиковать ли путь плеера на общем Ingress. # Выключают только при откате. ingress: enabled: true deployment: # Создавать ли Deployment и Service плеера enabled: true replicas: 1 terminationGracePeriodSeconds: 120 # Умеет ли образ плеера работать не в корне домена, а по пути. # Со старым образом без такой поддержки поставьте false — чарт # остановит установку вместо того, чтобы развернуть нерабочий плеер. binaryCapabilities: basePath: true # Secret с ключами плеера. # create: false — Secret заводят вне чарта, чарт только ссылается. existingSecret: create: true name: "hrbox-nanabush-player" keys: ticketHs256: player-hs256-secret sessionHs256: player-session-hs256-secret redisUrl: redis-url ticketKeys: "" ticket: # Сколько живёт launch-тикет, секунды ttlSeconds: 300 # Сколько живут учётные данные обратного канала: сессия плеера плюс # 2 минуты на расхождение часов credentialTtlSeconds: 28920 maxLifetime: "5m" sessionTtl: "8h" # Нужно только при первом переходе на набор ключей: до какого момента # (RFC3339) принимать тикеты без kid. Пусто — не принимать. keylessAcceptedUntil: "" redis: # false — адрес собирается из app.redis. # true — полный redis:// или rediss:// URL берётся из внешнего Secret # (нужно для пароля, ACL или TLS), требует existingSecret.create: false urlFromExistingSecret: false database: 0 # Полный префикс: hrbox::<суффикс>. # Разделяет несколько установок HRBox на одном Redis. keyPrefixSuffix: "nanabush-player" # Обращения плеера обратно в HRBox: за пакетом курса и с отчётами backchannel: # Внутренний адрес HRBox. Пусто — <релиз>-web. host: "" schemes: "http" allowPrivateIps: true packageFetchMaxBytes: "5242880" # Должно вмещать самый большой медиафайл курса packageContentMaxBytes: "2147483648" scormPackageMaxBytes: "1073741824" # Пусто — берётся значение приложения (4000 файлов) scormPackageMaxFiles: "" packageFetchTimeout: "15s" # Считается до конца передачи файла в браузер учащегося, поэтому # зависит от скорости его интернета packageStreamTimeout: "20m" reportTimeout: "30s" # Очередь отправки учебных событий в HRBox forwarder: queueSize: "1000" workers: "4" maxAttempts: "5" initialBackoff: "1s" maxBackoff: "30s" perAttemptTimeout: "30s" deadLetterSize: "256" claimIdle: "5m" pollInterval: "1s" rateLimitEventsPerMinute: "600" rateLimitBatchesPerMinute: "120" rateLimitPayloadBytesPerMinute: "8388608" log: level: info format: json # Метрики отдаются на отдельном порту и наружу не публикуются metrics: enabled: true port: 9090 probes: readiness: path: /readyz initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 6 liveness: path: /healthz initialDelaySeconds: 20 periodSeconds: 20 timeoutSeconds: 2 failureThreshold: 3 # --- Фоновые задачи ----------------------------------------------------- # Формат: "очередь:сколько воркеров" launchpad: topics: "launcher:1,file-processor:1,image-processor:1,send-mail:1,send-im:1,send-bell:1,send-push:1,backup:1,cleaning:1" sms: senderName: "HRBOX" # --- Внешние интеграции ------------------------------------------------- integrations: telegram: # Если прямого доступа к Telegram нет, укажите адрес прокси apiUrl: "https://api.telegram.org/bot" google: enabled: "false" # clientId уходит в браузер, clientSecret попадает в Secret clientId: "692956564858-ccapt35khk7tmadl17b3879ht2cropp6.apps.googleusercontent.com" clientSecret: "" glagol: partnerId: "ab230ee1-6946-43b9-8kfa-447beb8348b0" apiUrl: "https://api.glagol.online/glagol-api" # Привязка мобильных приложений к домену: без неё ссылки из писем и пушей # открываются в браузере, а не в приложении. По умолчанию указаны # приложения HRBox, меняйте только для своей сборки. mobileApps: android: - packageName: "io.hrbox.hrboxapp" sha256CertFingerprints: - "DE:75:B2:CA:CB:50:96:02:8D:E1:07:4F:CE:E9:92:1C:4C:ED:87:B0:64:12:1A:69:27:7B:D2:B5:1A:23:31:70" apple: appIds: - "DX67FD7GQJ.io.hrbox.app" yandex: clientId: "" clientPassword: "" slack: clientId: "" clientSecret: "" verificationToken: "" # --- HRBox Hub ---------------------------------------------------------- # Лицензирование и общие сервисы. Токен выдают сотрудники HRBox. hub: url: "https://hub.hrbox.io" token: "" # --- AI ----------------------------------------------------------------- ai: docsIndexEnabled: "true" semanticIndexEnabled: "true" semanticIndexUseBatch: "true" yandex: folderId: "" apiKey: "" # --- Трассировка -------------------------------------------------------- # Включает OpenTelemetry в PHP и коллектор рядом с подом web tracing: enabled: false exporterUrl: "http://localhost:4318" # Куда коллектор отправляет трейсы: Tempo, Jaeger tempoUrl: "" # --- Безопасность ------------------------------------------------------- security: # "true" даёт встроенному iframe полный доступ к родительскому окну. # Для production лучше "false". iframeFullAccess: "false" # --- Секреты -------------------------------------------------------------- # Эти значения вместе с паролями из app.* складываются в один Kubernetes # Secret, поды читают их оттуда. secrets: # Имя Secret, созданного вне чарта. Если задано, чарт свой Secret не # создаёт и берёт ключи из указанного. Список ключей — в README. existingSecret: "" # Защита cookie от подделки, 32 символа. # Генерация: openssl rand -hex 16 cookieValidationKey: "" # Шифрование паролей интеграций в базе. # Без этого ключа данные не расшифровать, храните копию отдельно. # Генерация: openssl rand -base64 48 encryptionKey: "" # Проверка вызовов между сервисами внутри релиза. # Генерация: openssl rand -base64 48 servicesInternalSecret: "" # --- Ingress -------------------------------------------------------------- ingress: enabled: true # Обычно "nginx" или "traefik" className: "nginx" # Домен установки. Для мультиарендности можно wildcard: *.hrbox.company.com host: "hrbox.example.com" # Дополнительные аннотации ingress-контроллера annotations: {} # Максимальный размер загружаемого файла. # У загрузки оргструктуры из 1С отдельный лимит, он выше. maxBodySize: "10m" tls: enabled: true # kubectl create secret tls hrbox-tls --cert=cert.pem --key=key.pem # или выпустить сертификат через cert-manager secretName: "hrbox-tls" # --- Кластер -------------------------------------------------------------- cluster: # Домен служебных имён Kubernetes. Менять только если он нестандартный. domain: "cluster.local" # --- Ресурсы -------------------------------------------------------------- # Значения близки к тем, что используются в облаке HRBox. # Можно оставить только requests: незаполненные поля в манифест не попадают. resources: # PHP-FPM: веб-интерфейс и API app: requests: cpu: "1" memory: "2Gi" ephemeralStorage: "64Mi" limits: cpu: "2" memory: "2Gi" ephemeralStorage: "2Gi" # nginx в поде web nginx: requests: cpu: "0.1" memory: "256Mi" ephemeralStorage: "64Mi" limits: cpu: "0.5" memory: "256Mi" ephemeralStorage: "512Mi" # Фоновые задачи: файлы, почта, отчёты worker: requests: cpu: "0.6" memory: "640Mi" ephemeralStorage: "4Gi" limits: cpu: "2" memory: "4Gi" ephemeralStorage: "8Gi" # Планировщик задач по расписанию conductor: requests: cpu: "0.25" memory: "128Mi" ephemeralStorage: "64Mi" limits: cpu: "0.7" memory: "384Mi" ephemeralStorage: "64Mi" chatbox: requests: cpu: "0.3" memory: "96Mi" ephemeralStorage: "128Mi" limits: cpu: "1" memory: "256Mi" ephemeralStorage: "256Mi" geonames: requests: cpu: "0.1" memory: "196Mi" ephemeralStorage: "64Mi" limits: cpu: "0.5" memory: "256Mi" ephemeralStorage: "64Mi" goworker: requests: cpu: "0.1" memory: "196Mi" ephemeralStorage: "64Mi" limits: cpu: "0.5" memory: "256Mi" ephemeralStorage: "64Mi" kedoca: requests: cpu: "0.1" memory: "196Mi" ephemeralStorage: "64Mi" limits: cpu: "1" memory: "256Mi" ephemeralStorage: "64Mi" fileProcessor: requests: cpu: "0.5" memory: "512Mi" ephemeralStorage: "2Gi" limits: cpu: "1" memory: "1Gi" ephemeralStorage: "2Gi" # Конвертация видео: тяжёлые поды на отдельных нодах fileProcessorVideo: requests: cpu: "4" memory: "4Gi" ephemeralStorage: "40Gi" limits: cpu: "8" memory: "8Gi" ephemeralStorage: "44Gi" nanabushPlayer: requests: cpu: "0.1" memory: "192Mi" limits: memory: "512Mi" dragonfly: requests: cpu: "0.1" memory: "256Mi" limits: cpu: "1" memory: "1Gi" nats: requests: cpu: "0.1" memory: "256Mi" limits: cpu: "1" memory: "2Gi" # Разовые задачи: миграции и обновление кластера jobs: requests: cpu: "0.5" memory: "1Gi" ephemeralStorage: "64Mi" limits: cpu: "2" memory: "4Gi" ephemeralStorage: "256Mi" # --- NATS ----------------------------------------------------------------- nats: # HRBox без брокера не работает. Выключают, только если NATS ставят # отдельно и указали его адрес в app.nats.url. enabled: true # Для отказоустойчивости 3 или 5. Должно совпадать с cluster.replicas. replicas: 3 jetstream: enabled: true # Хранение в памяти: подходит небольшим установкам memStorage: enabled: true size: "2Gi" # Хранение на диске: для production fileStorage: enabled: false size: "4Gi" storageDirectory: "/data" # JetStream нужен быстрый диск storageClassName: "fast-ssd" cluster: enabled: true # Должно совпадать с nats.replicas replicas: 3 # Подхватывает изменения конфигурации без перезапуска NATS reloader: enabled: true terminationGracePeriodSeconds: 120 # --- Dragonfly ------------------------------------------------------------ # Redis-совместимый кеш. dragonfly: # false — если Redis ставят отдельно; тогда заполните app.redis.host enabled: true # Ограничение памяти # maxmemory: "256M"