# Azure deployment

> Source: https://docs.clonepartner.com/deployment/azure/

The Azure topology provisions one isolated Envoy environment inside a resource group. It uses the same control-plane and executor roles as remote Docker, with managed Azure services for ingress, state, files, images, and secrets.

```mermaid Azure topology
flowchart TD
  user["Browser"] --> cp["Control plane<br/>external HTTPS ingress"]
  cp <--> ex["Executor<br/>internal ingress"]
  cp --> sql["Azure SQL"]
  cp --> kv["Azure Key Vault"]
  ex --> blob["Azure Blob Storage"]
  acr["Azure Container Registry"] --> cp
  acr --> ex
```

## Resources

The supplied Terraform module creates:

- an Azure resource group;
- a Container Apps environment;
- external control-plane and internal executor Container Apps;
- Azure Container Registry, or access to a configured source registry;
- an Azure Storage account and data container;
- an Azure SQL logical server and database;
- Azure Key Vault when selected as the secret provider.

Resource names such as the registry, storage account, SQL server, and vault must be globally unique.

## Requirements

- Contributor access to the target Azure subscription.
- Terraform for the module workflow, or Azure CLI for the shell workflow.
- An Envoy image already available to the selected ACR path, or source/build access supplied through your ClonePartner delivery channel.
- Three deployment secrets: application encryption key, executor key, and SQL administrator password.
- Optional OAuth and Anthropic credentials for SSO and the AI assistant.

## Terraform workflow

From the Envoy delivery repository:

```bash
cd terraform/azure
cp terraform.tfvars.example terraform.tfvars
```

Fill at least:

```hcl
envoy_encryption_key = "<high-entropy-key>"
envoy_executor_key   = "<different-high-entropy-key>"
sql_admin_password   = "<strong-password>"
image_tag            = "<tag-that-exists-in-acr>"
```

Then review and apply:

```bash
terraform init
terraform plan
terraform apply
```

The outputs include the control-plane HTTPS URL, executor internal FQDN, image reference, SQL FQDN, storage account, and Key Vault URL.

:::callout{type="warning"}
`terraform.tfvars` contains secrets. Keep it out of version control and use your organization's protected Terraform state and secret-injection workflow.
:::

## Shell deployment workflow

The alternative Azure CLI script reads `.env.deploy` when present:

```bash
./scripts/deploy-azure.sh
```

It supports:

```bash
FORCE_DEPLOY=true ./scripts/deploy-azure.sh
DEPLOY_SCOPE=cp ./scripts/deploy-azure.sh
DEPLOY_SCOPE=ex ./scripts/deploy-azure.sh
```

The first run requires `ENVOY_ENCRYPTION_KEY`, `ENVOY_EXECUTOR_KEY`, and `SQL_ADMIN_PASSWORD`. Subsequent script runs reuse deployed secrets when they are not supplied again.

## State and logs

The supplied Azure configuration uses Microsoft SQL Server for application state and run logs. The control plane connects with encrypted SQL transport and a configurable pool.

Azure SQL is also available as a task connector, but application state and business data remain separate concerns. Do not let tasks modify Envoy's own state tables.

## Key Vault

With `secrets.default: azure_key_vault`, connector configurations and TOTP secrets are stored in the vault. The database stores only provider and handle metadata.

The control plane uses its managed identity. It needs permission to list, read, create, update, and delete the secrets Envoy owns. The UI can then:

- write a directly entered secret to Key Vault;
- list secret names for a vault-backed field;
- save a reference without exposing the selected value.

Use a dedicated vault for each environment when practical, even though `name_prefix` can partition names.

## OAuth redirect URIs

Register the final control-plane URL with the identity provider:

```text
https://<control-plane-fqdn>/api/auth/oauth/microsoft/callback
https://<control-plane-fqdn>/api/auth/oauth/google/callback
```

Leave a provider's client ID empty to keep it disabled.

## Executor availability

The current Terraform module declares the executor with internal ingress and a replica range of zero to one. Validate the effective Container Apps scaling behavior for your environment before relying on automatic activation from zero; dispatch requires a reachable executor. Keep at least one executor available if no tested scaling rule starts it in time.

## Post-deploy checks

1. Open the Terraform `control_plane_url`.
2. Complete the first administrator setup.
3. Verify that the executor registers.
4. Create a connector using a vault reference and test it.
5. Run a bounded task and confirm logs and metrics reach Azure SQL.
6. Confirm Azure SQL backup retention and Key Vault recovery settings meet your policy.

For the component boundary, see [Control plane and executors](/deployment/control-plane-and-executors). For product security behavior, see [RBAC, secrets, and hardening](/security/rbac-secrets-and-hardening).
