Skip to main content
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 and we’ll work the install with you.
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

ResourceNotes
Resource groupHolds the AKS cluster, database, storage account, and networking
Virtual network + subnetSubnet for AKS nodes; private endpoints for Postgres and Blob recommended
AKS clusterKubernetes 1.28+
Azure Database for PostgreSQL (Flexible Server)Postgres 15+, private access
Azure Storage Account + Blob containerLakehouse data
Azure AD app (optional)For OIDC SSO via Entra ID

Prerequisites

1

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>).
2

Local tooling

Install the following on the machine you’ll run az and definite from:
ToolVersionCheck
azrecentaz version
kubectl1.28+kubectl version --client
helm3.12+helm version
3

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).
4

Definite license key

On-prem Definite requires a license key issued by Definite. It looks like onprem_ followed by a long hex string, and you reference it from config.yaml. If you do not have one yet, email hello@definite.app. Until the license is activated the deployment comes up unlicensed and returns HTTP 403 on every product API route.

Phase 1: Provision Azure infrastructure

Set up shared env vars first:
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

az group create --name "$RG" --location "$LOCATION"

2. Create the AKS cluster

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)

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

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

curl -fsSL https://storage.googleapis.com/definite-public/definite-onprem/install.sh | sh
definite version

2. Bootstrap cluster prerequisites

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

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 config: minimal-aks.yaml. The shape:
deployment:
  name: definite
  namespace: definite
  hostname: <your-hostname>
  tls: cert_manager

license:
  key: !env LICENSE_KEY              # your Definite-issued onprem_... key

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
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.
For the full list of knobs, see the config reference in Definite’s built-in docs.

5. Export secrets

export LICENSE_KEY="onprem_..."                            # your Definite-issued license key
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

definite doctor --config config.yaml
definite init --config config.yaml
If your Postgres Flexible Server is on private access (the recommended production setup), definite doctor and the definite init preflight cannot reach it from a laptop and will fail the Postgres check. On v0.0.8, pass --skip-preflight to definite init for laptop installs and run doctor from a pod inside the cluster instead.
init renders the bundled Helm chart and runs helm upgrade --install. Watch the rollout:
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.
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.).
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.)
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:
definite status   --config config.yaml
definite logs api --follow
definite upgrade  --config config.yaml
definite license  status
definite run maintenance stats
Definite’s built-in docs include a full CLI reference.

Phase 3: Teardown

# Trigger Kubernetes to delete the Azure Standard Load Balancer cleanly
# before the resource group goes away.
kubectl delete svc ingress-nginx-controller -n ingress-nginx --ignore-not-found

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. Deleting the ingress Service first lets Kubernetes release the cloud LB cleanly; az group delete will pick up anything you miss, but the explicit order avoids a stuck LB you’d otherwise have to clean up by hand.

Support

This install path is actively being matured. For issues or questions, contact hello@definite.app. If you’re planning an Azure install, we’d love to be in the room: design-partner support is free.