# Configuration Model (/docs/deployment/configuration-model)



This page explains how deployment configuration is structured in the `bsqai-platform` CLI.

Configuration is split into two layers: a global `platform.toml` file that defines platform-wide settings, and per-component `variables.toml` files that define each component's identity, resources, secrets, and SSO enrollment. Environment variables can override any value at any layer.

Configuration layers [#configuration-layers]

1\. Global platform defaults [#1-global-platform-defaults]

`platform.toml` is located at `src/manifests/source/platform.toml`. It defines the shared foundation used across all platform applications.

| Section        | Purpose                                                                                         |
| -------------- | ----------------------------------------------------------------------------------------------- |
| `[common]`     | Base domain, registry, storage classes, image pull secret, realm name, affinity enforcement     |
| `[git]`        | Manifests repository URL, branch, and path for ArgoCD reconciliation                            |
| `[custom_tls]` | Optional TLS material (CA cert, certificate, key) when DNS-based issuance is not used           |
| `[proxy]`      | HTTP/HTTPS proxy and no-proxy settings                                                          |
| `[azure]`      | Azure-specific: subscription, DNS, tenant, client credentials                                   |
| `[gcp]`        | GCP-specific: service account namespaces                                                        |
| `[apps]`       | Sync wave ordering for parent ArgoCD Applications (common=1, coreai=2, proai=3)                 |
| `[default]`    | Default sizing values (CPU, memory, replicas) applied when a component does not specify its own |

2\. Environment files [#2-environment-files]

Environment variables are loaded in three layers, from lowest to highest priority:

1. **`platform.env`** — shared settings committed alongside the deployment (lowest priority)
2. **`local.env`** — personal overrides, gitignored (overrides `platform.env`)
3. **OS environment** — always wins (highest priority, used mainly in CI/CD)

Both `.env` files live at the repository root. They are loaded automatically when the CLI starts.

3\. Per-component configuration [#3-per-component-configuration]

Each component has a `variables.toml` file inside its source directory under `src/manifests/source/<group>/<component>/`. The file is organized into TOML tables:

```toml
[component]
name          = "keycloak"
namespace     = "keycloak"
version       = "26.5.2"
format        = "helm"
chart_name    = "keycloak"
chart_version = "18.10.0"
release_name  = "keycloak"
url_prefix    = "iam"
parent_app    = "common"
sync_wave     = "7"
sync_options  = "- SkipDryRunOnMissingResource=true"
sync_annotations = ""

[database]
postgresql_name     = "keycloak"
postgresql_owner    = "keycloak"
postgresql_password = {value = "", secret = true}
```

The `[component]` table is required and defines identity, chart coordinates, namespace, and ArgoCD sync behavior. Additional tables (`[database]`, `[sso]`, `[auth]`, `[server]`, etc.) are component-specific and become template variables prefixed with the table name.

4\. Variable resolution [#4-variable-resolution]

When the CLI loads a component, it resolves each variable through this chain:

1. **Environment variable override** — if an env var matching `COMPONENTNAME_TABLENAME_KEY` (uppercased, hyphens replaced with underscores) exists, it wins
2. **Explicit TOML value** — a non-empty value in `variables.toml` is used as-is
3. **Generator** — if the variable has a `generate` key (e.g., `generate = "s3_access_key_id"`), a value is generated automatically when the TOML value is empty
4. **Global default fallback** — for flagged values (`secret = true`, `token = true`, `cert = true`), the CLI falls back to `GLOBAL_SECRET_DEFAULT`, `GLOBAL_TOKEN_DEFAULT`, or `GLOBAL_CERT_DEFAULT` environment variables
5. **Empty string** — if none of the above produce a value

Type coercion is automatic. The CLI matches the type of the TOML reference value: booleans (`"true"`/`"false"`), integers, and floats are coerced from string env vars. Complex types (dicts and lists) must be provided as JSON-encoded strings when overriding from an environment variable or `.env` file.

Secrets management [#secrets-management]

Secrets in `variables.toml` use a metadata wrapper instead of a plain value:

```toml
postgresql_password = {value = "", secret = true}
```

The `secret = true` flag tells the CLI that the value is sensitive. When the rendered template produces a Kubernetes `Secret` manifest, the CLI automatically seals it with `kubeseal` before writing the output. The sealed secret can be safely stored in Git.

Three flag types exist:

| Flag            | Fallback env var        | Typical use                 |
| --------------- | ----------------------- | --------------------------- |
| `secret = true` | `GLOBAL_SECRET_DEFAULT` | Passwords, client secrets   |
| `token = true`  | `GLOBAL_TOKEN_DEFAULT`  | API tokens, registry tokens |
| `cert = true`   | `GLOBAL_CERT_DEFAULT`   | Certificate material        |

Auto-generated values are also supported. S3 access keys use built-in generators:

```toml
access_key_id     = {value = "", generate = "s3_access_key_id"}
secret_access_key = {value = "", generate = "s3_secret_access_key"}
```

When the value is empty and no environment override exists, the generator produces a cryptographically random credential.

SSO scope [#sso-scope]

All platform components with a user-facing endpoint are enrolled into Keycloak for single sign-on. This is controlled per component through an `[sso]` table in `variables.toml`.

How it works [#how-it-works]

When a component has `[sso] enabled = true`, the CLI generates:

* an SSO configuration secret containing the OIDC client definition, groups, and roles
* a **setup job** that registers the component with Keycloak before deployment (uses a negative sync wave to run before the component)
* a **PostDelete cleanup job** that removes the Keycloak client when the component is deleted

When `enabled` is `false` or the `[sso]` table is absent, none of these resources are created.

SSO configuration structure [#sso-configuration-structure]

The `[sso]` table defines the full OIDC client registration:

```toml
[sso]
enabled       = true
client_id     = "grafana"
client_secret = {value = "", secret = true}
description   = "Grafana OAuth client"

default_scope                = ["openid", "profile", "email"]
standard_flow_enabled        = true
direct_access_grants_enabled = true
service_accounts_enabled     = false
redirect_uris                = ["*"]
groups                       = [{name = "Grafana-Viewer"}]
roles                        = []
```

Client secrets left empty are auto-generated. Keycloak-side client secrets are stored centrally in the Keycloak component's `[clients]` table and distributed via sealed secrets.

Components with SSO support [#components-with-sso-support]

| Layer   | Components                                                                     |
| ------- | ------------------------------------------------------------------------------ |
| Runtime | Grafana, PgAdmin, Rook Ceph RGW, ArgoCD                                        |
| CoreAI  | Portal, LLM Backend (CoreAI API), MLflow, Temporal, Model Installer, LiteLLM   |
| Data    | Superset, Strimzi (Kafka), Airbyte (via OAuth2 Proxy), Attu (via OAuth2 Proxy) |

Keycloak enroll credentials [#keycloak-enroll-credentials]

The setup and cleanup jobs authenticate against Keycloak using a dedicated enroll user. The password for this user is controlled by `[auth] enroll_password` in the Keycloak component's `variables.toml`. When left empty, a random password is generated.

For a deeper explanation of how the enrollment mechanism works, see the [Keycloak component page](/docs/runtime/components/keycloak).

Environment-specific settings [#environment-specific-settings]

Some settings only apply in specific deployment environments.

Azure [#azure]

```toml
[azure]
enabled             = true
subscription_id     = ""
dns_resource_group  = ""
hosted_zone_name    = ""
tenant_id           = ""
client_id           = ""
client_secret_b64   = ""
dns_client_json     = ""
```

These control `external-dns` zone ownership and `cert-manager` DNS-01 challenge solving in Azure.

GCP [#gcp]

```toml
[gcp]
enabled                    = false
gcloud_svc_acct_namespaces = ""
```

Proxy [#proxy]

```toml
[proxy]
no_proxy_url = ""
http_url     = ""
https_url    = ""
```

Set these when the cluster requires an outbound proxy for internet access.

Custom TLS [#custom-tls]

```toml
[custom_tls]
enabled = false
ca_crt  = ""
crt     = ""
key     = ""
```

Used when certificates are provided directly instead of issued through DNS automation.

Safe review checklist [#safe-review-checklist]

Before applying a deployment, validate:

1. Does the target environment have the required storage classes (`rwo_storageclass`, `rwx_storageclass`)?
2. Does `base_domain` match a DNS zone the platform can manage?
3. Is the container registry reachable from the cluster?
4. Is `[git]` pointing to the correct manifests repository and branch?
5. Is the certificate model clear: custom TLS material or DNS-driven issuance?
6. Are only the needed platform tiers enabled?

Minimal input shape [#minimal-input-shape]

```toml
[common]
base_domain                  = "<platform-domain>"
rwo_storageclass             = "<rwo-storage-class>"
rwx_storageclass             = "<rwx-storage-class>"
registry_name                = "<registry-host>"
registry_platform_repository = "coreai/platform"
registry_backend_repository  = "coreai/backend"
registry_portal_repository   = "coreai/portal"
registry_helm_repository     = "coreai/helm"
realm_name                   = "dataplatform"

[git]
repo_url = "<manifests-repository-url>"
branch   = "<branch>"
path     = "platform"

[custom_tls]
enabled = false
```

Use that structure as the baseline, then add only the environment-specific and component-specific inputs required by the deployment target.

Related pages [#related-pages]

* [Platform CLI](/docs/deployment/platform-cli)
* [GitOps workflow](/docs/deployment/gitops-workflow)
* [Component anatomy](/docs/deployment/component-anatomy)
* [Keycloak](/docs/runtime/components/keycloak)
