Architecture¶
End-to-end model from Pulumi program to a running App Service instance.
flowchart TD
subgraph consumer [Consumer projects]
PulumiStack[Pulumi stack]
DjangoApp[Django app repo]
end
subgraph azure [Azure resources]
SA[Storage + CDN]
PG[Postgres Flexible Server]
ASP[App Service Plan]
WA[Django Web App]
PGA[pgAdmin Web App]
KV[Key Vault]
Redis[Redis sidecar]
end
subgraph deploy [Deploy on App Service]
Boot[bootstrap.django-azu.re]
Oryx[Oryx build]
Start[startup.sh]
end
PulumiStack -->|DjangoDeployment| azure
DjangoApp -->|Git source control| WA
WA --> Boot --> Oryx --> Start
Start --> WA
WA --> PG
WA --> SA
WA --> KV
WA --> Redis
Shared vs per-app¶
One DjangoDeployment creates the shared plane (storage, CDN, Postgres server, plan, pgAdmin). Each add_django_website(...) adds an application plane (database, containers, vault, Web App, optional ACS/Redis).
Runtime trust model¶
- Web App uses a system-assigned managed identity.
- Postgres uses Entra ID auth only (no password auth on the server). The app password in Django is a short-lived Entra access token refreshed via health checks.
- Secrets from Pulumi config land in Key Vault; the app receives
{ENV}_SECRET_NAMEand reads values withAZURE_KEY_VAULT_CLIENT. - Static/media go to blob storage and are served through the CDN host.
Build and start¶
- App setting
PRE_BUILD_COMMANDcurlshttps://bootstrap.django-azu.re. - Bootstrap fills
cicd//utility/and runspre_build.sh. - Oryx installs from exported
requirements.txt;POST_BUILD_COMMANDrunspost_build.sh. - App Service starts
cicd/startup.sh(migrate, collectstatic, supervisord, Gunicorn).
Details: Deploy pipeline.