Azure Runtime
<!-- TASK-212-MARKER:azure -->
Azure Runtime
TesseraCMS kører helt på Azure. Hele infrastrukturen er IaaS-fri — alt er managed services.
Komponenter
| Service | Rolle |
|---|---|
| Azure Container Apps (ACA) | SSR Next.js-runtime, auto-skalerer på trafik |
| Azure Container Registry / GHCR | Docker images bygget af GitHub Actions |
| Azure Table Storage | Content-items (alle pages, blocks, menus, themes) |
| Azure Blob Storage | Media (billeder, dokumenter) |
| Azure AD via ACA Easy Auth | OAuth-login til admin |
| Azure Communication Services (ACS) | Transactional email (invitationer, reset osv.) |
Storage-model
Content: Azure Table Storage med PartitionKey = <tenantSlug>_<typeName>. Alle læs/skriv-operationer skal scope på tenantSlug — dette håndhæves i src/lib/storage/content-items.ts.
Media: Azure Blob Storage med container per tenant. Editor upload'er via /admin/media, public-site-rendering bruger blob-URLs direkte.
Deploy-flow
- Push til
masterpå GitHub - GitHub Action bygger Docker image (Node 24, Next.js standalone)
- Image push'es til GHCR
- Action kalder
az containerapp update --imagepå ACA - ACA traffic-shift'er gradvist til ny revision
- Total tid: ~5-7 minutter
Easy Auth
Azure AD-login håndteres af Easy Auth foran ACA. Når en bruger besøger /admin/* kører Easy Auth OAuth-flowet og sætter X-MS-CLIENT-PRINCIPAL-headers. TesseraCMS læser dem og krydser med roller fra storage for at autorisere.
Hvad TesseraCMS IKKE bruger
Bevidste fravalg for at holde stacken simpel:
- Ingen separat database (Azure Tables dækker behovet)
- Ingen Redis / cache-layer (Tables er lave-latens nok)
- Ingen Kubernetes (ACA håndterer scaling)
- Ingen Service Bus (admin er CRUD — ingen async-flows endnu)
Dybere indhold
Se Azure architecture-siden for fuldt deployment-diagram, naming-conventions for resources og operational runbook.
Cross-references
- Platform Admin manual — operations og drift
- Tenants — multi-tenant data-isolation
- Testing + deployment — CI-flow detaljer
Azure runtime architecture
Layered view of how a public request travels from browser to Azure storage. Each row is a deployment layer.
<!-- TASK-216-MARKER:azure-diagram -->