Deploy the Routeplane gateway to Azure Container Apps with scale-to-zero: it costs nothing while idle, cold-starts on the first request, and terminates TLS for you. By the end you'll have a live HTTPS endpoint serving completions, with an in-region provider for data-residency enforcement.
az) logged in to a subscription, the containerapp extension (az extension add --name containerapp), and at least one provider key. Set a few shell variables, RG (resource group), LOC (e.g. centralindia), and APP, before you start.
1. Create the environment
The gateway image is published to a public registry, so there's nothing to build, Container Apps pulls it directly. Create a resource group and a Container Apps environment:
az group create -n "$RG" -l "$LOC"
az containerapp env create \
-n "rp-env" -g "$RG" -l "$LOC"
2. Deploy the gateway with scale-to-zero
Point it at the published image. Ingress on target port 8080, --min-replicas 0 for scale-to-zero, the provider key as a Container Apps secret, and the key surfaced to the process as an env var via secretref:.
az containerapp create \
-n "$APP" -g "$RG" --environment "rp-env" \
--image ghcr.io/routeplane-core/routeplane:latest \
--target-port 8080 --ingress external \
--min-replicas 0 --max-replicas 5 \
--secrets "openai-key=$OPENAI_API_KEY" \
--env-vars "OPENAI_API_KEY=secretref:openai-key" "PORT=8080"
--secrets and referencing it with secretref: keeps it out of the container's plain env definition. Never put a provider key directly in --env-vars.
Want the image in your own registry instead of pulling from the public one (for a private pull path or compliance)? Import it once with az acr import --source ghcr.io/routeplane-core/routeplane:latest and point --image + --registry-server at your ACR.
3. Verify the live endpoint
FQDN=$(az containerapp show -n "$APP" -g "$RG" \
--query properties.configuration.ingress.fqdn -o tsv)
curl -s "https://$FQDN/healthz" # 200 OK (may cold-start on first hit)
curl -s "https://$FQDN/v1/chat/completions" \
-H 'content-type: application/json' \
-H 'x-routeplane-api-key: rp_dev_REPLACE_ME' \
-H 'x-routeplane-provider: openai' \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hello from ACA"}]}'
The first request after an idle period pays a cold-start; subsequent requests are warm until it scales back to zero.
4. Make it sovereign
To enforce data residency, give the gateway an in-region provider and call with a residency header. Deploy this app to an Indian region (centralindia) and configure an Azure OpenAI deployment in-region via the AZURE_OPENAI_* settings (see Configuration). Then:
curl -s "https://$FQDN/v1/chat/completions" \
-H 'content-type: application/json' \
-H 'x-routeplane-api-key: rp_...' \
-H 'x-routeplane-residency: IN' \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"My PAN is ABCDE1234F"}]}'
Now a request carrying regulated data is hard-locked to the in-region provider, and fails closed with 422 if none is eligible.
az commands show the shape; for anything beyond a demo, manage it as infrastructure-as-code. A Terraform topology (reusable modules + per-environment wiring, with OIDC-federated CI, no static cloud credentials) provisions exactly this. See Deploy.