# Azure (/docs/deployment/environments/azure)



This page shows how the current `coreai-platform` Terraform layer is typically adapted for Azure.

Azure is included here not only because it is a common hyperscaler target, but also because it can be relevant in sovereign or region-constrained deployment discussions where teams need a controlled Azure-hosted environment with explicit DNS, certificate, registry, and storage choices.

It is based on the real variable structure under `coreai-platform/deployments/terraform/bsq-ai`, especially:

* `secrets.auto.tfvars.example`
* `variables.tf`
* `external-dns-helm.tf`
* `cert-manager-helm.tf`

The examples below are intentionally sanitized. They follow the real input shape, but all secret material and environment-specific identifiers are replaced with placeholders.

When This Page Applies [#when-this-page-applies]

Use this page when BullSequana AI is deployed into an Azure-backed Kubernetes environment and Azure is responsible for at least some of these concerns:

* DNS record management
* wildcard certificate issuance through DNS-01
* registry hosting through `ACR`
* cluster storage classes

What Usually Changes On Azure [#what-usually-changes-on-azure]

Compared with the generic deployment model, the Azure-specific parts usually are:

* `managed-csi` for `ReadWriteOnce` storage
* `azurefile-csi` for `ReadWriteMany` storage
* Azure DNS credentials for `external-dns`
* Azure DNS-01 inputs for `cert-manager`
* `ACR` registry host and Docker pull credentials

The rest of the platform shape stays the same: `common_config`, `git_config`, component scope, and service credentials still follow the shared BullSequana AI deployment model.

Minimal Azure-Shaped Example [#minimal-azure-shaped-example]

This is the practical starting point for an Azure deployment input file.

```hcl
common_config = {
  ingressclassname             = "nginx"
  imagepullsecret              = "registry-secret"
  base_domain                  = "<cluster-subdomain>.<dns-zone>"
  wildcard_cert_secret_name    = "acme-crt-secret-wildcard"
  rwo_storageclass             = "managed-csi"
  rwx_storageclass             = "azurefile-csi"
  realm_name                   = "dataplatform"
  registry                     = "<acr-name>.azurecr.io"
  registry_platform_repository = "coreai/platform"
  registry_backend_repository  = "coreai/backend"
  registry_portal_repository   = "coreai/portal"
  registry_helm_repository     = "coreai/helm"
  coreai_components            = true
  proai_components             = true
  enforce_affinity             = false
  internal_resolver            = "kube-dns"
}

git_config = {
  git_repo_url = "https://github.com/<org>/<platform-manifests-repo>.git"
  git_branch   = "<branch-name>"
  git_path     = "data-platform"
}

azure_sa_secret_name  = "azureconfigfile"
azure_dns_client_json = "<base64-encoded-azure-dns-json>"

azure_subscription_id      = "<azure-subscription-id>"
azure_resource_group_name  = "<dns-zone-resource-group>"
azure_hosted_zone_name     = "<dns-zone-name>"
azure_tenant_id            = "<azure-tenant-id>"
azure_client_id            = "<azure-client-id>"
azure_client_secret_base64 = "<base64-encoded-azure-client-secret>"

dockerconfigjson = "<base64-dockerconfigjson>"

custom_tls = {
  enabled = false
  ca_crt  = ""
  tls_crt = ""
  tls_key = ""
}
```

The Azure-Specific Inputs [#the-azure-specific-inputs]

`common_config` [#common_config]

For Azure, the most important common settings are usually:

* `base_domain`
* `rwo_storageclass`
* `rwx_storageclass`
* `registry`

Typical Azure storage values from the current example model are:

* `rwo_storageclass = "managed-csi"`
* `rwx_storageclass = "azurefile-csi"`

This matters because some platform components require shared storage semantics. In particular, the example deployment guidance explicitly calls out `ReadWriteMany` as important for shared model and document-processing workflows.

`git_config` [#git_config]

Azure does not change the Argo CD source model itself.

You still need:

* the Git repository URL
* the branch
* the manifest path

If these values are wrong, the Azure infrastructure can be perfectly healthy while the platform still fails to reconcile correctly.

Azure DNS For `external-dns` [#azure-dns-for-external-dns]

The current Azure deployment path configures `external-dns` with:

* `provider: azure`
* `secretName = azure_sa_secret_name`
* `resourceGroup = azure_resource_group_name`
* `domainFilters = [common_config.base_domain]`

That means three values must line up logically:

* `common_config.base_domain`: the domain suffix the platform will publish under
* `azure_resource_group_name`: the Azure resource group that owns the relevant DNS zone
* `azure_dns_client_json`: a base64-encoded Azure credentials JSON whose `resourceGroup` matches that DNS zone resource group

The current example file also documents an important nuance:

* for an individually created cluster, the DNS zone may live in the cluster's own child-zone resource group
* for ephemeral clusters, the workflow may generate the Azure DNS JSON dynamically for the cluster-specific zone resource group

So do not treat `azure_resource_group_name` as a fixed global Azure value. It must match the resource group that owns the DNS zone you actually expect `external-dns` to manage.

Azure DNS-01 For `cert-manager` [#azure-dns-01-for-cert-manager]

The Azure certificate path uses:

* `azure_subscription_id`
* `azure_resource_group_name`
* `azure_hosted_zone_name`
* `azure_tenant_id`
* `azure_client_id`
* `azure_client_secret_base64`

This is the part that enables wildcard and other DNS-validated certificates when `custom_tls.enabled = false` and the platform relies on DNS-driven issuance.

Operationally:

* `azure_hosted_zone_name` is the DNS zone cert-manager should solve against
* `azure_resource_group_name` is the resource group where that zone exists
* `azure_client_secret_base64` is stored as a Kubernetes secret payload for the Azure client secret used by the solver

Azure Container Registry [#azure-container-registry]

The current Azure deployment path also assumes the registry can be hosted in `ACR`.

The important inputs are:

* `common_config.registry = "<acr-name>.azurecr.io"`
* the repository prefixes such as `coreai/platform`, `coreai/backend`, `coreai/portal`, and `coreai/helm`
* `dockerconfigjson` for image pull authentication

This lets the deployment automation point platform images and Helm-related artifacts at the Azure-hosted registry path.

`azure_dns_client_json` Shape [#azure_dns_client_json-shape]

The example file documents the expected payload shape for `azure_dns_client_json`.

It is a base64-encoded JSON object like this:

```json
{
  "tenantId": "<azure-tenant-id>",
  "subscriptionId": "<azure-subscription-id>",
  "resourceGroup": "<dns-zone-resource-group>",
  "aadClientId": "<azure-client-id>",
  "aadClientSecret": "<azure-client-secret>"
}
```

Example generation pattern:

```bash
echo -n '{"tenantId":"<tenant-id>","subscriptionId":"<subscription-id>","resourceGroup":"<dns-zone-rg>","aadClientId":"<client-id>","aadClientSecret":"<client-secret>"}' | base64 -w 0
```

The important point is not the shell snippet itself. It is that the embedded `resourceGroup` must match the DNS zone resource group the platform will manage.

Recommended Azure Baseline [#recommended-azure-baseline]

For a straightforward Azure deployment, start with this baseline:

1. Use `managed-csi` for `RWO`.
2. Use `azurefile-csi` for `RWX`.
3. Use an `ACR` hostname for `common_config.registry`.
4. Use `external-dns` with Azure credentials scoped to the DNS zone resource group.
5. Use Azure DNS-01 inputs for `cert-manager` unless custom TLS material is provided directly.
6. Keep the shared repository prefixes:
   `coreai/platform`, `coreai/backend`, `coreai/portal`, `coreai/helm`.

Safe Handling Rules [#safe-handling-rules]

The real `secrets.auto.tfvars` file contains sensitive values.

Do not copy any live secret values into docs, commits, tickets, or shared examples.

Use these sources instead when preparing customer or internal documentation:

* `secrets.auto.tfvars.example` for variable shape and comments
* sanitized placeholder values for examples
* your actual secret-management process for live credentials

Validation Checklist [#validation-checklist]

Before applying an Azure deployment, validate these questions:

1. Does the cluster actually expose `managed-csi` and `azurefile-csi`, or do those names need adjusting?
2. Does `common_config.base_domain` match the domain suffix you want platform ingresses to publish under?
3. Does `azure_resource_group_name` point to the resource group that owns the DNS zone?
4. Does `azure_dns_client_json` embed the same DNS zone resource group internally?
5. Does `azure_hosted_zone_name` match the hosted zone cert-manager should solve against?
6. Is `dockerconfigjson` valid for the chosen `ACR` host?
7. Is the Git source path correct for the manifests Argo CD should reconcile?

Related Pages [#related-pages]

* [Configuration Model](/docs/deployment/configuration-model)
* [Before You Start](/docs/deployment/setup-context)
* [Deployment Sequence](/docs/deployment/playbooks/deployment-sequence)
* [Files & RAG](/docs/coreai/files-rag)
