Configuration Guide#
HASTE environments are configured with the Azure Developer CLI. Every setting is
supplied with azd env set <NAME> <value> before azd up; the values are
read by infra/main.bicepparam at provision time and
by the deploy hooks in deploy/. Defaults live in
main.bicepparam, so an unset variable falls back to a sensible value.
This guide documents each configuration mode. For the end-to-end workflow, see
setup/README.md and deployment.md.
Contents#
Core settings#
Variable |
Default |
Purpose |
|---|---|---|
|
|
Prefix for all resource names. Generic default; override per deployment. |
|
|
Per-environment suffix; keeps names unique. |
|
|
Azure region. |
|
— |
APIM publisher email (required). |
|
|
APIM publisher name. |
|
env RG |
Resource group holding bring-your-own shared resources (Batch, ACR). |
|
— |
Shared Azure Container Registry name (without |
Resource names are HASTE_RESOURCE_PREFIX + HASTE_RANDOM_SUFFIX based (not
azd’s resourceToken) so what-if stays clean against existing deployments.
Project detail performance#
The API and queue workers use the following optional runtime settings. Blob executor and project cache settings are validated at process startup. Metadata map and artifact worker limits are validated when their associated operation is first used; invalid settings may therefore fail a later request or job.
Function App setting |
Default |
Allowed |
Purpose |
|---|---|---|---|
|
16 |
1–64 |
Process-wide blocking Blob I/O budget. |
|
8 |
1–64 |
Per-map limit within the process budget. |
|
8 |
1–64 |
Per-artifact limit within the process budget. |
|
15 |
0–300 |
Process-local response freshness; browsers must revalidate ( |
|
64 |
1–512 |
Maximum cached project response variants per worker. |
These controls have code defaults and are not yet exposed as Bicep parameters. Treat IaC parameterization of non-default values as a separate deployment change. Load-test worker-count overrides with concurrent requests before production rollout.
Batch (create vs. bring-your-own)#
HASTE runs GPU workloads on Azure Batch. Both the Batch account and the GPU pool can either be created in the environment resource group or reused from a shared resource group.
Variable |
Default |
Values |
Purpose |
|---|---|---|---|
|
|
|
Create a Batch account in the env RG, or reference a shared one. |
|
— |
account name |
Required when the account mode is |
|
|
|
Create the GPU pool, or reference an existing one. |
|
— |
pool resource id |
Required when the pool mode is |
Additional pool parameters (batchPoolVmSize, batchPoolMaxNodes,
batchPoolSubnetName) have defaults in infra/main.bicep
and can be overridden by adding them to main.bicepparam.
Common combinations:
Self-contained fork —
HASTE_BATCH_ACCOUNT_MODE=CreateandHASTE_BATCH_POOL_MODE=Createcreate a Batch account and a GPU pool in the environment resource group.Shared account, own pool —
HASTE_BATCH_ACCOUNT_MODE=ExistingwithHASTE_BATCH_POOL_MODE=Createcreates only a new named pool on the shared account, in the shared resource group, via a cross-RG-scoped sub-module. It never modifies the account or sibling pools.Shared account and pool — both set to
Existingreference the account and pool for app-settings wiring only; nothing is written to the shared resource group.
When the pool is created on a shared account, review what-if against both
the environment resource group and HASTE_SHARED_RESOURCE_GROUP, and make sure
the deploy identity has pool-write on the shared account.
hastegeo wheel pinning#
The Function Apps install hastegeo from a published wheel, but
api/*/requirements.txt commit -e ../../hastelib as the default install source
so docker-compose and local Function builds work straight from the checked-out
tree with no wheel publish.
That relative path does not resolve inside a deployment package — only
api/<app> is uploaded — so the line must be rewritten to the published wheel
before packaging. CI does this in
deploy_apps.sh;
azd does it with a pair of hooks:
Hook |
Script |
Purpose |
|---|---|---|
|
Resolve the wheel URL and pin it into the |
|
|
Restore the editable source from a verbatim backup. |
Variable |
Default |
Purpose |
|---|---|---|
|
(blank) |
Exact |
Four things worth knowing:
The hooks are declared per service in
azure.yaml, not at the root. Root-level hooks fire around the matchingazdcommand, so a rootprepackageruns forazd packagebut is skipped byazd deploy’s internal packaging step — which would ship the unresolvable editable path and fail the Oryx build.test_hastegeo_pin_hooks_are_service_scopedguards the placement.titilerhas nohastegeodependency and needs neither hook.The pin fails the deploy on error, deliberately. A mis-resolved wheel produces an app that deploys “successfully” and only breaks when a task runs.
Resolution requires
pythonand an authenticatedghCLI, because the resolver lists release assets viagh release view.
Email sender domain#
The email backend (Azure Communication Services) is provisioned in-IaC, so its connection string is a deploy-time output rather than a manually pasted secret.
Variable |
Default |
Values |
Purpose |
|---|---|---|---|
|
|
|
Sender-domain strategy. |
|
— |
domain |
Required when the type is |
AzureManaged provisions an
azurecomm.netsender domain with no DNS step — the default, best for forks and quick environments.Custom provisions a custom sender domain. DNS verification (TXT/SPF/DKIM records) lives in the customer’s DNS zone and is an out-of-band, one-time step.
No Key Vault is introduced; the connection string is wired from a listKeys()
output to the Function App settings.
Front Door#
Azure Front Door and its WAF are a feature-flagged module, deployed only when enabled.
Variable |
Default |
Purpose |
|---|---|---|
|
|
Provision Front Door + WAF in front of the app. |
Development mode#
Development mode is a dev-only switch. It must never be true in production.
Variable |
Default |
Purpose |
|---|---|---|
|
|
Anonymous Function auth + auto-provisioning of users as administrators. |
When true, the API uses anonymous auth and GetUserById auto-creates any
unknown caller as an administrator — convenient for local and throwaway
environments, unacceptable for production. When false (the default and the
production setting), Functions are key-protected (the postdeploy hook injects the
host key into the APIM backends) and unknown users are rejected until an admin
adds them.
The Docker Compose UI image pre-fills administrators in the SWA emulator’s
mock-login form. The source staticwebapp.config.json used for production is
unchanged.
Data publishing#
Enables the Published Datasets feature and the Publish action on model results. The Local target (an immutable copy in the app’s storage) is on by default; the Planetary Computer target is off until you configure it. For how the feature is used, see Publishing datasets.
Feature flags#
Variable |
Default |
Purpose |
|---|---|---|
|
|
Master switch for the Published Datasets section and the Publish action. |
|
|
Register/expose the Planetary Computer publishing target. |
|
|
Render a damage-classification COG and register the Explorer render/mosaic/tile config on Planetary Computer publish. |
Planetary Computer target#
Required to publish to a Microsoft Planetary Computer Pro GeoCatalog. The GeoCatalog is external to this template — you provision and own it (see the out-of-app setup).
Variable |
Default |
Purpose |
|---|---|---|
|
— |
GeoCatalog base URL (no trailing slash). Required for the PC target. |
|
— |
Explorer base URL used to build published-dataset links. |
|
— |
GeoCatalog ingestion-source name. Only for private publish containers; public containers need none. |
|
|
Prefix for STAC collection ids (one collection per project/event). |
|
|
STAC license id applied to published collections/items. |
|
— |
Object id of the GeoCatalog managed identity to grant Storage Blob Data Reader on HASTE storage (asset ingestion). Empty = skip the role grant. |
Publish storage and attribution#
HASTE copies published assets into a network-reachable container the GeoCatalog ingests from,
and records the operating organization as the STAC processor provider.
Variable |
Default |
Purpose |
|---|---|---|
|
— |
Storage account URL the GeoCatalog ingests published assets from. |
|
— |
Blob container (on the publish storage account) HASTE copies published PC assets into. |
The publish-store settings are an all-or-nothing pair
HASTE_PUBLISH_STORAGE_ACCOUNT_URL and HASTE_PUBLISH_BLOB_CONTAINER are used only when
both are set. If either is empty, HASTE silently falls back to referencing assets in
place from the primary artifact store — which a firewalled GeoCatalog cannot ingest, so
publishing appears configured but fails at ingestion. Set both, or neither.
| HASTE_PUBLISHING_ORGANIZATION_NAME | — | Organization operating this deployment, recorded as the STAC processor provider. Empty = omit. |
| HASTE_PUBLISHING_ORGANIZATION_URL | — | URL companion to HASTE_PUBLISHING_ORGANIZATION_NAME. |
Organization attribution and PC URLs are treated as secrets in CI
On the GitHub Actions deploy path the organization values and the GeoCatalog/publish-storage
URLs are read from environment secrets (masked in logs), while the non-sensitive feature
flags and collection prefix are environment variables. The Bicep/azd path reads them all
as HASTE_* settings.
First-admin bootstrap#
Production uses DEVELOPMENT_MODE=false, so users are managed explicitly and are
not auto-provisioned as administrators. That creates a bootstrap problem: an
admin is needed to add the first users, but a fresh environment has none. The
postdeploy hooks solve it by seeding a first admin.
Variable |
Default |
Purpose |
|---|---|---|
|
signed-in user |
Email of the first administrator. |
Interactive deploys — if
HASTE_FIRST_ADMIN_EMAILis unset, the seed uses the signed-in deployer’s email (deploy/seed-storage-defaults.ps1), writes it intousers_acl.jsonas an administrator, and invites it to the Static Web App (deploy/invite-user.ps1).Non-interactive / CI / service-principal deploys — there is no signed-in user, so set
HASTE_FIRST_ADMIN_EMAIL. Without it, the first-admin seed is skipped and the environment has no administrator.
Both hooks are idempotent (skip-if-exists / dedup). After the first admin signs in, subsequent users are added through the app’s admin user-management flow — the first-admin seed is a one-time bootstrap, not the ongoing mechanism.
Cleaning up an environment#
Deleting an environment does not immediately free its name. APIM, Front Door, and
Batch resources are soft-deleted and retained by Azure for a day or two, so
you cannot reuse the same HASTE_RESOURCE_PREFIX + HASTE_RANDOM_SUFFIX
combination right away.
To tear down and reuse a name sooner:
# Delete the environment's resources.
azd down --force --purge
# APIM must be purged from its soft-deleted state before the name is free.
az apim deletedservice list -o table
az apim deletedservice purge --service-name <name-from-the-list> --location <region>
azd down --purge purges soft-deletable resources it manages; a shared Batch
pool created on a shared account is additive, so remove it explicitly if it
is no longer needed. Otherwise, choose a new suffix and let Azure auto-purge the
old resources.