> ## Documentation Index
> Fetch the complete documentation index at: https://docs.definite.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Install on Azure

> Preliminary guide for running Definite on AKS, Azure Database for PostgreSQL, and Azure Blob Storage.

<Warning>
  **This install path has not been fully validated end to end.** The shape below is the same one customers have run on AWS and GCP, and the on-prem CLI ships an Azure-aware `config.yaml` schema and an Azure example. The guide is preliminary; we have not yet completed a clean-room Azure install. If you want to be a design partner for the Azure path, reach out to [hello@definite.app](mailto:hello@definite.app) and we'll work the install with you.
</Warning>

This page sketches an on-prem Definite install on Microsoft Azure: AKS for the cluster, Azure Database for PostgreSQL Flexible Server for the application database, and Azure Blob Storage for the lakehouse.

## What you'll create

| Resource                                        | Notes                                                                     |
| ----------------------------------------------- | ------------------------------------------------------------------------- |
| Resource group                                  | Holds the AKS cluster, database, storage account, and networking          |
| Virtual network + subnet                        | Subnet for AKS nodes; private endpoints for Postgres and Blob recommended |
| AKS cluster                                     | Kubernetes 1.28+                                                          |
| Azure Database for PostgreSQL (Flexible Server) | Postgres 15+, private access                                              |
| Azure Storage Account + Blob container          | Lakehouse data                                                            |
| Azure AD app (optional)                         | For OIDC SSO via Entra ID                                                 |

***

## Prerequisites

<Steps>
  <Step title="Azure access">
    A subscription where you have permission to create AKS, Postgres Flexible Server, and Storage Accounts. The `az` CLI must be authenticated (`az login`) and the subscription set (`az account set --subscription <your-subscription-id>`).
  </Step>

  <Step title="Local tooling">
    Install the following on the machine you'll run `az` and `definite` from:

    | Tool      | Version | Check                      |
    | --------- | ------- | -------------------------- |
    | `az`      | recent  | `az version`               |
    | `kubectl` | 1.28+   | `kubectl version --client` |
    | `helm`    | 3.12+   | `helm version`             |
  </Step>

  <Step title="LLM access">
    Decide which LLM provider Fi will use. **Azure OpenAI** is the most common choice for Azure deployments because it lives in the same subscription. Anthropic, Bedrock, and Vertex are also supported. If you go with Azure OpenAI, make sure you've requested model access and created a deployment (the URL is your `llm.endpoint`).
  </Step>
</Steps>

***

## Phase 1: Provision Azure infrastructure

Set up shared env vars first:

```bash theme={null}
export RG="<your-resource-group>"
export LOCATION="<your-region>"               # e.g. eastus
export CLUSTER_NAME="<your-cluster-name>"     # e.g. definite
export PG_NAME="<your-pg-server>"             # e.g. acme-pg
export PG_USER="definite"
export STORAGE_ACCOUNT="<your-storage-acct>"  # lowercase, 3-24 chars
export BLOB_CONTAINER="definite"
```

### 1. Create the resource group

```bash theme={null}
az group create --name "$RG" --location "$LOCATION"
```

### 2. Create the AKS cluster

```bash theme={null}
az aks create \
  --resource-group "$RG" \
  --name "$CLUSTER_NAME" \
  --node-count 3 \
  --enable-managed-identity \
  --generate-ssh-keys

az aks get-credentials --resource-group "$RG" --name "$CLUSTER_NAME"
kubectl get nodes
```

### 3. Create Azure Database for PostgreSQL (Flexible Server)

```bash theme={null}
az postgres flexible-server create \
  --resource-group "$RG" \
  --name "$PG_NAME" \
  --location "$LOCATION" \
  --version 15 \
  --admin-user "$PG_USER" \
  --admin-password "<your-postgres-password>" \
  --tier GeneralPurpose \
  --sku-name Standard_D2ds_v4

az postgres flexible-server db create \
  --resource-group "$RG" \
  --server-name "$PG_NAME" \
  --database-name definite
```

For production, place the Flexible Server in a delegated subnet on the same VNet as the AKS cluster (private access) so the cluster can reach it without traversing the public internet.

### 4. Create a Storage Account + Blob container

```bash theme={null}
az storage account create \
  --resource-group "$RG" \
  --name "$STORAGE_ACCOUNT" \
  --location "$LOCATION" \
  --sku Standard_LRS \
  --kind StorageV2 \
  --allow-blob-public-access false

# Grab a storage account key (the lakehouse uses a single shared key, not an
# HMAC pair like S3/GCS).
STORAGE_KEY=$(az storage account keys list \
  --resource-group "$RG" \
  --account-name "$STORAGE_ACCOUNT" \
  --query '[0].value' --output tsv)

az storage container create \
  --account-name "$STORAGE_ACCOUNT" \
  --name "$BLOB_CONTAINER" \
  --account-key "$STORAGE_KEY"
```

### 5. (If using Entra ID SSO) Register an app

Create an Azure AD app for OIDC, set `https://<your-hostname>/auth/callback` as a redirect URI, and create a client secret. You'll plug the tenant ID, client ID, and client secret into `auth.mode: oidc` in `config.yaml`.

***

## Phase 2: Install Definite with the `definite` CLI

### 1. Install the CLI

```bash theme={null}
curl -fsSL https://storage.googleapis.com/definite-public/definite-onprem/install.sh | sh
definite version
```

