Skip to content

Inspect a running service's env & secrets

There is no per-service .env in the cloud. Deployed Configuration lives as GitHub org-level Variables and Secrets, and the deploy engine selects them by prefix and injects them into the Azure Container App — see Environment & service-discovery. The catch: the deploy job declares no GitHub environment: block, so those org-level values are invisible to an ordinary read:org token — you can’t list them from GitHub. The only reliable source of truth for what a service actually received is the live container.

This page is the runbook for reading it with az, and the one rule that keeps it safe: the env dump shows secret references, never secret values.

  • Azure CLI logged in to the subscription that owns rg-core (az login, then az account set if you belong to several). Reading a container app needs Reader on the resource group.
  • The containerapp extension: az extension add --name containerapp (or az extension update --name containerapp).
  • The app name. Every app is <service>-<env> — e.g. core-gateway-consumer-staging, core-database-prod. Workers follow the same pattern (core-tool-agent-staging), they just have no ingress. The full list lives in the Service catalog.
  1. Dump the container’s env array. Every app is in resource group rg-core:

    read one service's effective env
    az containerapp show \
    -n core-gateway-consumer-staging \
    -g rg-core \
    --query "properties.template.containers[0].env"
  2. Read the two shapes. Each entry is either a plain Variable or a secret reference:

    properties.template.containers[0].env (illustrative — values elided)
    [
    { "name": "ENVIRONMENT", "value": "staging" },
    { "name": "CORE_DATABASE_GRPC", "value": "<fqdn>:443" },
    { "name": "REDIS_ADDR", "value": "<redis-url>" },
    { "name": "INTERNAL_RPC_SECRET", "secretRef": "internal-rpc-secret" },
    { "name": "REDIS_PASSWORD", "secretRef": "redis-password" }
    ]

    A value field is an org Variable, injected inline. A secretRef field is an org Secret — the container spec holds only the reference name, never the value.

  3. Narrow to what you need. JMESPath projections keep the output tight and keep values off your screen entirely:

    just the names — no values at all
    az containerapp show -n core-gateway-consumer-staging -g rg-core \
    --query "properties.template.containers[0].env[].name" -o tsv
    is one var wired, and how?
    az containerapp show -n core-gateway-consumer-staging -g rg-core \
    --query "properties.template.containers[0].env[?name=='INTERNAL_RPC_SECRET']"

The names you see are the deploy-injection convention in reverse:

In the container Injected from (org-level, STAGING_/PROD_) Kind
INTERNAL_RPC_SECRET → secretRef internal-rpc-secret STAGING_INTERNAL_RPC_SECRET (Secret) Secret
REDIS_ADDR = value STAGING_REDIS_ADDR (Variable) Variable
CORE_DATABASE_GRPC = <fqdn>:443 STAGING_CORE_DATABASE_GRPC (auto-published on deploy) Variable

The rule: the env-var name is the org name with the STAGING_/PROD_ prefix stripped; a secret’s secretRef is that stripped name lower-cased with _- — so STAGING_INTERNAL_RPC_SECRET becomes env INTERNAL_RPC_SECRET pointing at ACA secret internal-rpc-secret. Service-to-service URLs (CORE_*_GRPC) are the previous deploy’s published FQDN, not something you set by hand.

A secretRef points at a named ACA secret. You can list which secret names are wired on an app — but never print their values:

list secret names only
az containerapp secret list -n core-gateway-consumer-staging -g rg-core \
--query "[].name" -o tsv

All are az containerapp show -n <app> -g rg-core unless noted:

Question --query
Which image/tag is live? "properties.template.containers[0].image"
What is the public FQDN? "properties.configuration.ingress.fqdn"
Is ingress external? "properties.configuration.ingress.external"
Which revisions exist? az containerapp revision list -n <app> -g rg-core -o table

The image tag is the commit SHA the deploy built from — the fastest way to answer “is my fix actually live?” before you dig further. Revisions feed the rollback runbook.

If a name your code reads is absent from the env array, the service didn’t error — it silently fell back to a hard-coded default. That is the class of bug behind historical INTERNAL_AUTH_SECRET vs INTERNAL_RPC_SECRET and REDIS_URL vs REDIS_ADDR drifts: the org published one name, the code read another, and nothing complained. When a service “can’t find” a dependency, diff the names it reads against this env dump first. See Troubleshooting.