Конфигурация .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
Переиндексация после 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.