### 2. Bootstrap cluster prerequisites

```bash theme={null}
definite bootstrap --acme-email you@yourcompany.com
```

This installs an ingress controller, cert-manager, the `letsencrypt-prod` ClusterIssuer, and the agent-sandbox CRDs the Fi runtime needs.

### 3. Discover the load balancer IP

```bash theme={null}
kubectl get svc ingress-nginx-controller -n ingress-nginx \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```

Use that IP either as a `nip.io` host for demos, or create an A record in your DNS provider pointing your chosen hostname at it.

### 4. Build `config.yaml`

Start from the AKS example in the repo: [`examples/minimal-aks.yaml`](https://github.com/definite-app/definite-onprem/blob/main/examples/minimal-aks.yaml). The shape:

```yaml theme={null}
deployment:
  name: definite
  namespace: definite
  hostname: <your-hostname>
  tls: cert_manager

postgres:
  url: postgres://definite:${POSTGRES_PASSWORD}@<pg-server>.postgres.database.azure.com:5432/definite

object_store:
  type: azure
  account: <your-storage-account>
  container: definite
  credentials:
    env: AZURE_STORAGE_KEY

lakehouse:
  prefix: lake/
  storage:
    size: 50Gi
    storage_class_name: managed-csi-premium

auth:
  mode: oidc                         # or `local` for username/password auth
  issuer: https://login.microsoftonline.com/<your-tenant-id>/v2.0
  client_id: <your-azure-ad-client-id>
  client_secret:
    env: OIDC_CLIENT_SECRET

llm:
  provider: azure_openai
  endpoint: https://<your-aoai-resource>.openai.azure.com
  deployment: <your-aoai-deployment>
  api_key:
    env: AZURE_OPENAI_API_KEY

resources:
  api:
    replicas: 2
    cpu: "1"
    memory: 2Gi
  lakehouse:
    replicas: 1
    cpu: "4"
    memory: 16Gi
```

<Note>
  Azure uses a single shared storage key (not an HMAC pair). Pull it from the Storage Account's "Access keys" blade, or via `az storage account keys list` as shown above.
</Note>

For the full list of knobs, see the [config reference](https://github.com/definite-app/definite-onprem/blob/main/docs/config.md).

### 5. Export secrets

```bash theme={null}
export POSTGRES_PASSWORD="<your-postgres-password>"
export AZURE_STORAGE_KEY="<storage-key-from-step-4>"
export AZURE_OPENAI_API_KEY="<your-aoai-api-key>"
export OIDC_CLIENT_SECRET="<your-azure-ad-client-secret>"  # only if auth.mode: oidc
```

### 6. Preflight and deploy

```bash theme={null}
definite doctor --config config.yaml
definite init --config config.yaml
```

`init` renders the bundled Helm chart and runs `helm upgrade --install`. Watch the rollout:

```bash theme={null}
definite status --config config.yaml
definite logs api --follow
```

### 7. Set the initial admin user

The chart does not auto-create an initial admin. After `definite init` returns successfully and the pods are `Ready`, set `INITIAL_ADMIN_EMAIL` and `INITIAL_ADMIN_PASSWORD` on the api Deployment; the api creates the admin record on its next start.

```bash theme={null}
ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)
kubectl set env deploy/definite-api -n definite \
  INITIAL_ADMIN_EMAIL=<your-email> \
  INITIAL_ADMIN_PASSWORD="$ADMIN_PASSWORD"
kubectl rollout status deploy/definite-api -n definite
echo "Admin password: $ADMIN_PASSWORD"
```

Save the password somewhere safe (1Password, Vault, etc.).

<Warning>
  A subsequent `helm upgrade` or `definite upgrade` clears these env vars, so re-set them after any upgrade. (Tracking issue: chart-managed initial admin so this step goes away.)
</Warning>

When cert-manager has issued a cert, open your hostname in a browser and log in with the admin email and password from above.

***

## Known limitations on Azure

A few things are worth flagging up front; these are why this guide is labeled preliminary:

* **`definite run load` (file upload via the CLI)** is documented as **not supported on Azure** in v1; S3, GCS, and MinIO backends are. Browser-based Drive uploads still work via the configured Storage Account.
* **`definite doctor`** validates Azure config *shape* but does not yet round-trip a real `PutBlob` against your storage account. Confirm the storage key has write access before deploying.
* **Workload Identity / Entra-bound credentials** for the lakehouse are not yet wired in; the storage account key is the supported path today.

***

## Day-2 operations

Same CLI as AWS and GCP:

```bash theme={null}
definite status   --config config.yaml
definite logs api --follow
definite upgrade  --config config.yaml
definite license  show
definite run maintenance stats
```

See the [CLI reference](https://github.com/definite-app/definite-onprem/blob/main/docs/cli.md).

***

## Phase 3: Teardown

```bash theme={null}
az group delete --name "$RG" --yes
```

Deleting the resource group removes the AKS cluster, Postgres server, storage account, and everything else in one shot. Snapshot or export anything you care about first.

***

## Support

This install path is actively being matured. For issues or questions, contact [hello@definite.app](mailto:hello@definite.app) or open an issue on [definite-app/definite-onprem](https://github.com/definite-app/definite-onprem/issues). If you're planning an Azure install, we'd love to be in the room: design-partner support is free.
