Hosting — SaaS Applicatie
De AutoMate SaaS-applicatie draait op Azure App Service en wordt volledig beheerd via Bicep Infrastructure as Code. Dit omvat de API, het Management Portal en alle ondersteunende Azure-services. Er zijn twee ingress-paden: klanten gebruiken de publieke HTTPS-endpoint van de App Service, medewerkers benaderen de applicatie via Cloudflare One Zero Trust met WAF, Access policies en twee tunnels per omgeving. Beide App Services hebben publicNetworkAccess: Disabled en zijn alleen bereikbaar via Private Endpoint. Data-resources (Azure SQL, Key Vault, Managed Redis) zijn eveneens alleen via Private Endpoint bereikbaar.
Voor SKU/scaling per asset zie Asset Catalogus. Voor de bredere infrastructuur-context zie Infrastructuur.
Componenten
Component | Azure Resource | Doel |
|---|---|---|
AutoMate.API | App Service (Linux, .NET 10) | Centrale API met FastEndpoints en Hangfire (in-process background jobs) |
Management Portal | App Service (Linux, .NET 10) | Blazor Server beheersinterface |
App Service Plan | Serverfarm (Linux, | Gedeeld plan voor API + Portal — zowel dev als prod draaien op Premium V3 |
Cloudflare Zero Trust | WAF + Cloudflare Access + twee tunnels per omgeving | WAF + OWASP managed ruleset op alle |
Cloudflare Tunnel B — Portal sidecar |
| Routeert |
Cloudflare Tunnel A — Container App | Azure Container App ( | Routeert beheerverkeer: SCM/Kudu, Redis-beheer, SQL-beheer |
Azure SQL Server | SQL Server + Elastic Pool + Databases |
|
Azure Managed Redis | Redis Enterprise (kind v2) | Distributed cache, achter Private Endpoint, Entra-only auth |
Azure Key Vault | Key Vault (standard) | Secrets, certificaten, Cloudflared tunnel-tokens, SendGrid keys, Seq API key |
AuditLogs Storage Account | Storage Account ( | Audit log opslag voor het AuditLog-plugin |
SendGrid | SaaS (extern) | Transactionele e-mail + webhook-verificatie |
Application Insights | App Insights (workspace-based) | APM, telemetry, OpenTelemetry — schrijft naar Log Analytics |
Log Analytics Workspace | Log Analytics ( | Centrale opslag voor App Insights data; retentie 31 dagen (prod) / 30 dagen (dev), daily quota 1 GB |
Seq @ TransIP | Seq (TransIP-gehost, extern) | Productie-pad voor Serilog structured logging |
Netwerk — VNet, subnets, Private Endpoints
Twee ingress-paden voor de App Services:
Klantverkeer loopt via de publieke HTTPS-endpoint van de App Service op de custom domains (
app.automate365.cloud,api.automate365.cloud).Beheerverkeer (medewerkers) loopt via Cloudflare One Zero Trust (WAF + Access) naar twee tunnels per omgeving: de Portal sidecar (Tunnel B) voor publieke gebruikersdomeinen, en de dedicated Container App (Tunnel A) voor beheerverkeer. Beide tunnels routen via de VNet naar de Private Endpoints.
Beide App Services hebben publicNetworkAccess: Disabled. Data-resources (SQL, KV, Redis) zijn achter Private Endpoint vanuit de VNet. Alle 11 subnets hebben NSG's — zie Cloudflare Tunnel Architectuur voor de volledige NSG-regels.
VNet & subnets
VNet <env>-Automate-Vnet-Weu met address space 10.36.0.0/16. Per applicatie aparte in- en out-subnets:
Subnet | CIDR | Doel |
|---|---|---|
| 10.36.1.0/24 | Private Endpoint Azure SQL |
| 10.36.2.0/24 | Private Endpoint Web API (productie + staging slot) |
| 10.36.3.0/24 | VNet-integratie Web API (delegated |
| 10.36.4.0/24 | Private Endpoint Portal |
| 10.36.5.0/24 | VNet-integratie Portal (delegated |
| 10.36.6.0/24 | Autosign service (inbound PE) |
| 10.36.7.0/24 | Autosign service (outbound, delegated) |
| 10.36.8.0/24 | Private Endpoint Managed Redis |
| 10.36.9.0/24 | Private Endpoint Key Vault |
| 10.36.10.0/24 | Private Endpoint AuditLogs Storage Account |
| 10.36.11.0/24 | Outbound VNet-integratie Cloudflare Tunnel Container App (delegated |
Private DNS Zones
In de VNet zijn de volgende Private DNS Zones gekoppeld zodat resolutie van privatelink hostnames intern blijft:
privatelink.azurewebsites.net— App Servicesprivatelink.database.windows.net— Azure SQLprivatelink.redis.azure.net— Managed Redisprivatelink.vaultcore.azure.net— Key Vaultprivatelink.table.core.windows.net— AuditLogs Storage Account (Table/Blob)
Private Endpoints
Endpoint | Subnet | Resource | groupId |
|---|---|---|---|
Azure SQL |
| SQL Server |
|
Key Vault |
| Key Vault |
|
Managed Redis |
| Redis Enterprise |
|
Web API (productie slot) |
| App Service |
|
Web API (staging slot) |
| App Service slot |
|
Gedefinieerd in Infrastructure/Src/main.bicep via de module Modules/Networking/PrivateEndpoint.bicep.
Netwerk-diagram
Het diagram toont welk subnet bij welke resource hoort, samen met de twee ingress-paden. Gestippelde lijnen zijn Private Endpoints.
Ingress — twee paden
Klantverkeer (publiek): komt binnen op de publieke HTTPS-endpoint van de App Service. DNS A-records voor de custom domains wijzen naar het inboundIpAddress van de Web App; de certificate-binding loopt via Microsoft.Web/certificates + SNI-enable (sni-enable.bicep).
Beheerverkeer (Cloudflare One Zero Trust): medewerkers benaderen interne paden via Cloudflare Zero Trust (WAF + Access). Twee tunnels per omgeving: Tunnel B (Portal sidecar) voor publieke gebruikersdomeinen, Tunnel A (Container App *-Automate-Conn-CFTunnel-CA-Weu, 2 replicas, snet-cftunnel-out) voor beheerverkeer. De Portal-webapp heeft vier host-bindings (app.*, dev.*, api.*, api.dev.*); api.* verkeer verwerkt de Portal via een self-loop. Zie Cloudflare Tunnel Architectuur.
Buitenkant — publieke endpoints
App Service custom domains voor klantverkeer:
Productie:
app.automate365.cloud(Portal),api.automate365.cloud(Web API)Development:
dev.automate365.cloud,api.dev.automate365.cloud
Key Vault is alleen via Private Endpoint en een korte IP-allowlist voor office/runner bereikbaar — geen publieke ingest.
Azure SQL en Managed Redis zijn niet publiek bereikbaar (alleen via Private Endpoint, plus voor SQL een office-IP firewall-rule).
Logging & Telemetrie
Twee parallelle paden voor logging:
Pad | Bron | Bestemming | Doel |
|---|---|---|---|
Serilog → Seq | Web API en Portal (Serilog provider) | Seq-instantie gehost op TransIP | Productie-pad voor structured application logging — query via Seq UI |
Application Insights → Log Analytics | App Service runtime, OpenTelemetry | Azure Log Analytics Workspace | APM, performance, distributed tracing, Azure-native telemetrie |
AuditLogs Storage Account | AuditLog-plugin | Storage Account (Blob) | Domein-specifieke audit-trail per tenant |
Configuratie in Bicep:
Serilog__SeqUrlenSerilog__SeqApiKey(Key Vault reference naar secretSeqApiKey) worden doorWebApiAppSettings.bicepenPortalAppSettings.bicepals app-setting geïnjecteerd.APPINSIGHTS_INSTRUMENTATIONKEYenAPPLICATIONINSIGHTS_CONNECTION_STRINGworden gezet door dezelfde bicep-modules.AuditLogs storage account connection string komt uit
MainComponents.bicepoutputAuditLogsStorageAccountConnectionString.
Zie de Logging-pagina onder Crosscutting Concerns voor de Serilog-configuratie zelf.
Deployment
Infrastructure as Code (Bicep)
Alle Azure-resources worden gedefinieerd in /Infrastructure/Src/:
Bestand | Wat het deployt |
|---|---|
| Master orchestrator — SubnetHardening, VNet, Private Endpoints (SQL/KV/Redis/Web API prod+staging), MainComponents, Managed Redis, Web API, Portal, SQL users, CFTunnel |
| Container App Environment + Container App voor de Cloudflare Tunnel (Tunnel A) |
| Key Vault, SQL, App Service Plan, App Insights, Log Analytics, AuditLogs Storage, Managed Identity ( |
| Web Apps, App Settings, DNS, SNI/certificate. Portal-module bevat parameter |
| 11 NSG-modules voor alle subnets |
| VNet, Private Endpoints, Private DNS Zones |
| Key Vault access policies, Storage authenticatie |
CI/CD Pipeline
Deployment verloopt via GitHub Actions:
Infrastructure —
Deployment-Infrastructure-Azure.ymlpast Bicep templates toeWeb Apps —
Deployment-WebApps-selfhosted-runner.ymldeployt API en PortalDeployment slots — Productie- én staging-slot voor zero-downtime deployments
Omgevingen
Omgeving | Prefix | Doel |
|---|---|---|
Development | D | Ontwikkeling en testen |
Test | T | Acceptatietests |
Production | P | Live omgeving |
Naamgeving van resources is gebaseerd op het resource group prefix (D/T/P). De environment-letter wordt in main.bicep afgeleid uit resourceGroup().name.
Secrets management
Alle secrets worden exclusief beheerd via Azure Key Vault. De API en Portal gebruiken Key Vault referenties in hun configuratie — er worden geen secrets opgeslagen in appsettings of environment variables. Key Vault zelf is alleen via Private Endpoint en een IP-allowlist bereikbaar.
Database-architectuur
De SaaS-applicatie gebruikt één gedeelde SQL Server met een Elastic Pool (BasicPool, capaciteit 50 eDTU). Huidige databases:
Database | Inhoud |
|---|---|
Signatures | E-mailhandtekeningen |
UserTypes | UserType definities en formulieren (Personas/OrgModel) |
Jobs | Hangfire job storage |
Emails | E-mail logging |
De eerder gedocumenteerde databases Tenants, Users, Branding, Licenses en Devices zijn afgevoerd. Tenant- en branding-state is verplaatst naar Azure Table Storage of weggevallen door de Workflows 2.0-migratie.
SQL-toegang loopt via Azure AD only authentication (admin-groep SG - Azure SQL Administrators (Production)) en de App Service managed identities worden per database als SQL user toegevoegd (AddUsersLoop.bicep) — de Portal alleen op Signatures, de Web API op Signatures, UserTypes, Jobs en Emails.
Verschil met andere componenten
Component | Hosting | Database | Deployment |
|---|---|---|---|
SaaS App (API + Portal) | Azure App Service; beheerverkeer via Cloudflare One → Container App → Private Endpoints | Azure SQL (4 DBs in Elastic Pool) | Bicep + GitHub Actions |
Status Page | Railway (Docker) | MySQL | Docker + Railway |
Documentatie | Azure Static Web Apps + K8s | — | Writerside + GitHub Actions |
Zie Status Page hosting en Documentatie hosting voor de andere componenten.