Azure Container

Prerequisites

  • formae CLI installed on your local machine - see local installation
  • Azure CLI installed and authenticated (az login)

If you have never used Azure Container Instances, register the provider first:

az provider register --namespace Microsoft.ContainerInstance

Create a resource group

az group create --name formae-rg --location <region>

Set up the database

The agent needs a persistent database. Azure Database for PostgreSQL - Flexible Server works well here.

If you already have a Flexible Server, create a database and skip to configure the agent.

Create a Flexible Server (Burstable B1ms is the cheapest tier):

az postgres flexible-server create \
  --resource-group formae-rg \
  --name formae-pg \
  --location <region> \
  --sku-name Standard_B1ms \
  --storage-size 32 \
  --tier Burstable \
  --version 16 \
  --admin-user formaeadmin \
  --admin-password <password> \
  --public-access 0.0.0.0 \
  --yes

--public-access 0.0.0.0 adds a firewall rule allowing connections from Azure services, including ACI.

Create the database:

az postgres flexible-server db create \
  --resource-group formae-rg \
  --server-name formae-pg \
  --database-name formae

Configure the agent

The agent needs a config file pointing at the database. Create a storage account and file share to mount into the container:

az storage account create \
  --resource-group formae-rg \
  --name formaeconfig \
  --location <region> \
  --sku Standard_LRS
az storage share create \
  --account-name formaeconfig \
  --name formae-config

Create a config file (formae.conf.pkl):

amends "formae:/Config.pkl"

agent {
  datastore {
    datastoreType = "postgres"
    postgres {
      host = "formae-pg.postgres.database.azure.com"
      port = 5432
      user = "formaeadmin"
      password = "<password>"
      database = "formae"
      connectionParams = "sslmode=require"
    }
  }
}

Upload it:

az storage file upload \
  --account-name formaeconfig \
  --share-name formae-config \
  --source formae.conf.pkl \
  --path formae.conf.pkl

Deploy the agent

Get the storage account key:

STORAGE_KEY=$(az storage account keys list \
  --resource-group formae-rg \
  --account-name formaeconfig \
  --query "[0].value" -o tsv)

Create the container with the config mounted and a managed identity:

az container create \
  --resource-group formae-rg \
  --name formae-agent \
  --image ghcr.io/platform-engineering-labs/formae:latest \
  --ports 49684 \
  --os-type Linux \
  --dns-name-label formae-agent \
  --cpu 1 --memory 1 \
  --assign-identity \
  --azure-file-volume-account-name formaeconfig \
  --azure-file-volume-account-key "$STORAGE_KEY" \
  --azure-file-volume-share-name formae-config \
  --azure-file-volume-mount-path /config \
  --command-line "formae agent start --config /config/formae.conf.pkl"

--assign-identity gives the container a system-assigned managed identity. The agent authenticates to Azure automatically - no credentials on the container.

--dns-name-label gives you a stable FQDN (formae-agent.<region>.azurecontainer.io). Without it, you get an ephemeral IP.

Note the principalId from the identity block in the output - you need it next.

Assign permissions

The identity exists but has no permissions yet. Assign the Contributor role:

az role assignment create \
  --assignee <principalId> \
  --role Contributor \
  --scope /subscriptions/<subscription-id>

Role assignments can take a minute or two to propagate.

Verify

curl -s -o /dev/null -w "%{http_code}" \
  "http://formae-agent.<region>.azurecontainer.io:49684/api/v1/health"
# 200

Applying formas

The formae CLI runs on your local machine. It evaluates your Pkl files locally and sends the result to the agent API - no files need to be loaded into the container.

Update the CLI's agent URL in ~/.config/formae/formae.conf.pkl:

amends "formae:/Config.pkl"

cli {
    api {
        url = "http://formae-agent.<region>.azurecontainer.io"
        port = 49684
    }
}

Check connectivity:

formae status agent

Then apply a forma:

formae apply --mode reconcile your-forma.pkl

How authentication works

The formae Azure plugin uses DefaultAzureCredential, which picks up tokens from the Instance Metadata Service (IMDS) automatically when running on Azure. No env vars, no secret files, no token refresh to manage.

See the Azure plugin docs for the full credential chain.

Next steps

Head to the quick start or see the configuration docs for available options.