Deploy Keeptrusts on Azure
This guide covers a production deployment of Keeptrusts on Microsoft Azure using Azure Container Instances (ACI) or Azure Kubernetes Service (AKS), Azure Database for PostgreSQL, Application Gateway, Azure Monitor, and Blob Storage for exports.
Use this page when
- You are deploying the Keeptrusts gateway and API to Microsoft Azure.
- You need AKS or ACI deployment patterns with Azure Database for PostgreSQL.
- You want to use Managed Identity for secrets access instead of static credentials.
- You need to configure Application Gateway, Azure Monitor, and Blob Storage for Keeptrusts.
Primary audience
- Primary: Technical Engineers
- Secondary: AI Agents, Technical Leaders
Architecture overview
Internet
→ Azure Front Door / Application Gateway
→ AKS Cluster / ACI Container Groups
→ Keeptrusts Gateway (port 41002)
→ Keeptrusts API (port 8080)
→ Worker containers (export, lifecycle, config)
→ Azure Database for PostgreSQL Flexible Server (private subnet)
→ Azure Blob Storage (export artifacts)
→ Azure Key Vault (secrets)
→ Azure Monitor (logs, metrics, alerts)
Prerequisites
- Azure subscription with Contributor access
- Azure CLI (
az) installed and authenticated - Keeptrusts container images pushed to Azure Container Registry (ACR)
- A resource group for all Keeptrusts resources
az login
az group create --name keeptrusts-rg --location eastus
Container Registry
Push Keeptrusts images to ACR before deploying compute resources.
az acr create --resource-group keeptrusts-rg \
--name keeptrustscr --sku Standard
az acr login --name keeptrustscr
docker tag keeptrusts-api:latest keeptrustscr.azurecr.io/keeptrusts-api:latest
docker tag keeptrusts-gateway:latest keeptrustscr.azurecr.io/keeptrusts-gateway:latest
docker push keeptrustscr.azurecr.io/keeptrusts-api:latest
docker push keeptrustscr.azurecr.io/keeptrusts-gateway:latest
Virtual network
Create a VNET with subnets for compute, database, and Application Gateway.
resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
name: 'keeptrusts-vnet'
location: resourceGroup().location
properties: {
addressSpace: { addressPrefixes: ['10.0.0.0/16'] }
subnets: [
{ name: 'aks-subnet', properties: { addressPrefix: '10.0.1.0/24' } }
{ name: 'db-subnet', properties: {
addressPrefix: '10.0.2.0/24'
delegations: [{ name: 'postgres', properties: { serviceName: 'Microsoft.DBforPostgreSQL/flexibleServers' } }]
}
}
{ name: 'appgw-subnet', properties: { addressPrefix: '10.0.3.0/24' } }
]
}
}
Azure Database for PostgreSQL
az postgres flexible-server create \
--resource-group keeptrusts-rg \
--name keeptrusts-db \
--location eastus \
--admin-user ktadmin \
--admin-password "${POSTGRES_PASSWORD}" \
--sku-name Standard_B2s \
--tier Burstable \
--storage-size 128 \
--version 15 \
--vnet keeptrusts-vnet \
--subnet db-subnet \
--private-dns-zone keeptrusts-dns.postgres.database.azure.com
az postgres flexible-server db create \
--resource-group keeptrusts-rg \
--server-name keeptrusts-db \
--database-name keeptrusts
Set the DATABASE_URL for your containers:
DATABASE_URL=postgres://ktadmin:${POSTGRES_PASSWORD}@keeptrusts-db.postgres.database.azure.com:5432/keeptrusts?sslmode=require
Managed Identity
Use a User-Assigned Managed Identity so containers authenticate to Key Vault, ACR, and Blob Storage without storing credentials.
az identity create --resource-group keeptrusts-rg --name keeptrusts-identity
# Grant ACR pull
IDENTITY_ID=$(az identity show -g keeptrusts-rg -n keeptrusts-identity --query principalId -o tsv)
ACR_ID=$(az acr show -n keeptrustscr --query id -o tsv)
az role assignment create --assignee "$IDENTITY_ID" --role AcrPull --scope "$ACR_ID"
Deploy with AKS
Create cluster
az aks create \
--resource-group keeptrusts-rg \
--name keeptrusts-aks \
--node-count 3 \
--node-vm-size Standard_D4s_v5 \
--network-plugin azure \
--vnet-subnet-id "/subscriptions/<sub>/resourceGroups/keeptrusts-rg/providers/Microsoft.Network/virtualNetworks/keeptrusts-vnet/subnets/aks-subnet" \
--enable-managed-identity \
--attach-acr keeptrustscr
az aks get-credentials -g keeptrusts-rg -n keeptrusts-aks
Kubernetes manifests
# keeptrusts-api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: keeptrusts-api
spec:
replicas: 2
selector:
matchLabels: { app: keeptrusts-api }
template:
metadata:
labels: { app: keeptrusts-api }
spec:
containers:
- name: api
image: keeptrustscr.azurecr.io/keeptrusts-api:latest
ports: [{ containerPort: 8080 }]
env:
- name: DATABASE_URL
valueFrom: { secretKeyRef: { name: keeptrusts-secrets, key: database-url } }
- name: KEEPTRUSTS_CORS_ALLOWED_ORIGINS
value: "https://console.yourdomain.com"
readinessProbe:
httpGet: { path: /healthz, port: 8080 }
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata: { name: keeptrusts-api-svc }
spec:
selector: { app: keeptrusts-api }
ports: [{ port: 8080, targetPort: 8080 }]
Deploy with ACI (simpler alternative)
For smaller deployments, use Azure Container Instances.
az container create \
--resource-group keeptrusts-rg \
--name keeptrusts-gateway \
--image keeptrustscr.azurecr.io/keeptrusts-gateway:latest \
--cpu 2 --memory 4 \
--ports 41002 \
--vnet keeptrusts-vnet \
--subnet aks-subnet \
--assign-identity keeptrusts-identity \
--environment-variables \
KEEPTRUSTS_API_URL=http://keeptrusts-api:8080 \
--secure-environment-variables \
KEEPTRUSTS_GATEWAY_TOKEN="${API_KEY}"
Application Gateway
az network application-gateway create \
--resource-group keeptrusts-rg \
--name keeptrusts-appgw \
--location eastus \
--vnet-name keeptrusts-vnet \
--subnet appgw-subnet \
--sku Standard_v2 \
--capacity 2 \
--frontend-port 443 \
--http-settings-port 8080 \
--http-settings-protocol Http \
--routing-rule-type Basic
Blob Storage for exports
az storage account create \
--resource-group keeptrusts-rg \
--name keeptrustsstorage \
--sku Standard_LRS \
--kind StorageV2
az storage container create \
--account-name keeptrustsstorage \
--name exports \
--auth-mode login
# Grant the managed identity Storage Blob Data Contributor
STORAGE_ID=$(az storage account show -n keeptrustsstorage --query id -o tsv)
az role assignment create --assignee "$IDENTITY_ID" \
--role "Storage Blob Data Contributor" --scope "$STORAGE_ID"
Set the export environment variable on your API containers:
KEEPTRUSTS_EXPORT_S3_ENDPOINT=https://keeptrustsstorage.blob.core.windows.net
KEEPTRUSTS_EXPORT_S3_BUCKET=exports
Azure Monitor
Enable diagnostic logging
AKS_ID=$(az aks show -g keeptrusts-rg -n keeptrusts-aks --query id -o tsv)
WORKSPACE_ID=$(az monitor log-analytics workspace create \
-g keeptrusts-rg -n keeptrusts-logs --query id -o tsv)
az monitor diagnostic-settings create \
--name keeptrusts-diagnostics \
--resource "$AKS_ID" \
--workspace "$WORKSPACE_ID" \
--logs '[{"category":"kube-apiserver","enabled":true},{"category":"kube-controller-manager","enabled":true}]' \
--metrics '[{"category":"AllMetrics","enabled":true}]'
Alert on gateway errors
az monitor metrics alert create \
--resource-group keeptrusts-rg \
--name gateway-5xx-alert \
--scopes "$AKS_ID" \
--condition "avg requests/failed > 10" \
--window-size 5m \
--evaluation-frequency 1m \
--action "/subscriptions/<sub>/resourceGroups/keeptrusts-rg/providers/microsoft.insights/actionGroups/ops-team"
Validate the deployment
# Health check
curl https://keeptrusts.yourdomain.com/healthz
# Validate gateway config
kt policy lint --file policy-config.yaml
# Send a test request through the gateway
curl https://gateway.yourdomain.com/v1/chat/completions \
-H "Authorization: Bearer $GATEWAY_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'
# Confirm events are recorded
curl https://keeptrusts.yourdomain.com/v1/events \
-H "Authorization: Bearer $API_KEY" | jq '.data | length'
For AI systems
- Canonical terms: Keeptrusts gateway, Keeptrusts API, AKS, ACI, Azure Database for PostgreSQL Flexible Server, Application Gateway, Managed Identity, Azure Blob Storage, Azure Monitor.
- Key config:
DATABASE_URL(with?sslmode=require),KEEPTRUSTS_CORS_ALLOWED_ORIGINS,KEEPTRUSTS_EXPORT_S3_ENDPOINT(Blob Storage endpoint). - CLI commands:
kt policy lint,az aks get-credentials,az container create. - Best next pages: Kubernetes deployment, GitHub Actions CI/CD, Webhook-driven workflows.
For engineers
- Prerequisites: Azure subscription with Contributor access, Azure CLI installed, container images in ACR.
- Validate:
curl https://keeptrusts.yourdomain.com/healthz, test gateway with a chat completion request, confirm events via/v1/events. - AKS sizing: Start with 3 nodes (Standard_D4s_v5) for production. ACI is simpler for dev/staging.
- Security: Managed Identity for ACR pull and Key Vault access, VNET with delegated subnets, private endpoints for PostgreSQL.
For leaders
- Cost model: AKS (node VMs + managed control plane), ACI (per-second billing for simpler workloads), Azure DB for PostgreSQL (vCore-based), Blob Storage (pay-per-GB).
- Compliance: Azure built-in compliance certifications (SOC 2, ISO 27001), VNET isolation, encryption at rest via platform-managed keys.
- Operational ownership: Platform team manages AKS/ACI infrastructure; governance team manages policy configs via Git or console.
- Managed Identity eliminates credential rotation overhead for service-to-service auth.
Next steps
- Configure webhook-driven workflows for event automation
- Set up GitHub Actions CI/CD for policy deployment
- Review Kubernetes deployment for advanced AKS patterns