EddytorDocs & API
02 · Deploy & RunKubernetes with Helm

AKS (Azure)

Azure-specific deltas for deploying Eddytor on AKS - cluster, Flexible Server Postgres, Blob storage.

This is the Azure delta over Install the chart. The chart install, required secret, verify, and first-admin steps are identical - follow that page for them, and apply only the AKS-specific pieces here.

Needs az, kubectl, helm ≥ 3.8, and a subscription that can create resource groups + AKS clusters.

1. Create the cluster

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

az aks create \
  --resource-group "$RG" --name "$CLUSTER" --location "$REGION" \
  --node-count "$NODES" --node-vm-size "$VM_SIZE" \
  --enable-managed-identity --generate-ssh-keys
  # existing VNet:   --vnet-subnet-id "$SUBNET_ID" --network-plugin azure
  # private cluster: --enable-private-cluster

az aks get-credentials --resource-group "$RG" --name "$CLUSTER" --overwrite-existing
kubectl get nodes        # all Ready

Engine requests ~1 CPU / 2Gi and server ~200m / 512Mi (×2 each), so three 4-vCPU nodes give headroom.

Heads up

vCPU quota can be 0 for a VM family. If az aks create fails with InsufficientVCPUQuota, check az vm list-usage --location "$REGION" -o table and pick a family with headroom (Standard_D4as_v4 is a safe fallback), or request a quota increase.

2. Managed Postgres (production)

Use Azure Database for PostgreSQL Flexible Server. Read the password without echoing it into shell history:

read -rs PGADMIN_PW

az postgres flexible-server create \
  --resource-group "$RG" --name eddytor-pg --location "$REGION" \
  --admin-user eddytor --admin-password "$PGADMIN_PW" \
  --tier Burstable --sku-name Standard_B2s \
  --version 16 --storage-size 32 \
  --public-access 0.0.0.0    # Azure-services sentinel (NOT 0.0.0.0/0); use VNet/Private Link for prod

az postgres flexible-server db create \
  --resource-group "$RG" --server-name eddytor-pg --name eddytor

# Allow-list the extensions the migrations need (Azure blocks them by default):
az postgres flexible-server parameter set \
  --resource-group "$RG" --server-name eddytor-pg \
  --name azure.extensions --value citext,pgcrypto

Heads up

Allow-list citext + pgcrypto before first server boot. Azure blocks all extensions by default, so without this migration 0 dies with extension "citext" is not allow-listed.

Build the conn string into the secret from the base skill - Azure requires TLS, so it must end with ?sslmode=require:

kubectl -n eddytor create secret generic eddytor-secrets \
  --from-literal=EDDYTOR_DATABASE_URL="postgres://eddytor:${PGADMIN_PW}@eddytor-pg.postgres.database.azure.com:5432/eddytor?sslmode=require" \
  --from-literal=EDDYTOR_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
  --from-literal=EDDYTOR_API_KEY_SECRET="$(openssl rand -base64 32)"
unset PGADMIN_PW

Then helm upgrade --install per Install the chart, with postgres.bundled left off. Do not enable waitForDb for this external DB. For production prefer Microsoft Entra (Azure AD) auth over a static admin password.

3. Object store - Azure Blob

After install, register Azure Blob as a storage connection - prefer managed identity (use_msi) so no key lives in the cluster. See Azure Blob. For evaluation only, --set garage.bundled=true gives an in-cluster S3.

Gotchas

  • waitForDb is broken with an external DB - leave it false (default); the init container hardcodes the bundled eddytor-postgres host and loops forever otherwise.
  • Bundled Postgres crash-loops on azuredisk (chown: Operation not permitted) - use Flexible Server, or patch the StatefulSet to add CHOWN,FOWNER,DAC_OVERRIDE,SETGID,SETUID.
  • config.publicUrl / ui.origin must equal the address the browser hits, or OAuth redirects and cookies break - hence the two-step on the raw-LB-IP path (install with a placeholder, read the EXTERNAL-IP, then --reuse-values --set config.publicUrl=…).
  • The AKS egress IP (or VNet) must be allowed through the Postgres firewall.

Teardown

az group delete --name "$RG" --yes --no-wait

Next

On this page