# Deployment Advies - Zuyderland CMDB GUI 🎯 **Datum:** {{ vandaag }} **Aanbeveling:** Azure App Service (Basic Tier) **Geschatte kosten:** ~€20-25/maand --- ## πŸ“Š Analyse van Jouw Situatie ### Jouw Requirements: - βœ… **Managed service** (geen serverbeheer) - **Jouw voorkeur** - βœ… **Interne productie** (niet bedrijfskritisch) - βœ… **20 gebruikers** (kleine team) - βœ… **Downtime acceptabel** (kan zelfs 's avonds/weekend uit) - βœ… **Budget geen probleem** (~€20-25/maand is prima) - βœ… **Monitoring via Elastic stack** (kan geΓ―ntegreerd worden) - βœ… **NEN 7510 compliance** (vereist) - βœ… **Updates:** Initieel dagelijks, daarna wekelijks/maandelijks ### Waarom Azure App Service Perfect Past: 1. **Managed Service** ⭐ - Geen serverbeheer, SSH, Linux configuratie - Azure beheert alles (updates, security patches, scaling) - Perfect voor jouw voorkeur: "liever niet als het niet hoeft" 2. **Eenvoudig & Snel** - Setup in ~15 minuten - Automatische SSL/TLS certificaten - Integratie met Azure DevOps (je pipeline werkt al!) 3. **Kosten-Effectief** - Basic B1 plan: ~€15-25/maand - Voldoende voor 20 gebruikers - Geen verborgen kosten 4. **Flexibel** - Deployment slots voor testen (staging β†’ productie) - Eenvoudige rollback - Integratie met Azure Key Vault voor secrets 5. **Monitoring & Compliance** - Integratie met Azure Monitor β†’ kan naar Elastic stack - Logging en audit trails (NEN 7510 compliance) - Health checks ingebouwd --- ## πŸš€ Aanbevolen Architectuur ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Azure App Service Plan (B1) β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Frontend β”‚ β”‚ Backend β”‚ β”‚ β”‚ β”‚ Web App β”‚ β”‚ Web App β”‚ β”‚ β”‚ β”‚ (Container) β”‚ β”‚ (Container) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”‚ Azure Key β”‚ β”‚ Azure β”‚ β”‚ Elastic β”‚ β”‚ Vault β”‚ β”‚ Monitor β”‚ β”‚ Stack β”‚ β”‚ (Secrets) β”‚ β”‚ (Logs) β”‚ β”‚ (Export) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Componenten:** - **App Service Plan B1**: 1 vCPU, 1.75GB RAM (voldoende voor 20 gebruikers) - **2 Web Apps**: Frontend + Backend (delen dezelfde plan = kostenbesparend) - **Azure Key Vault**: Voor secrets (Jira credentials, session secrets) - **Azure Monitor**: Logging β†’ kan geΓ«xporteerd worden naar Elastic stack - **Azure Storage**: Voor SQLite database (als je SQLite blijft gebruiken) **Kosten Breakdown:** - App Service Plan B1: ~€15-20/maand - Azure Key Vault: ~€1-2/maand - Azure Storage (SQLite): ~€1-2/maand - **Totaal: ~€17-24/maand** --- ## πŸ“‹ Stap-voor-Stap Deployment Plan ### Fase 1: Basis Setup (15 minuten) #### Stap 1.1: Resource Group Aanmaken ```bash az group create \ --name rg-cmdb-gui-prod \ --location westeurope ``` #### Stap 1.2: App Service Plan Aanmaken ```bash az appservice plan create \ --name plan-cmdb-gui-prod \ --resource-group rg-cmdb-gui-prod \ --sku B1 \ --is-linux ``` **Waarom B1?** - 1 vCPU, 1.75GB RAM - Voldoende voor 20 gebruikers - Goede prijs/prestatie verhouding #### Stap 1.3: Web Apps Aanmaken ```bash # Backend Web App az webapp create \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --plan plan-cmdb-gui-prod \ --deployment-container-image-name zdlas.azurecr.io/zuyderland-cmdb-gui/backend:latest # Frontend Web App az webapp create \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --plan plan-cmdb-gui-prod \ --deployment-container-image-name zdlas.azurecr.io/zuyderland-cmdb-gui/frontend:latest ``` --- ### Fase 2: ACR Authentication (5 minuten) #### Stap 2.1: Enable Managed Identity ```bash # Backend az webapp identity assign \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod # Frontend az webapp identity assign \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod ``` #### Stap 2.2: Grant ACR Pull Permissions ```bash # Get managed identity principal ID BACKEND_PRINCIPAL_ID=$(az webapp identity show \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --query principalId -o tsv) FRONTEND_PRINCIPAL_ID=$(az webapp identity show \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --query principalId -o tsv) # Get ACR resource ID ACR_ID=$(az acr show \ --name zdlas \ --resource-group \ --query id -o tsv) # Grant AcrPull role az role assignment create \ --assignee $BACKEND_PRINCIPAL_ID \ --role AcrPull \ --scope $ACR_ID az role assignment create \ --assignee $FRONTEND_PRINCIPAL_ID \ --role AcrPull \ --scope $ACR_ID ``` #### Stap 2.3: Configure Container Settings ```bash # Backend az webapp config container set \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --docker-custom-image-name zdlas.azurecr.io/zuyderland-cmdb-gui/backend:latest \ --docker-registry-server-url https://zdlas.azurecr.io # Frontend az webapp config container set \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --docker-custom-image-name zdlas.azurecr.io/zuyderland-cmdb-gui/frontend:latest \ --docker-registry-server-url https://zdlas.azurecr.io ``` --- ### Fase 3: Environment Variabelen (10 minuten) #### Stap 3.1: Azure Key Vault Aanmaken ```bash az keyvault create \ --name kv-cmdb-gui-prod \ --resource-group rg-cmdb-gui-prod \ --location westeurope \ --sku standard ``` #### Stap 3.2: Secrets Toevoegen aan Key Vault ```bash # Jira Personal Access Token (of OAuth credentials) az keyvault secret set \ --vault-name kv-cmdb-gui-prod \ --name JiraPat \ --value "your-jira-pat-token" # Session Secret az keyvault secret set \ --vault-name kv-cmdb-gui-prod \ --name SessionSecret \ --value "$(openssl rand -hex 32)" # Jira Schema ID az keyvault secret set \ --vault-name kv-cmdb-gui-prod \ --name JiraSchemaId \ --value "your-schema-id" # Anthropic API Key (optioneel) az keyvault secret set \ --vault-name kv-cmdb-gui-prod \ --name AnthropicApiKey \ --value "your-anthropic-key" ``` #### Stap 3.3: Grant Web Apps Access tot Key Vault ```bash # Backend az keyvault set-policy \ --name kv-cmdb-gui-prod \ --object-id $BACKEND_PRINCIPAL_ID \ --secret-permissions get list # Frontend (als nodig) az keyvault set-policy \ --name kv-cmdb-gui-prod \ --object-id $FRONTEND_PRINCIPAL_ID \ --secret-permissions get list ``` #### Stap 3.4: Configure App Settings met Key Vault References ```bash # Backend App Settings az webapp config appsettings set \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --settings \ NODE_ENV=production \ PORT=3001 \ JIRA_BASE_URL=https://jira.zuyderland.nl \ JIRA_SCHEMA_ID="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-gui-prod.vault.azure.net/secrets/JiraSchemaId/)" \ JIRA_PAT="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-gui-prod.vault.azure.net/secrets/JiraPat/)" \ SESSION_SECRET="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-gui-prod.vault.azure.net/secrets/SessionSecret/)" \ ANTHROPIC_API_KEY="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-gui-prod.vault.azure.net/secrets/AnthropicApiKey/)" \ FRONTEND_URL=https://cmdb-frontend-prod.azurewebsites.net # Frontend App Settings az webapp config appsettings set \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --settings \ VITE_API_URL=https://cmdb-backend-prod.azurewebsites.net/api ``` --- ### Fase 4: SSL/TLS & Domain (10 minuten) #### Stap 4.1: Gratis SSL via App Service App Service heeft automatisch SSL voor `*.azurewebsites.net`: - Frontend: `https://cmdb-frontend-prod.azurewebsites.net` - Backend: `https://cmdb-backend-prod.azurewebsites.net` **Geen configuratie nodig!** SSL werkt automatisch. #### Stap 4.2: Custom Domain (Optioneel - Later) Als je later een custom domain wilt (bijv. `cmdb.zuyderland.nl`): ```bash # Add custom domain az webapp config hostname add \ --webapp-name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --hostname cmdb.zuyderland.nl # Bind SSL certificate (App Service Certificate of Let's Encrypt) az webapp config ssl bind \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-gui-prod \ --certificate-thumbprint \ --ssl-type SNI ``` --- ### Fase 5: Monitoring & Logging (15 minuten) #### Stap 5.1: Enable Application Insights ```bash # Create Application Insights az monitor app-insights component create \ --app cmdb-gui-prod \ --location westeurope \ --resource-group rg-cmdb-gui-prod \ --application-type web # Get Instrumentation Key INSTRUMENTATION_KEY=$(az monitor app-insights component show \ --app cmdb-gui-prod \ --resource-group rg-cmdb-gui-prod \ --query instrumentationKey -o tsv) # Configure App Settings az webapp config appsettings set \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --settings \ APPINSIGHTS_INSTRUMENTATIONKEY=$INSTRUMENTATION_KEY \ APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=$INSTRUMENTATION_KEY" ``` #### Stap 5.2: Export naar Elastic Stack (Later) Azure Monitor kan geΓ«xporteerd worden naar Elastic stack via: - **Azure Monitor β†’ Log Analytics Workspace β†’ Export naar Elastic** - Of gebruik **Azure Function** om logs te streamen naar Elastic **Zie:** `docs/ELASTIC-STACK-INTEGRATION.md` (te maken als nodig) --- ### Fase 6: Test & Start (5 minuten) #### Stap 6.1: Start Web Apps ```bash az webapp start --name cmdb-backend-prod --resource-group rg-cmdb-gui-prod az webapp start --name cmdb-frontend-prod --resource-group rg-cmdb-gui-prod ``` #### Stap 6.2: Test Health Endpoints ```bash # Backend health check curl https://cmdb-backend-prod.azurewebsites.net/api/health # Frontend curl https://cmdb-frontend-prod.azurewebsites.net ``` #### Stap 6.3: Check Logs ```bash # Backend logs az webapp log tail --name cmdb-backend-prod --resource-group rg-cmdb-gui-prod # Frontend logs az webapp log tail --name cmdb-frontend-prod --resource-group rg-cmdb-gui-prod ``` --- ## πŸ”’ NEN 7510 Compliance ### Wat App Service Biedt: 1. **Encryption** - βœ… Data at rest: Azure Storage encryption - βœ… Data in transit: TLS 1.2+ (automatisch) - βœ… Secrets: Azure Key Vault (encrypted) 2. **Access Control** - βœ… Azure AD integratie (RBAC) - βœ… Managed Identity (geen credentials in code) - βœ… Network isolation (optioneel via VNet integration) 3. **Logging & Audit** - βœ… Application Insights (alle API calls) - βœ… Azure Monitor (resource logs) - βœ… Activity Logs (wie deed wat) - βœ… Export naar Elastic stack mogelijk 4. **Backup & Recovery** - βœ… App Service backups (optioneel) - βœ… Key Vault soft delete (recovery) - ⚠️ **Opmerking**: Jouw data wordt gesynchroniseerd vanuit Jira, dus backup is minder kritisch ### Compliance Checklist: - [ ] Secrets in Azure Key Vault (niet in code) - [ ] HTTPS only (automatisch via App Service) - [ ] Logging ingeschakeld (Application Insights) - [ ] Access control (Azure AD RBAC) - [ ] Audit trail (Activity Logs) - [ ] Encryption at rest (Azure Storage) - [ ] Encryption in transit (TLS 1.2+) **Zie:** `docs/NEN-7510-COMPLIANCE.md` (te maken als nodig) --- ## πŸ” VPN/Private Network Opties (Voor Later) ### Optie 1: App Service VNet Integration **Wat het doet:** - Web App verbindt met Azure Virtual Network - Toegang tot resources in VNet (bijv. database, andere services) - **Niet**: Maakt de app niet privΓ© (app blijft publiek bereikbaar) **Wanneer gebruiken:** - Als je een database in VNet hebt - Als je andere Azure services in VNet moet bereiken **Setup:** ```bash # Create VNet (als nog niet bestaat) az network vnet create \ --name vnet-cmdb-gui \ --resource-group rg-cmdb-gui-prod \ --address-prefix 10.0.0.0/16 # Create subnet az network vnet subnet create \ --name subnet-app-service \ --resource-group rg-cmdb-gui-prod \ --vnet-name vnet-cmdb-gui \ --address-prefix 10.0.1.0/24 # Integrate Web App with VNet az webapp vnet-integration add \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --vnet vnet-cmdb-gui \ --subnet subnet-app-service ``` ### Optie 2: Private Endpoint (Maakt App PrivΓ©) **Wat het doet:** - Maakt de Web App alleen bereikbaar via private IP - Vereist VPN/ExpressRoute om toegang te krijgen - **Kosten:** ~€7-10/maand per Private Endpoint **Wanneer gebruiken:** - Als je de app alleen via VPN wilt bereiken - Als je geen publieke toegang wilt **Setup:** ```bash # Create Private Endpoint az network private-endpoint create \ --name pe-cmdb-backend \ --resource-group rg-cmdb-gui-prod \ --vnet-name vnet-cmdb-gui \ --subnet subnet-private-endpoint \ --private-connection-resource-id /subscriptions//resourceGroups/rg-cmdb-gui-prod/providers/Microsoft.Web/sites/cmdb-backend-prod \ --group-id sites \ --connection-name pe-connection-backend ``` ### Optie 3: App Service Environment (ASE) - Enterprise **Wat het doet:** - Volledig geΓ―soleerde App Service omgeving - Alleen bereikbaar via VNet - **Kosten:** ~€1000+/maand (te duur voor jouw use case) **Niet aanbevolen** voor jouw situatie (te duur, overkill). --- ## πŸ”„ Updates Deployen ### Automatische Deployment (Via Pipeline) Je Azure DevOps pipeline bouwt al automatisch images. Voor automatische deployment: #### Optie A: Continuous Deployment (Aanbevolen) ```bash # Enable continuous deployment az webapp deployment container config \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --enable-cd true # Configure deployment slot (staging) az webapp deployment slot create \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --slot staging # Swap staging β†’ production (zero-downtime) az webapp deployment slot swap \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --slot staging \ --target-slot production ``` #### Optie B: Manual Deployment (Eenvoudig) ```bash # Pull nieuwe image en restart az webapp restart --name cmdb-backend-prod --resource-group rg-cmdb-gui-prod az webapp restart --name cmdb-frontend-prod --resource-group rg-cmdb-gui-prod ``` **Workflow:** 1. Push code naar `main` branch 2. Pipeline bouwt nieuwe images β†’ `zdlas.azurecr.io/.../backend:88767` 3. Images worden getagged als `latest` 4. Restart Web Apps β†’ pull nieuwe `latest` image --- ## πŸ“Š Monitoring Setup ### Azure Monitor β†’ Elastic Stack Export **Optie 1: Log Analytics Workspace Export** ```bash # Create Log Analytics Workspace az monitor log-analytics workspace create \ --workspace-name law-cmdb-gui-prod \ --resource-group rg-cmdb-gui-prod \ --location westeurope # Configure App Service to send logs az webapp log config \ --name cmdb-backend-prod \ --resource-group rg-cmdb-gui-prod \ --application-logging filesystem \ --detailed-error-messages true \ --failed-request-tracing true \ --web-server-logging filesystem # Export to Elastic (via Azure Function of Event Hub) # Zie: docs/ELASTIC-STACK-INTEGRATION.md ``` **Optie 2: Application Insights β†’ Elastic** Application Insights kan geΓ«xporteerd worden via: - **Continuous Export** (deprecated, maar werkt nog) - **Azure Function** die Application Insights API gebruikt - **Log Analytics Workspace** β†’ Export naar Elastic --- ## βœ… Deployment Checklist ### Pre-Deployment: - [ ] Resource Group aangemaakt - [ ] App Service Plan aangemaakt (B1) - [ ] Web Apps aangemaakt (backend + frontend) - [ ] ACR authentication geconfigureerd - [ ] Key Vault aangemaakt - [ ] Secrets toegevoegd aan Key Vault - [ ] App Settings geconfigureerd (met Key Vault references) - [ ] Application Insights ingeschakeld ### Post-Deployment: - [ ] Health checks werken - [ ] SSL/TLS werkt (automatisch) - [ ] Logging werkt - [ ] Monitoring ingesteld - [ ] Team geΓ―nformeerd over URLs - [ ] Documentatie bijgewerkt --- ## 🎯 Volgende Stappen 1. **Start met Fase 1-3** (Basis setup + ACR + Environment variabelen) 2. **Test de applicatie** (Fase 6) 3. **Configureer monitoring** (Fase 5) 4. **Documenteer voor team** (URLs, credentials, etc.) --- ## πŸ“š Gerelateerde Documentatie - **Quick Deployment Guide**: `docs/QUICK-DEPLOYMENT-GUIDE.md` - **Production Deployment**: `docs/PRODUCTION-DEPLOYMENT.md` - **Azure Deployment Summary**: `docs/AZURE-DEPLOYMENT-SUMMARY.md` --- ## ❓ Vragen? **Veelgestelde vragen:** **Q: Moet ik PostgreSQL gebruiken of kan ik SQLite houden?** A: SQLite is prima voor 20 gebruikers. Als je later groeit, kun je migreren naar PostgreSQL. **Q: Hoe update ik de applicatie?** A: Push naar `main` β†’ Pipeline bouwt images β†’ Restart Web Apps (of gebruik deployment slots voor zero-downtime). **Q: Kan ik de app 's avonds/weekend uitzetten?** A: Ja! `az webapp stop --name cmdb-backend-prod --resource-group rg-cmdb-gui-prod` (bespaart kosten). **Q: Hoe integreer ik met Elastic stack?** A: Exporteer Azure Monitor logs via Log Analytics Workspace β†’ Elastic (zie Fase 5). --- ## πŸŽ‰ Success! Je hebt nu een compleet deployment plan voor Azure App Service! **Start met Fase 1** en laat me weten als je hulp nodig hebt bij een specifieke stap.