Перейти к содержанию

Конфигурация .env

Статья разбирает единый файл окружения платформы — .env в корне суперпроекта — по группам: что означает каждая переменная, в какие переменные сервисов она раскладывается в compose.yml, какое значение нормально для локального стенда и что менять для своего. Полный алфавитный перечень всех переменных всех компонентов — в Переменных окружения.

Как устроена конфигурация

flowchart LR
    EX[.env.example<br/>в git] -->|make secrets| ENV[.env<br/>0600, вне git]
    ENV -->|интерполяция| C[compose.yml]
    C -->|CP_*| CP[control-plane-*]
    C -->|IAM_*| IAM[iam-service]
    C -->|CB_*| MEM[memory-service]
    C -->|KC_*, S3_*, SERVICE_GATEWAY_*| PL[platform-*]
    C -->|SD_*, PR_*, POL_*, ENT_*| OPT[опциональные сервисы]
    B[deploy/bootstrap.py] -->|читает| ENV
    B -->|пишет| SEC[secrets/*.env, *-pat]
    SEC -->|env_file| CP

Принципы:

  • Одно понятие — одно имя. В .env задаётся, например, один MEMORY_API_KEY, а compose.yml сам раскладывает его в CB_SERVER_API_KEY памяти, CP_CONTEXT_API_KEY ядра и SD_MEMORY_TOKEN демо. Код сервисов для смены окружения менять не нужно.
  • Локальный и промышленный стенд различаются только .env и Caddyfile. DNS-имена сервисов внутри сети одинаковые.
  • Секреты — только в .env и secrets/. Оба пути в .gitignore.
  • .env читают три потребителя: Docker Compose (автоматически из корня), deploy/bootstrap.py (--env .env) и tools/smoke.py (порты).
  • Переменные, которых нет в .env.example, имеют значения по умолчанию прямо в compose.yml (${VAR:-default}) — их можно добавить в .env, чтобы переопределить.

Интерполяция всего файла

Compose подставляет переменные во все сервисы, включая сервисы невключённых профилей. Поэтому обязательными (${VAR:?…}) объявлены только значения, которые генерирует make secrets. IAM_TENANT_ID, SUPPORT_BOT_PAT и SUPPORT_WORKSPACE_ID по умолчанию пусты и нужны только своим профилям — см. Установка и первый запуск.

Окружение

Переменная По умолчанию Смысл
TAIMEN_PUBLIC_URL http://taimen.localhost Публичный адрес платформы без завершающего /. Из него выводятся issuer IAM (${TAIMEN_PUBLIC_URL}/iam), issuer Keycloak (…/auth/realms/platform), адреса веба и platform-api. Попадает в каждый токен и в bindings Control Plane
TAIMEN_PUBLIC_HOST taimen.localhost Имя хоста из адреса выше. Становится сетевым alias Caddy, чтобы контейнеры ходили на публичный адрес через него
COMPOSE_PROJECT_NAME taimen Имя compose-проекта: префикс контейнеров и volumes, имя tenant (slug) и файла состояния bootstrap по умолчанию
TAIMEN_NETWORK taimen_default Имя docker-сети всех сервисов
CADDYFILE ./deploy/caddy/Caddyfile.local Конфигурация периметра. Локальная — http без ACME; для промышленного стенда — файл с TLS
EDGE_HTTP_PORT, EDGE_HTTPS_PORT 80, 443 Порты Caddy на хосте
LOG_LEVEL INFO Уровень логов сервисов (CP_LOG_LEVEL, OpenFGA, platform-api)
LOG_RENDERER console Формат логов platform-api (console или json; по умолчанию в compose — json)
CP_TIMEZONE Europe/Moscow Часовой пояс отображения дат в веб-консоли (NEXT_PUBLIC_CP_TIMEZONE, печётся в бандл при сборке)

Смена TAIMEN_PUBLIC_URL на живом стенде

Issuer IAM выводится из публичного адреса, а bindings Control Plane ищутся по паре (issuer, principal). Сменив адрес, вы закроете вход всем principal, пока bindings не будут перенесены на новый issuer. Выбирайте адрес до bootstrap. Процедура переноса — в Обновлении и миграциях.

Tenant

Переменная Смысл
IAM_TENANT_ID UUID tenant в IAM. Известен только после bootstrap (он напечатает строку впишите в .env: IAM_TENANT_ID=…). Нужен шлюзу platform-api (SERVICE_GATEWAY_IAM_TENANT_ID), fleet-controller, launcher'у харнессов и git-connector. Ядру (core) не нужен

Остальные идентификаторы (tenant Control Plane, оператор, проект, workspace) bootstrap хранит в deploy/state/<имя>.json.

Секреты

Все заполняются make secrets случайными значениями, если пусты.

Переменная Куда попадает Смысл
CP_POSTGRES_PASSWORD control-plane-db, CP_DATABASE_URL пароль БД Control Plane
IAM_POSTGRES_PASSWORD iam-db, IAM_DATABASE_URL пароль БД IAM
MEMORY_POSTGRES_PASSWORD memory-db, CB_DATABASE_URL пароль БД памяти
PLATFORM_POSTGRES_PASSWORD platform-db, platform-api пароль БД платформы (профиль platform)
KEYCLOAK_DB_PASSWORD platform-db (БД keycloak), keycloak пароль БД Keycloak
REDIS_PASSWORD platform-redis, platform-api пароль Redis
ENT_POSTGRES_PASSWORD entitlement-db пароль БД Entitlement (без значения — entitlement)
POL_POSTGRES_PASSWORD policy-db, OpenFGA пароль БД policy-service и OpenFGA (без значения — policy)
CP_BOOTSTRAP_TOKEN control-plane-api однократный POST /api/v1/bootstrap (Authorization: Bearer). Пустое значение выключает bootstrap-эндпоинт
IAM_BOOTSTRAP_TOKEN iam-service, воркер policy-service административные операции IAM (X-IAM-Bootstrap-Token): tenants, principals, PAT, service accounts
ENT_BOOTSTRAP_TOKEN entitlement-service администрирование Entitlement
POL_BOOTSTRAP_TOKEN policy-service администрирование policy-service (X-Policy-Bootstrap-Token). Непустое значение включает шаг 7 bootstrap, если policy-service поднят — см. ниже
MEMORY_API_KEY CB_SERVER_API_KEY, CP_CONTEXT_API_KEY, SD_MEMORY_TOKEN статический ключ памяти с полным доступом; ядро пользуется им только до появления service account
KEYCLOAK_ADMIN, KEYCLOAK_ADMIN_PASSWORD keycloak, platform-api администратор Keycloak
KEYCLOAK_CLIENT_SECRET шаблон realm, platform-api секрет confidential-клиента platform-api в realm platform
KEYCLOAK_HOSTNAME_STRICT KC_HOSTNAME_STRICT false локально (http без домена), true на промышленном стенде
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET minio, platform-api учётка MinIO и бакет документов (platform)
IAM_SIGNING_KEY_FILE, IAM_SIGNING_KEY_ID docker-секрет iam_signing_key, IAM_SIGNING_KEY_ID путь к приватному RSA-ключу подписи токенов и его kid в JWKS
ENT_SIGNING_KEY_FILE docker-секрет entitlement_signing_key ключ подписи проекций Entitlement

Шаг policy в bootstrap

deploy/bootstrap.py выполняет настройку policy-service, если в .env есть непустой POL_BOOTSTRAP_TOKEN и policy-service уже отвечает на /healthz. Если профиль policy не поднят, шаг пропускается с сообщением, а bootstrap завершается успешно — трогать переменную не нужно. Чтобы отсутствие профиля считалось ошибкой, запускайте make bootstrap ARGS=--policy: тогда скрипт ждёт сервис до 30 секунд и падает не дождался …/healthz.

IAM_SIGNING_KEY_ID при ротации ключа

kid публикуется в JWKS и стоит в заголовке каждого токена. При замене ключа подписи меняйте и IAM_SIGNING_KEY_ID, иначе сервисы с закэшированным JWKS будут проверять новые токены старым ключом до обновления кэша. См. Секреты и ротация.

LLM

Один OpenAI-совместимый провайдер на всех потребителей: память (эмбеддинги, реранк, синтез), демо support-bot.

Переменная По умолчанию Куда попадает
AITUNNEL_API_KEY пусто CB_EMBEDDING_API_KEY, CB_LLM_API_KEY, SD_LLM_API_KEY — ключ провайдера (имя историческое, подходит любой OpenAI-совместимый endpoint)
LLM_BASE_URL OpenAI-совместимый шлюз из .env.example CB_EMBEDDING_BASE_URL, CB_LLM_BASE_URL, SD_LLM_BASE_URL, … — базовый URL /v1
LLM_MODEL модель из .env.example CB_LLM_MODEL (реранк и синтез памяти), SD_LLM_MODEL
MEMORY_EMBEDDING_MODEL text-embedding-3-small CB_EMBEDDING_MODEL; размерность фиксирована — CB_EMBEDDING_DIM=1536
MEMORY_EMBEDDING_PROVIDER fake CB_EMBEDDING_PROVIDER: fake (офлайн) или openai
MEMORY_LLM_PROVIDER echo CB_LLM_PROVIDER: echo (офлайн) или openai
MEMORY_RERANK_ENABLED false CB_RERANK_ENABLED — LLM-реранк результатов поиска (пул 20)
MEMORY_CONSOLE_ENABLED false CB_CONSOLE_ENABLED — встроенная консоль памяти

Включение настоящего провайдера:

AITUNNEL_API_KEY=<ключ провайдера>
LLM_BASE_URL=https://llm.example.com/v1
LLM_MODEL=<модель чата>
MEMORY_EMBEDDING_PROVIDER=openai
MEMORY_LLM_PROVIDER=openai
MEMORY_RERANK_ENABLED=true
docker compose up -d memory-service

Переиндексация после fake

Провайдер fake строит векторы хэшированием слов той же размерности, что и настоящая модель, поэтому схема их принимает, но семантический поиск по ним не работает. Данные, загруженные в память в режиме fake, после переключения на openai нужно переиндексировать. См. Загрузку знаний.

Таймаут эмбеддингов в compose — 60 секунд (CB_EMBEDDING_TIMEOUT): у шлюзов бывают редкие долгие ответы.

Память и доступ к ней

Переменная По умолчанию Смысл
MEMORY_IAM_ENABLED true CB_IAM_ENABLED — память принимает токены IAM audience memory-service параллельно со статическим ключом
MEMORY_POLICY_ENABLED false CB_POLICY_ENABLED — видимость памяти по principal через policy-service. Требует профиль policy (experimental) и service account памяти, который bootstrap заводит на шаге 7

Дополнительно compose фиксирует: CB_PII_PROTECTION=true, CB_DEFAULT_NAMESPACE=main, issuer и JWKS IAM, audience memory-service.

Control Plane

Переменная По умолчанию Смысл
CP_LEGACY_API_KEYS_ENABLED false Принимать ли статические ключи cp_…. В поставке — только IAM; true — аварийный режим
CP_CONTEXT_AUTH auto Чем ядро авторизуется в памяти: auto — service account из secrets/control-plane-iam.env, пока файла нет — MEMORY_API_KEY; api_key или iam — принудительно
CP_ENTITLEMENT_ENABLED false Проверять лицензии в Entitlement Service (профиль entitlement). Выключенная проверка видна в аудите как источник решения disabled
CP_AUTHZ_MODE local Источник доменной авторизации: local, shadow (спрашивать policy-service и журналировать расхождения, решать локально), policy (решает policy-service)
CP_CORS_ORIGINS [] JSON-список origin'ов для CORS API Control Plane (нужен, только если браузерный клиент ходит в API напрямую, а не через шлюз)

Жёстко заданы в compose.yml и из .env не меняются: CP_IAM_ENABLED=true, CP_IAM_AUDIENCE=control-plane, CP_IAM_ISSUER=${TAIMEN_PUBLIC_URL}/iam, CP_IAM_JWKS_URL (внутренний адрес IAM), CP_CONTEXT_PROVIDER=http, CP_CONTEXT_BASE_URL. Остальные настройки Control Plane (TTL claims и сессий, лимиты контекста, кэш bindings) имеют значения по умолчанию в коде и описаны в Конфигурации Control Plane.

Демо support-bot (профиль demo)

Переменная Смысл
SUPPORT_BOT_PAT PAT principal бота в Control Plane (эскалации создаются задачами). Обязателен для compose
SUPPORT_WORKSPACE_ID Workspace, куда бот заводит эскалации. Обязателен для compose
SUPPORT_MEMORY_NAMESPACE Namespace памяти с базой знаний демо

Порты на 127.0.0.1

Переменная По умолчанию Сервис
CP_HOST_PORT 18000 control-plane-api
MEMORY_HOST_PORT 18001 memory-service
IAM_HOST_PORT 18010 iam-service
ENT_HOST_PORT 18020 entitlement-service
POL_HOST_PORT 18040 policy-service
PLATFORM_API_HOST_PORT 18080 platform-api
KEYCLOAK_HOST_PORT 18081 keycloak
SUPPORT_HOST_PORT 18095 support-bot
PLATFORM_WEB_HOST_PORT 13000 platform-web

Bootstrap и make smoke ходят в сервисы именно по этим портам — при смене значения меняйте его в .env, а не в compose.yml.

Лимиты памяти контейнеров

Все mem_limit параметризованы. В .env.example закомментированы значения для машины 2 vCPU / 6 ГБ; остальные переменные можно добавить при необходимости.

Переменная По умолчанию Сервисы
PG_MEM_LIMIT 256m все PostgreSQL, кроме memory-db
MEMORY_DB_MEM_LIMIT 512m memory-db
MEMORY_MEM_LIMIT 512m memory-service
IAM_MEM_LIMIT 256m iam-service
CP_MEM_LIMIT 512m control-plane-api
CP_WORKER_MEM_LIMIT 256m control-plane-worker, context-adapter
KEYCLOAK_MEM_LIMIT 768m keycloak
PLATFORM_API_MEM_LIMIT, PLATFORM_WEB_MEM_LIMIT 512m platform-api, platform-web
MINIO_MEM_LIMIT, REDIS_MEM_LIMIT 256m, 128m minio, platform-redis
ENT_MEM_LIMIT, POL_MEM_LIMIT, OPENFGA_MEM_LIMIT 256m опциональные сервисы
SUPPORT_MEM_LIMIT 256m support-bot

Имена volumes

По умолчанию volume называется ${COMPOSE_PROJECT_NAME}_<имя>. Переменные VOLUME_CONTROL_PLANE_DB, VOLUME_IAM_DB, VOLUME_MEMORY_DB, VOLUME_CADDY_DATA, VOLUME_CADDY_CONFIG, VOLUME_PLATFORM_DB, VOLUME_PLATFORM_REDIS, VOLUME_PLATFORM_MINIO, VOLUME_REALM_IMPORT, VOLUME_SUPPORT_DATA, VOLUME_ENTITLEMENT_DB, VOLUME_POLICY_DB позволяют указать уже существующие volumes — например, при переводе стенда, поднятого раньше другими compose- файлами, на корневой compose.yml без потери данных.

Сборка образов

Переменная По умолчанию Смысл
IMAGE_PREFIX, IMAGE_TAG taimen, local имя и тег собираемых образов (${IMAGE_PREFIX}/control-plane:${IMAGE_TAG})
CP_BUILD_CONTEXT, MEMORY_BUILD_CONTEXT, IAM_BUILD_CONTEXT, POL_BUILD_CONTEXT, ENT_BUILD_CONTEXT, PLATFORM_BUILD_CONTEXT, PLATFORM_WEB_BUILD_CONTEXT, SUPPORT_BUILD_CONTEXT корень или каталог компонента контекст сборки; меняют, когда исходники релиза лежат в другом каталоге

Прочие переменные опциональных профилей

Переменная По умолчанию Смысл
NOTIFY_POSTGRES_PASSWORD — (обязательна) пароль БД notification-service, генерирует make secrets
ENT_SIGNING_KEY_ID local-dev kid ключа подписи Entitlement
APP_DISPLAY_NAME Taimen отображаемое имя в platform-api
EMAIL_FROM служебный адрес отправитель писем platform-api (транспорт — log)
RATE_LIMIT_PER_IP 300 лимит запросов в минуту на IP в platform-api
SERVICE_GATEWAY_UPSTREAMS JSON с control-plane upstream'ы шлюза platform-api: base_url, audience, scopes

Файлы, которые пишет bootstrap

Эти файлы подключаются к контейнерам через env_file с required: false, поэтому первый make up проходит и без них:

Файл Кем читается Содержимое
secrets/control-plane-iam.env control-plane-api, control-plane-worker, context-adapter CP_IAM_CLIENT_ID, CP_IAM_CLIENT_SECRET — service account ядра
secrets/memory-service-iam.env memory-service CB_IAM_CLIENT_ID, CB_IAM_CLIENT_SECRET — identity памяти для policy-service
secrets/policy-service-cp.env policy-worker POL_CONTROL_PLANE_TOKEN, POL_CP_CLIENT_ID, POL_CP_CLIENT_SECRET

После появления или замены такого файла перезапустите потребителя (docker compose up -d <сервис>) — env_file читается при создании контейнера.

Промышленный стенд: что поменять

Переменная Локально Промышленный стенд
TAIMEN_PUBLIC_URL http://taimen.localhost https://platform.example.com
TAIMEN_PUBLIC_HOST taimen.localhost platform.example.com
CADDYFILE ./deploy/caddy/Caddyfile.local Caddyfile с доменом и автоматическим TLS
KEYCLOAK_HOSTNAME_STRICT false true
MEMORY_EMBEDDING_PROVIDER / MEMORY_LLM_PROVIDER fake / echo openai / openai
*_MEM_LIMIT не заданы по ресурсам машины
COMPOSE_PROJECT_NAME, VOLUME_* по умолчанию по договорённости об именах

Подробно — Промышленное развёртывание и Периметр и TLS.

См. также