Consolidate documentation and update backend services

- Reorganize docs into 'Core deployment guides' and 'Setup and configuration' subdirectories
- Consolidate redundant documentation files (ACR, pipelines, deployment guides)
- Add documentation consolidation plan
- Update backend database factory and logger services
- Update migration script and docker-compose configurations
- Add PostgreSQL setup script
This commit is contained in:
2026-01-22 22:45:54 +01:00
parent 18aec4ad80
commit f4399a8e4e
49 changed files with 1320 additions and 7243 deletions

View File

@@ -0,0 +1,378 @@
# Azure Container Registry - Quick Start Guide
Snelstart guide om zelf Azure Container Registry aan te maken en te configureren voor productie.
## 🚀 Stap 1: Azure Container Registry Aanmaken
### Optie A: Met Script (Aanbevolen)
```bash
# Run het script
./scripts/create-acr.sh
# Of met custom parameters:
./scripts/create-acr.sh rg-cmdb-gui zuyderlandcmdbacr westeurope Basic
```
Het script doet automatisch:
- ✅ Checkt of je ingelogd bent bij Azure
- ✅ Maakt resource group aan (als nodig)
- ✅ Controleert of ACR naam beschikbaar is
- ✅ Maakt ACR aan met Basic SKU
- ✅ Toont credentials
- ✅ Test Docker login
### Optie B: Handmatig via Azure CLI
```bash
# Login bij Azure
az login
# Resource group aanmaken
az group create --name rg-cmdb-gui --location westeurope
# Check of naam beschikbaar is
az acr check-name --name zuyderlandcmdbacr
# ACR aanmaken (Basic SKU - ~€5/maand)
az acr create \
--resource-group rg-cmdb-gui \
--name zuyderlandcmdbacr \
--sku Basic \
--admin-enabled true
# Credentials ophalen
az acr credential show --name zuyderlandcmdbacr
```
### Optie C: Via Azure Portal
1. Ga naar [Azure Portal](https://portal.azure.com)
2. Klik **"Create a resource"**
3. Zoek **"Container Registry"**
4. Klik **"Create"**
5. Vul in:
- **Resource group**: `rg-cmdb-gui` (of maak nieuwe)
- **Registry name**: `zuyderlandcmdbacr` (moet uniek zijn, alleen kleine letters en cijfers, **geen streepjes**)
- **Location**: `West Europe`
- **SKU**: `Basic` ⭐ (aanbevolen - ~€5/maand)
- **Domain name label scope**:
- **"Unsecure"** ⭐ (aanbevolen) - DNS naam wordt: `zuyderlandcmdbacr.azurecr.io`
- **"Resource Group Reuse"** (voor extra security) - DNS naam wordt: `zuyderlandcmdbacr-abc123.azurecr.io` (met hash)
- ⚠️ **Let op**: Als je een hash gebruikt, moet je alle configuraties aanpassen met de volledige DNS naam!
- **Role assignment permissions mode**:
- **"RBAC Registry Permissions"** ⭐ (aanbevolen - eenvoudigst)
- **"RBAC Registry + ABAC Repository Permissions"** (alleen als je per-repository permissions nodig hebt)
6. Klik **"Review + create"** → **"Create"**
**💡 Aanbeveling:** Kies **"Unsecure"** voor de eenvoudigste setup. Zie `docs/AZURE-ACR-DNL-SCOPE.md` voor details.
**Noteer je ACR naam!** Je hebt deze nodig voor de volgende stappen.
---
## 🔧 Stap 2: Pipeline Variabelen Aanpassen
Pas `azure-pipelines.yml` aan met jouw ACR naam:
```yaml
variables:
# Pas deze aan naar jouw ACR naam
acrName: 'zuyderlandcmdbacr' # ← Jouw ACR naam hier
repositoryName: 'cmdb-insight'
# Service connection naam (maak je in volgende stap)
dockerRegistryServiceConnection: 'zuyderland-cmdb-acr-connection'
imageTag: '$(Build.BuildId)'
```
**Commit en push:**
```bash
git add azure-pipelines.yml
git commit -m "Configure ACR in pipeline"
git push origin main
```
---
## 🔗 Stap 3: Service Connection Aanmaken in Azure DevOps
Deze connection geeft Azure DevOps toegang tot je ACR.
1. **Ga naar je Azure DevOps project**
2. Klik op **⚙️ Project Settings** (onderaan links)
3. Ga naar **Service connections** (onder Pipelines)
4. Klik op **"New service connection"**
5. Kies **"Docker Registry"**
6. Kies **"Azure Container Registry"**
7. Vul in:
- **Azure subscription**: Selecteer je Azure subscription
- **Azure container registry**: Selecteer je ACR (bijv. `zuyderlandcmdbacr`)
- **Service connection name**: `zuyderland-cmdb-acr-connection`
- **Description**: Optioneel (bijv. "ACR for CMDB GUI")
8. Klik **"Save"**
**✅ Noteer de service connection naam!** Deze moet overeenkomen met `dockerRegistryServiceConnection` in `azure-pipelines.yml`.
---
## 🎯 Stap 4: Pipeline Aanmaken en Run
1. **Ga naar je Azure DevOps project**
2. Klik op **Pipelines** (links in het menu)
3. Klik op **"New pipeline"** of **"Create Pipeline"**
4. Kies **"Azure Repos Git"** (of waar je code staat)
5. Selecteer je repository: **"CMDB Insight"**
6. Kies **"Existing Azure Pipelines YAML file"**
7. Selecteer:
- **Branch**: `main`
- **Path**: `/azure-pipelines.yml`
8. Klik **"Continue"**
9. **Review** de pipeline configuratie
10. Klik **"Run"** om de pipeline te starten
---
## ✅ Stap 5: Verifiëren
### In Azure Portal:
1. Ga naar je **Container Registry** (`zuyderlandcmdbacr`)
2. Klik op **"Repositories"**
3. Je zou moeten zien:
- `cmdb-insight/backend`
- `cmdb-insight/frontend`
4. Klik op een repository om de tags te zien (bijv. `latest`, `123`)
### Via Azure CLI:
```bash
# Lijst repositories
az acr repository list --name zuyderlandcmdbacr
# Lijst tags voor backend
az acr repository show-tags --name zuyderlandcmdbacr --repository cmdb-insight/backend
# Lijst tags voor frontend
az acr repository show-tags --name zuyderlandcmdbacr --repository cmdb-insight/frontend
```
---
## 🐳 Stap 6: Images Lokaal Testen (Optioneel)
```bash
# Login bij ACR
az acr login --name zuyderlandcmdbacr
# Pull images
docker pull zuyderlandcmdbacr.azurecr.io/cmdb-insight/backend:latest
docker pull zuyderlandcmdbacr.azurecr.io/cmdb-insight/frontend:latest
# Test run (met docker-compose)
docker-compose -f docker-compose.prod.acr.yml pull
docker-compose -f docker-compose.prod.acr.yml up -d
```
---
## 📋 Checklist
- [ ] Azure Container Registry aangemaakt
- [ ] ACR naam genoteerd
- [ ] `azure-pipelines.yml` variabelen aangepast
- [ ] Service Connection aangemaakt in Azure DevOps
- [ ] Pipeline aangemaakt en gerund
- [ ] Images succesvol gebouwd en gepusht
- [ ] Images geverifieerd in Azure Portal
---
## 🔄 Automatische Triggers
De pipeline triggert automatisch bij:
1. **Push naar `main` branch** → Bouwt `latest` tag
2. **Git tags die beginnen met `v*`** → Bouwt versie tag (bijv. `v1.0.0`)
**Voorbeeld:**
```bash
# Tag aanmaken en pushen
git tag v1.0.0
git push origin v1.0.0
# → Pipeline triggert automatisch en bouwt versie 1.0.0
```
---
## 🚨 Troubleshooting
### Pipeline Fails: "Service connection not found"
**Oplossing:**
- Controleer of de service connection naam in `azure-pipelines.yml` overeenkomt met de naam in Azure DevOps
- Ga naar Project Settings → Service connections en verifieer de naam
### Pipeline Fails: "ACR not found"
**Oplossing:**
- Controleer of de `acrName` variabele correct is in `azure-pipelines.yml`
- Verifieer dat de ACR bestaat: `az acr list`
### Pipeline Fails: "Permission denied"
**Oplossing:**
- Controleer of de service connection de juiste permissions heeft
- Verifieer dat je Azure subscription toegang heeft tot de ACR
- Probeer de service connection opnieuw aan te maken
### ACR Naam Niet Beschikbaar
**Oplossing:**
- ACR namen moeten uniek zijn wereldwijd
- Probeer een andere naam:
- `zuyderlandcmdbacr1`
- `zuyderlandcmdbprod`
- `cmdbzuyderlandacr`
- `zuyderlandcmdbgui`
---
## 💰 Kosten & SKU Keuze
**Aanbeveling: Basic SKU** ⭐ (~€5/maand)
### Basic SKU (Aanbevolen voor jouw situatie)
**Inclusief:**
-**10GB storage** - Ruim voldoende voor backend + frontend images met meerdere versies
-**1GB/day webhook throughput** - Voldoende voor CI/CD
-**Unlimited pulls** - Geen extra kosten voor image pulls
-**Admin user enabled** - Voor development/productie
-**RBAC support** - Role-based access control
-**Content trust** - Image signing support
-**Kosten: ~€5/maand**
**Limitaties:**
- ❌ Geen geo-replicatie
- ❌ Geen security scanning (vulnerability scanning)
- ❌ Geen content trust storage
**Wanneer gebruiken:**
-**Jouw situatie** - 20 gebruikers, corporate tool
- ✅ Development en productie omgevingen
- ✅ Kleine tot middelgrote teams
- ✅ Budget-conscious deployments
### Standard SKU (~€20/maand)
**Inclusief (alles van Basic +):**
- 100GB storage
- 10GB/day webhook throughput
- Geo-replicatie
- **Niet nodig voor jouw situatie**
### Premium SKU (~€50/maand)
**Inclusief (alles van Standard +):**
- 500GB storage
- Security scanning
- Private endpoints
- **Overkill voor 20 gebruikers**
**Voor jouw situatie (20 gebruikers): Basic is perfect!**
---
## 🔐 Permissions Mode
**Aanbeveling: RBAC Registry Permissions**
### RBAC Registry Permissions (Aanbevolen)
**Hoe het werkt:**
- Permissions worden ingesteld op **registry niveau**
- Alle repositories binnen de registry delen dezelfde permissions
- Gebruikers hebben toegang tot alle repositories of geen
**Voordelen:**
-**Eenvoudig** - Minder complexiteit
-**Makkelijk te beheren** - Eén set permissions voor de hele registry
-**Voldoende voor de meeste scenario's** - Perfect voor jouw situatie
-**Standaard keuze** - Meest gebruikte optie
**Wanneer gebruiken:**
-**Jouw situatie** - 20 gebruikers, corporate tool
- ✅ Kleine tot middelgrote teams
- ✅ Alle repositories hebben dezelfde toegangsvereisten
- ✅ Eenvoudige permission structuur gewenst
### RBAC Registry + ABAC Repository Permissions
**Wanneer gebruiken:**
- Als je per-repository permissions nodig hebt
- Grote teams met verschillende toegangsvereisten
- Complexe permission structuur
**Voor jouw situatie: RBAC Registry Permissions is perfect!**
---
## 🔄 Shared ACR Setup (Optioneel)
Als je al een ACR hebt voor andere applicaties, kun je deze hergebruiken:
**Voordelen:**
-**Cost Savings**: Eén ACR voor alle applicaties (€5-20/month vs multiple ACRs)
-**Centralized Management**: All images in one place
-**Easier Collaboration**: Teams can share images
**Hoe het werkt:**
- ACR is shared, maar elke applicatie gebruikt een **unique repository name**
- Repository name (`cmdb-insight`) scheidt jouw app van anderen
- Images zijn georganiseerd per applicatie: `acr.azurecr.io/app-name/service:tag`
**Voorbeeld structuur:**
```
zuyderlandacr.azurecr.io/
├── cmdb-insight/ ← Deze applicatie
│ ├── backend:latest
│ └── frontend:latest
├── other-app/ ← Andere applicatie
│ └── api:latest
└── shared-services/ ← Gedeelde base images
└── nginx:latest
```
**Setup:**
```bash
# Gebruik bestaande ACR
ACR_NAME="your-existing-acr"
ACR_RESOURCE_GROUP="rg-shared-services"
# Verifieer dat het bestaat
az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP
# Update pipeline variabelen met bestaande ACR naam
```
---
## 📚 Meer Informatie
- **Deployment Guide**: `docs/AZURE-APP-SERVICE-DEPLOYMENT.md`
- **Azure DevOps Setup**: `docs/AZURE-DEVOPS-SETUP.md`
- **Deployment Guide**: `docs/PRODUCTION-DEPLOYMENT.md`
---
## 🎯 Volgende Stappen
Nu je images in ACR staan, kun je ze deployen naar:
1. **Azure Container Instances (ACI)** - Eenvoudig, snel
2. **Azure App Service (Container)** - Managed service
3. **Azure Kubernetes Service (AKS)** - Voor complexere setups
4. **VM met Docker Compose** - Volledige controle
Zie `docs/AZURE-APP-SERVICE-DEPLOYMENT.md` voor deployment opties.

View File

@@ -0,0 +1,405 @@
# Azure App Service Deployment - Stap-voor-Stap Guide 🚀
Complete deployment guide voor CMDB Insight naar Azure App Service.
## 🎯 Waarom Azure App Service?
Azure App Service is de aanbevolen deployment optie voor CMDB Insight omdat:
1. **Managed Service**
- Geen serverbeheer, SSH, Linux configuratie nodig
- Azure beheert alles (updates, security patches, scaling)
- Perfect voor teams die geen infrastructuur willen beheren
2. **Eenvoudig & Snel**
- Setup in ~15 minuten
- Automatische SSL/TLS certificaten
- Integratie met Azure DevOps pipelines
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
- Logging en audit trails (NEN 7510 compliance)
- Health checks ingebouwd
**Geschatte kosten:** ~€20-25/maand (met PostgreSQL database)
---
## 📋 Prerequisites
- Azure CLI geïnstalleerd en geconfigureerd (`az login`)
- Docker images in ACR: `zdlasacr.azurecr.io/cmdb-insight/backend:latest` en `frontend:latest`
- Azure DevOps pipeline werkt (images worden automatisch gebouwd)
---
## 🎯 Quick Start (15 minuten)
### Stap 1: Resource Group
```bash
az group create \
--name zdl-cmdb-insight-prd-euwe-rg \
--location westeurope
```
### Stap 2: App Service Plan
```bash
az appservice plan create \
--name zdl-cmdb-insight-prd-euwe-appsvc \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--sku B1 \
--is-linux
```
### Stap 3: Web Apps
```bash
# Backend
az webapp create \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--plan zdl-cmdb-insight-prd-euwe-appsvc \
--container-image-name zdlasacr.azurecr.io/cmdb-insight/backend:latest
# Frontend
az webapp create \
--name zdl-cmdb-insight-prd-frontend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--plan zdl-cmdb-insight-prd-euwe-appsvc \
--container-image-name zdlasacr.azurecr.io/cmdb-insight/frontend:latest
```
### Stap 4: ACR Authentication
```bash
# Enable Managed Identity
az webapp identity assign --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
az webapp identity assign --name zdl-cmdb-insight-prd-frontend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
# Get Principal IDs
BACKEND_PRINCIPAL_ID=$(az webapp identity show \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--query principalId -o tsv)
FRONTEND_PRINCIPAL_ID=$(az webapp identity show \
--name zdl-cmdb-insight-prd-frontend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--query principalId -o tsv)
# Get ACR Resource ID
ACR_ID=$(az acr show --name zdlasacr --query id -o tsv)
# Grant AcrPull permissions
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
# Configure container settings
az webapp config container set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--docker-registry-server-url https://zdlasacr.azurecr.io
az webapp config container set \
--name zdl-cmdb-insight-prd-frontend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--docker-registry-server-url https://zdlasacr.azurecr.io
```
### Stap 5: PostgreSQL Database Setup (Aanbevolen voor Productie)
**Voor PostgreSQL setup, zie:** `docs/AZURE-POSTGRESQL-SETUP.md`
**Quick setup met script:**
```bash
./scripts/setup-postgresql.sh
```
**Of handmatig:**
```bash
# Maak PostgreSQL Flexible Server aan
az postgres flexible-server create \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--name zdl-cmdb-insight-prd-psql \
--location westeurope \
--admin-user cmdbadmin \
--admin-password $(openssl rand -base64 32) \
--sku-name Standard_B1ms \
--tier Burstable \
--storage-size 32 \
--version 15
# Maak database aan (één database is voldoende)
az postgres flexible-server db create \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--server-name zdl-cmdb-insight-prd-psql \
--database-name cmdb_insight
```
**Voor SQLite (alternatief, eenvoudiger maar minder geschikt voor productie):**
- Geen extra setup nodig
- Database wordt automatisch aangemaakt in container
- Zie Stap 5b hieronder
### Stap 5a: Environment Variabelen met PostgreSQL
```bash
# Backend met PostgreSQL (vervang met jouw waarden)
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
NODE_ENV=production \
PORT=3001 \
DATABASE_TYPE=postgres \
DATABASE_HOST=zdl-cmdb-insight-prd-psql.postgres.database.azure.com \
DATABASE_PORT=5432 \
DATABASE_NAME=cmdb_insight \
DATABASE_USER=cmdbadmin \
DATABASE_PASSWORD=your-database-password \
DATABASE_SSL=true \
JIRA_BASE_URL=https://jira.zuyderland.nl \
JIRA_SCHEMA_ID=your-schema-id \
JIRA_PAT=your-pat-token \
SESSION_SECRET=$(openssl rand -hex 32) \
FRONTEND_URL=https://zdl-cmdb-insight-prd-frontend-webapp.azurewebsites.net
# Frontend
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-frontend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
VITE_API_URL=https://zdl-cmdb-insight-prd-backend-webapp.azurewebsites.net/api
```
### Stap 5b: Environment Variabelen met SQLite (Alternatief)
```bash
# Backend met SQLite (vervang met jouw waarden)
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
NODE_ENV=production \
PORT=3001 \
DATABASE_TYPE=sqlite \
JIRA_BASE_URL=https://jira.zuyderland.nl \
JIRA_SCHEMA_ID=your-schema-id \
JIRA_PAT=your-pat-token \
SESSION_SECRET=$(openssl rand -hex 32) \
FRONTEND_URL=https://zdl-cmdb-insight-prd-frontend-webapp.azurewebsites.net
# Frontend
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-frontend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
VITE_API_URL=https://zdl-cmdb-insight-prd-backend-webapp.azurewebsites.net/api
```
### Stap 6: Start Apps
```bash
az webapp start --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
az webapp start --name zdl-cmdb-insight-prd-frontend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
```
### Stap 7: Test
```bash
# Health check
curl https://zdl-cmdb-insight-prd-backend-webapp.azurewebsites.net/api/health
# Frontend
curl https://zdl-cmdb-insight-prd-frontend-webapp.azurewebsites.net
```
**🎉 Je applicatie is nu live!**
- Frontend: `https://zdl-cmdb-insight-prd-frontend-webapp.azurewebsites.net`
- Backend API: `https://zdl-cmdb-insight-prd-backend-webapp.azurewebsites.net/api`
---
## 🔐 Azure Key Vault Setup (Aanbevolen)
Voor productie: gebruik Azure Key Vault voor secrets.
### Stap 1: Key Vault Aanmaken
```bash
az keyvault create \
--name kv-cmdb-insight-prod \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--location westeurope \
--sku standard
```
### Stap 2: Secrets Toevoegen
```bash
az keyvault secret set --vault-name kv-cmdb-insight-prod --name JiraPat --value "your-token"
az keyvault secret set --vault-name kv-cmdb-insight-prod --name SessionSecret --value "$(openssl rand -hex 32)"
az keyvault secret set --vault-name kv-cmdb-insight-prod --name JiraSchemaId --value "your-schema-id"
```
### Stap 3: Grant Access
**Voor Key Vault met RBAC authorization (aanbevolen):**
```bash
# Get Key Vault Resource ID
KV_ID=$(az keyvault show --name zdl-cmdb-insight-prd-kv --query id -o tsv)
# Grant Key Vault Secrets User role to backend
az role assignment create \
--assignee $BACKEND_PRINCIPAL_ID \
--role "Key Vault Secrets User" \
--scope $KV_ID
# Grant to frontend (if needed)
az role assignment create \
--assignee $FRONTEND_PRINCIPAL_ID \
--role "Key Vault Secrets User" \
--scope $KV_ID
```
**Voor Key Vault met Access Policies (oude methode):**
```bash
az keyvault set-policy \
--name zdl-cmdb-insight-prd-kv \
--object-id $BACKEND_PRINCIPAL_ID \
--secret-permissions get list
```
**Let op:** Als je de fout krijgt "Cannot set policies to a vault with '--enable-rbac-authorization'", gebruik dan de RBAC methode hierboven.
### Stap 4: Configure App Settings met Key Vault References
```bash
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
JIRA_PAT="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-insight-prod.vault.azure.net/secrets/JiraPat/)" \
SESSION_SECRET="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-insight-prod.vault.azure.net/secrets/SessionSecret/)" \
JIRA_SCHEMA_ID="@Microsoft.KeyVault(SecretUri=https://kv-cmdb-insight-prod.vault.azure.net/secrets/JiraSchemaId/)"
```
---
## 📊 Monitoring Setup
### Application Insights
```bash
# Create Application Insights
az monitor app-insights component create \
--app cmdb-insight-prod \
--location westeurope \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--application-type web
# Get Instrumentation Key
INSTRUMENTATION_KEY=$(az monitor app-insights component show \
--app cmdb-insight-prod \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--query instrumentationKey -o tsv)
# Configure App Settings
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--settings \
APPINSIGHTS_INSTRUMENTATIONKEY=$INSTRUMENTATION_KEY
```
---
## 🔄 Updates Deployen
### Optie 1: Manual (Eenvoudig)
```bash
# Restart Web Apps (pull nieuwe latest image)
az webapp restart --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
az webapp restart --name zdl-cmdb-insight-prd-frontend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
```
### Optie 2: Deployment Slots (Zero-Downtime)
```bash
# Create staging slot
az webapp deployment slot create \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--slot staging
# Deploy to staging
az webapp deployment slot swap \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group zdl-cmdb-insight-prd-euwe-rg \
--slot staging \
--target-slot production
```
---
## 🛠️ Troubleshooting
### Check Logs
```bash
# Live logs
az webapp log tail --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
# Download logs
az webapp log download --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg --log-file logs.zip
```
### Check Status
```bash
az webapp show --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg --query state
```
### Restart App
```bash
az webapp restart --name zdl-cmdb-insight-prd-backend-webapp --resource-group zdl-cmdb-insight-prd-euwe-rg
```
---
## 📚 Meer Informatie
- **Quick Reference**: `docs/AZURE-QUICK-REFERENCE.md`
- **Production Deployment**: `docs/PRODUCTION-DEPLOYMENT.md`
---
## ✅ Checklist
- [ ] Resource Group aangemaakt
- [ ] App Service Plan aangemaakt
- [ ] Web Apps aangemaakt
- [ ] ACR authentication geconfigureerd
- [ ] Environment variabelen ingesteld
- [ ] Key Vault geconfigureerd (optioneel)
- [ ] Application Insights ingeschakeld
- [ ] Health checks werken
- [ ] Team geïnformeerd
**Veel succes! 🚀**

View File

@@ -0,0 +1,275 @@
# Azure Pipelines Usage Guide
Guide for using the separate build and deployment pipelines.
## 📋 Quick Reference
### Pipeline Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `acrName` | Azure Container Registry name | `zdlas` |
| `repositoryName` | Docker repository name | `cmdb-insight` |
| `dockerRegistryServiceConnection` | ACR service connection name | `zuyderland-cmdb-acr-connection` |
| `resourceGroup` | Azure resource group | `rg-cmdb-insight-prod` |
| `backendAppName` | Backend App Service name | `cmdb-backend-prod` |
| `frontendAppName` | Frontend App Service name | `cmdb-frontend-prod` |
| `azureSubscription` | Azure service connection for deployment | `zuyderland-cmdb-subscription` |
| `deployToProduction` | Enable/disable deployment | `true` or `false` |
| `useDeploymentSlots` | Use staging slots for zero-downtime | `true` or `false` |
### Required Service Connections
1. **Docker Registry Connection** (for ACR)
- Type: Docker Registry → Azure Container Registry
- Name: Match `dockerRegistryServiceConnection` variable
- Authentication: **Service Principal** (not Managed Identity)
2. **Azure Resource Manager Connection** (for App Service deployment)
- Type: Azure Resource Manager
- Name: Match `azureSubscription` variable
- Authentication: Managed Identity or Service Principal
---
## 📋 Pipeline Files
### 1. `azure-pipelines.yml` - Build and Push Images
**Purpose**: Builds Docker images and pushes them to Azure Container Registry.
**What it does:**
- ✅ Builds backend Docker image
- ✅ Builds frontend Docker image
- ✅ Pushes both to ACR with tags: `$(Build.BuildId)` and `latest`
**When to use:**
- First time setup (to test image building)
- After code changes (to build new images)
- Before deployment (to ensure images are in ACR)
**Configuration:**
```yaml
variables:
acrName: 'zdlas' # Your ACR name
repositoryName: 'cmdb-insight'
dockerRegistryServiceConnection: 'zuyderland-cmdb-acr-connection'
```
### 2. `azure-pipelines-deploy.yml` - Deploy to App Service
**Purpose**: Deploys existing images from ACR to Azure App Services.
**What it does:**
- ✅ Deploys backend container to App Service
- ✅ Deploys frontend container to App Service
- ✅ Restarts both App Services
- ✅ Verifies deployment with health checks
**When to use:**
- After images are built and pushed to ACR
- When you want to deploy/update the application
- For production deployments
**Configuration:**
```yaml
variables:
acrName: 'zdlas' # Your ACR name
resourceGroup: 'rg-cmdb-insight-prod' # Your resource group
backendAppName: 'cmdb-backend-prod' # Your backend app name
frontendAppName: 'cmdb-frontend-prod' # Your frontend app name
azureSubscription: 'zuyderland-cmdb-subscription' # Azure service connection
imageTag: 'latest' # Image tag to deploy
```
## 🚀 Workflow
### Step 1: Build and Push Images
1. **Configure `azure-pipelines.yml`**:
- Update `acrName` with your ACR name
- Update `dockerRegistryServiceConnection` with your service connection name
2. **Create Pipeline in Azure DevOps**:
- Go to **Pipelines****New pipeline**
- Select **Existing Azure Pipelines YAML file**
- Choose `azure-pipelines.yml`
- Run the pipeline
3. **Verify Images in ACR**:
```bash
az acr repository list --name zdlas
az acr repository show-tags --name zdlas --repository cmdb-insight/backend
az acr repository show-tags --name zdlas --repository cmdb-insight/frontend
```
### Step 2: Deploy Application
1. **Ensure App Services exist**:
- Backend App Service: `cmdb-backend-prod`
- Frontend App Service: `cmdb-frontend-prod`
- See `AZURE-NEW-SUBSCRIPTION-SETUP.md` for setup instructions
2. **Configure `azure-pipelines-deploy.yml`**:
- Update all variables with your Azure resource names
- Create Azure service connection for App Service deployment
- Create `production` environment in Azure DevOps
3. **Create Deployment Pipeline**:
- Go to **Pipelines** → **New pipeline**
- Select **Existing Azure Pipelines YAML file**
- Choose `azure-pipelines-deploy.yml`
- Run the pipeline
4. **Verify Deployment**:
- Check backend: `https://cmdb-backend-prod.azurewebsites.net/api/health`
- Check frontend: `https://cmdb-frontend-prod.azurewebsites.net`
## 🔧 Setup Requirements
### For Build Pipeline (`azure-pipelines.yml`)
**Required:**
- ✅ Docker Registry service connection (for ACR)
- ✅ ACR exists and is accessible
- ✅ Service connection has push permissions
**Setup:**
1. Create Docker Registry service connection:
- **Project Settings** → **Service connections** → **New service connection**
- Choose **Docker Registry** → **Azure Container Registry**
- Select your ACR
- Name: `zuyderland-cmdb-acr-connection`
### For Deployment Pipeline (`azure-pipelines-deploy.yml`)
**Required:**
- ✅ Azure Resource Manager service connection
- ✅ App Services exist in Azure
- ✅ `production` environment created in Azure DevOps
- ✅ Images exist in ACR
**Setup:**
1. Create Azure service connection:
- **Project Settings** → **Service connections** → **New service connection**
- Choose **Azure Resource Manager**
- Select your subscription
- Name: `zuyderland-cmdb-subscription`
2. Create environment:
- **Pipelines** → **Environments** → **Create environment**
- Name: `production`
- (Optional) Add approvals for manual control
## 📝 Typical Usage Scenarios
### Scenario 1: First Time Setup
```bash
# 1. Build and push images
# Run azure-pipelines.yml → Images in ACR
# 2. Create App Services (manual or via script)
# See AZURE-NEW-SUBSCRIPTION-SETUP.md
# 3. Deploy application
# Run azure-pipelines-deploy.yml → App deployed
```
### Scenario 2: Code Update
```bash
# 1. Push code to main branch
git push origin main
# 2. Build pipeline runs automatically
# azure-pipelines.yml → New images in ACR
# 3. Deploy new version
# Run azure-pipelines-deploy.yml → App updated
```
### Scenario 3: Deploy Specific Version
```bash
# 1. Update azure-pipelines-deploy.yml
imageTag: 'v1.0.0' # Or specific build ID
# 2. Run deployment pipeline
# Deploys specific version
```
## 🔄 Combining Pipelines (Future)
Once you're comfortable with both pipelines, you can:
1. **Combine them** into one pipeline with conditional deployment
2. **Use deployment slots** for zero-downtime updates
3. **Add approval gates** for production deployments
See `azure-pipelines-slots.yml` for an advanced example with deployment slots.
## 🛠️ Troubleshooting
### Build Pipeline Fails
**Issue**: "Service connection not found"
- **Solution**: Verify service connection name matches `dockerRegistryServiceConnection` variable
- Check: **Project Settings** → **Service connections** → Verify name matches
**Issue**: "ACR not found"
- **Solution**: Check `acrName` variable matches your ACR name
- Verify: `az acr list --query "[].name"`
**Issue**: "MSI Authentication Error" / "Could not fetch access token for Managed Service Principal"
- **Solution**: Service connection must use **Service Principal** authentication (not Managed Identity)
- Recreate service connection: **Docker Registry** → **Azure Container Registry** → Use **Service Principal**
- See `docs/AZURE-SERVICE-CONNECTION-TROUBLESHOOTING.md` for details
**Issue**: "Permission denied"
- **Solution**: Verify service connection has correct permissions
- Check ACR admin is enabled: `az acr update --name <acr-name> --admin-enabled true`
### Deployment Pipeline Fails
**Issue**: "App Service not found"
- **Solution**: Verify app names match your Azure resources
- Check: `az webapp list --query "[].name"`
**Issue**: "Environment not found"
- **Solution**: Create `production` environment in Azure DevOps
- **Pipelines** → **Environments** → **Create environment**
**Issue**: "Image not found in ACR"
- **Solution**: Run build pipeline first to push images to ACR
- Verify: `az acr repository show-tags --name <acr-name> --repository cmdb-insight/backend`
### Repository Not Found
**Issue**: "No matching repositories were found" when creating pipeline
- **Solution 1**: Check repository exists in Azure DevOps → **Repos** → **Files**
- **Solution 2**: Push code to Azure DevOps: `git push azure main`
- **Solution 3**: Use **"Other Git"** option in pipeline wizard with repository URL
- **Solution 4**: Verify you're in the correct project (check project name in dropdown)
- See `docs/AZURE-SERVICE-CONNECTION-TROUBLESHOOTING.md` for details
## ✅ Checklist
### Build Pipeline Setup
- [ ] Docker Registry service connection created
- [ ] `azure-pipelines.yml` variables configured
- [ ] Pipeline created in Azure DevOps
- [ ] Test run successful
- [ ] Images visible in ACR
### Deployment Pipeline Setup
- [ ] Azure Resource Manager service connection created
- [ ] `production` environment created
- [ ] App Services exist in Azure
- [ ] `azure-pipelines-deploy.yml` variables configured
- [ ] Deployment pipeline created in Azure DevOps
- [ ] Test deployment successful
---
**Workflow**: Build first → Deploy second → Verify success!

View File

@@ -0,0 +1,371 @@
# Azure PostgreSQL Setup for Production
Complete guide for setting up Azure Database for PostgreSQL Flexible Server for CMDB Insight production deployment.
## 🎯 Overview
**Why PostgreSQL for Production?**
- ✅ Better concurrency handling (multiple users)
- ✅ Connection pooling support
- ✅ Better performance for 20+ users
- ✅ Production-ready database solution
- ✅ Identical dev/prod stack
**Cost:** ~€20-30/month (Basic B1ms tier)
---
## 📋 Prerequisites
- Azure CLI installed and configured (`az login`)
- Resource group created: `zdl-cmdb-insight-prd-euwe-rg`
- Appropriate permissions to create Azure Database resources
---
## 🚀 Quick Setup (15 minutes)
### Step 1: Create PostgreSQL Flexible Server
```bash
# Set variables
RESOURCE_GROUP="zdl-cmdb-insight-prd-euwe-rg"
SERVER_NAME="zdl-cmdb-insight-prd-psql"
ADMIN_USER="cmdbadmin"
ADMIN_PASSWORD="$(openssl rand -base64 32)" # Generate secure password
LOCATION="westeurope"
# Create PostgreSQL Flexible Server
az postgres flexible-server create \
--resource-group $RESOURCE_GROUP \
--name $SERVER_NAME \
--location $LOCATION \
--admin-user $ADMIN_USER \
--admin-password $ADMIN_PASSWORD \
--sku-name Standard_B1ms \
--tier Burstable \
--storage-size 32 \
--version 15 \
--public-access 0.0.0.0 \
--high-availability Disabled
echo "PostgreSQL server created!"
echo "Server: $SERVER_NAME.postgres.database.azure.com"
echo "Admin User: $ADMIN_USER"
echo "Password: $ADMIN_PASSWORD"
echo ""
echo "⚠️ Save the password securely!"
```
### Step 2: Create Database
**Note:** The application uses a single database for all data. All tables (CMDB cache, classification history, and session state) are stored in the same database.
```bash
# Create main database (this is all you need)
az postgres flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name $SERVER_NAME \
--database-name cmdb_insight
echo "✅ Database created"
```
### Step 3: Configure Firewall Rules
Allow Azure App Service to connect:
```bash
# Get App Service outbound IPs
BACKEND_IPS=$(az webapp show \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group $RESOURCE_GROUP \
--query "outboundIpAddresses" -o tsv)
# Add firewall rule for App Service (use first IP, or add all)
az postgres flexible-server firewall-rule create \
--resource-group $RESOURCE_GROUP \
--name $SERVER_NAME \
--rule-name AllowAppService \
--start-ip-address 0.0.0.0 \
--end-ip-address 255.255.255.255
# Or more secure: Allow Azure Services only
az postgres flexible-server firewall-rule create \
--resource-group $RESOURCE_GROUP \
--name $SERVER_NAME \
--rule-name AllowAzureServices \
--start-ip-address 0.0.0.0 \
--end-ip-address 0.0.0.0
```
**Note:** `0.0.0.0` to `0.0.0.0` allows all Azure services. For production, consider using specific App Service outbound IPs.
### Step 4: Store Credentials in Key Vault
```bash
KEY_VAULT="zdl-cmdb-insight-prd-kv"
# Store database password
az keyvault secret set \
--vault-name $KEY_VAULT \
--name DatabasePassword \
--value $ADMIN_PASSWORD
# Store connection string (optional, can construct from components)
CONNECTION_STRING="postgresql://${ADMIN_USER}:${ADMIN_PASSWORD}@${SERVER_NAME}.postgres.database.azure.com:5432/cmdb_insight?sslmode=require"
az keyvault secret set \
--vault-name $KEY_VAULT \
--name DatabaseUrl \
--value $CONNECTION_STRING
echo "✅ Credentials stored in Key Vault"
```
### Step 5: Configure App Service App Settings
```bash
# Get Key Vault URL
KV_URL=$(az keyvault show --name $KEY_VAULT --query properties.vaultUri -o tsv)
# Configure backend app settings
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group $RESOURCE_GROUP \
--settings \
DATABASE_TYPE=postgres \
DATABASE_HOST="${SERVER_NAME}.postgres.database.azure.com" \
DATABASE_PORT=5432 \
DATABASE_NAME=cmdb_insight \
DATABASE_USER=$ADMIN_USER \
DATABASE_PASSWORD="@Microsoft.KeyVault(SecretUri=${KV_URL}secrets/DatabasePassword/)" \
DATABASE_SSL=true
echo "✅ App settings configured"
```
**Alternative: Use DATABASE_URL directly**
```bash
az webapp config appsettings set \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group $RESOURCE_GROUP \
--settings \
DATABASE_TYPE=postgres \
DATABASE_URL="@Microsoft.KeyVault(SecretUri=${KV_URL}secrets/DatabaseUrl/)"
```
---
## 🔐 Security Best Practices
### 1. Use Key Vault for Secrets
**Do:** Store database password in Key Vault
**Don't:** Store password in app settings directly
### 2. Enable SSL/TLS
**Do:** Always use `DATABASE_SSL=true` or `?sslmode=require` in connection string
**Don't:** Connect without SSL in production
### 3. Firewall Rules
**Do:** Restrict to specific IPs or Azure services
**Don't:** Allow `0.0.0.0/0` (all IPs) unless necessary
### 4. Use Managed Identity (Advanced)
For even better security, use Managed Identity instead of passwords:
```bash
# Enable Managed Identity on PostgreSQL server
az postgres flexible-server identity assign \
--resource-group $RESOURCE_GROUP \
--name $SERVER_NAME \
--identity /subscriptions/.../resourceGroups/.../providers/Microsoft.ManagedIdentity/userAssignedIdentities/...
# Grant access
az postgres flexible-server ad-admin create \
--resource-group $RESOURCE_GROUP \
--server-name $SERVER_NAME \
--display-name "App Service Identity" \
--object-id <principal-id>
```
---
## 📊 Database Configuration
### Connection Pooling
The application uses connection pooling automatically via the `pg` library:
- **Max connections:** 20 (configured in `PostgresAdapter`)
- **Idle timeout:** 30 seconds
- **Connection timeout:** 10 seconds
### Database Sizes
For 20 users:
- **Database (cmdb_insight):** ~25-60MB total (includes CMDB cache, classification history, and session state)
- **Total storage:** 32GB (plenty of room for growth)
**Note:** All data (CMDB objects, classification history, and session state) is stored in a single database.
---
## 🔄 Migration from SQLite
If you're migrating from SQLite to PostgreSQL:
```bash
# 1. Export data from SQLite (if needed)
# The application will automatically sync from Jira, so migration may not be necessary
# 2. Set DATABASE_TYPE=postgres in app settings
# 3. Restart the app - it will create tables automatically on first run
# 4. The app will sync data from Jira Assets on first sync
```
**Note:** Since the database is a cache layer that syncs from Jira, you typically don't need to migrate data - just let it sync fresh.
---
## 🧪 Testing Connection
### Test from Local Machine
```bash
# Install psql if needed
# macOS: brew install postgresql
# Ubuntu: sudo apt-get install postgresql-client
# Connect (replace with your values)
psql "host=${SERVER_NAME}.postgres.database.azure.com port=5432 dbname=cmdb_insight user=${ADMIN_USER} password=${ADMIN_PASSWORD} sslmode=require"
```
### Test from App Service
```bash
# Check app logs
az webapp log tail \
--name zdl-cmdb-insight-prd-backend-webapp \
--resource-group $RESOURCE_GROUP
# Look for: "Creating PostgreSQL adapter" or connection errors
```
---
## 📈 Monitoring
### Check Database Status
```bash
az postgres flexible-server show \
--resource-group $RESOURCE_GROUP \
--name $SERVER_NAME \
--query "{state:state, version:version, sku:sku}"
```
### View Database Size
```sql
-- Connect to database
SELECT
pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database
WHERE datname = 'cmdb_insight';
```
### Monitor Connections
```sql
SELECT
count(*) as total_connections,
state,
application_name
FROM pg_stat_activity
WHERE datname = 'cmdb_insight'
GROUP BY state, application_name;
```
---
## 💰 Cost Optimization
### Current Setup (Recommended)
- **Tier:** Burstable (B1ms)
- **vCores:** 1
- **RAM:** 2GB
- **Storage:** 32GB
- **Cost:** ~€20-30/month
### If You Need More Performance
- **Upgrade to:** Standard_B2s (2 vCores, 4GB RAM) - ~€40-50/month
- **Or:** Standard_B1ms with more storage if needed
### Cost Savings Tips
1. **Use Burstable tier** - Perfect for 20 users
2. **Start with 32GB storage** - Can scale up later
3. **Disable high availability** - Not needed for small teams
4. **Use same region** - Reduces latency and costs
---
## 🛠️ Troubleshooting
### Connection Refused
**Problem:** Can't connect to database
**Solutions:**
1. Check firewall rules: `az postgres flexible-server firewall-rule list --resource-group $RESOURCE_GROUP --name $SERVER_NAME`
2. Verify SSL is enabled: `DATABASE_SSL=true`
3. Check credentials in Key Vault
### Authentication Failed
**Problem:** Wrong username/password
**Solutions:**
1. Verify admin user: `az postgres flexible-server show --resource-group $RESOURCE_GROUP --name $SERVER_NAME --query administratorLogin`
2. Reset password if needed: `az postgres flexible-server update --resource-group $RESOURCE_GROUP --name $SERVER_NAME --admin-password "new-password"`
### SSL Required Error
**Problem:** "SSL connection required"
**Solution:** Add `DATABASE_SSL=true` or `?sslmode=require` to connection string
---
## 📚 Related Documentation
- **`docs/AZURE-APP-SERVICE-DEPLOYMENT.md`** - Complete App Service deployment
- **`docs/DATABASE-RECOMMENDATION.md`** - Database comparison and recommendations
- **`docs/LOCAL-DEVELOPMENT-SETUP.md`** - Local PostgreSQL setup
---
## ✅ Checklist
- [ ] PostgreSQL Flexible Server created
- [ ] Database created (cmdb_insight)
- [ ] Firewall rules configured
- [ ] Credentials stored in Key Vault
- [ ] App Service app settings configured
- [ ] SSL enabled (`DATABASE_SSL=true`)
- [ ] Connection tested
- [ ] Monitoring configured
---
**🎉 Your PostgreSQL database is ready for production!**

View File

@@ -0,0 +1,177 @@
# Azure Deployment - Quick Reference
## 🎯 In één oogopslag
**Applicatie**: CMDB Insight (Node.js + React web app)
**Doel**: Hosten in Azure App Service
**Gebruikers**: Max. 20 collega's
**Geschatte kosten**: €18-39/maand (Basic tier)
**Complexiteit**: Laag (eenvoudige web app deployment)
---
## 📦 Wat hebben we nodig?
### Core Services
-**Azure App Service Plan (B1)**: Gedeeld tussen Backend + Frontend
-**Azure Key Vault**: Voor secrets (OAuth, API keys)
-**Database**: PostgreSQL (aanbevolen) of SQLite (huidige)
- PostgreSQL: Azure Database for PostgreSQL (B1ms) - €20-30/maand
- SQLite: Azure Storage - €1-3/maand
-**Application Insights (Basic)**: Monitoring & logging (gratis tot 5GB/maand)
### Networking
-**HTTPS**: SSL certificaat (App Service Certificate of Let's Encrypt)
-**DNS**: Subdomain (bijv. `cmdb.zuyderland.nl`)
-**Outbound**: Toegang naar `jira.zuyderland.nl` (HTTPS)
### Security
-**OAuth 2.0**: Authenticatie via Jira
-**Secrets**: Alles in Key Vault
-**HTTPS Only**: Geen HTTP toegang
---
## 💰 Kosten Breakdown
**Optie 1: Met SQLite (huidige setup)**
| Item | Maandelijks |
|------|-------------|
| App Service Plan (B1) | €15-25 |
| Application Insights (Basic) | €0-5 |
| Storage + Key Vault | €2-5 |
| **Totaal** | **€17-35** |
**Optie 2: Met PostgreSQL (aanbevolen voor identieke dev/prod)**
| Item | Maandelijks |
|------|-------------|
| App Service Plan (B1) | €15-25 |
| PostgreSQL Database (B1ms) | €20-30 |
| Application Insights (Basic) | €0-5 |
| Key Vault | €1-2 |
| **Totaal** | **€36-62** |
*Zie `DATABASE-RECOMMENDATION.md` voor volledige vergelijking*
*Backup niet nodig - data sync vanuit Jira Assets*
---
## ⚙️ Technische Details
**Backend:**
- Node.js 20, Express API
- Poort: 3001 (intern)
- Health check: `/health` endpoint
- Database: SQLite (~20MB - huidige grootte)
- **Resources**: 1 vCPU, 1.75GB RAM (B1 tier - voldoende)
- **Backup**: Niet nodig - data sync vanuit Jira Assets
**Frontend:**
- React SPA
- Static files via App Service
- API calls naar backend via `/api/*`
**Dependencies:**
- Jira Assets API (outbound HTTPS)
- Anthropic API (optioneel, voor AI features)
---
## 🚀 Deployment Opties
### Optie 1: Azure App Service Basic (Aanbevolen) ⭐
- **Pro**: Eenvoudig, managed service, goedkoop, voldoende voor 20 gebruikers
- **Con**: Geen auto-scaling (niet nodig), minder flexibel dan containers
- **Tijd**: 1 dag setup
- **Kosten**: €18-39/maand
### Optie 2: Azure Container Instances (ACI)
- **Pro**: Snelle setup, container-based
- **Con**: Duurder dan App Service, minder managed features
- **Tijd**: 1 dag setup
- **Kosten**: €30-50/maand
**Niet aanbevolen voor 20 gebruikers** - App Service is goedkoper en eenvoudiger.
---
## ❓ Vragen voor Jullie
1. **DNS**: Kunnen we `cmdb.zuyderland.nl` krijgen?
2. **SSL**: App Service Certificate of Let's Encrypt?
3. **Network**: Direct internet of via VPN/ExpressRoute?
4. **Monitoring**: Nieuwe workspace of bestaande?
5. **Backup**: Niet nodig - data wordt gesynchroniseerd vanuit Jira Assets
6. **Compliance**: Specifieke requirements? (NEN 7510, ISO 27001)
---
## 📋 Checklist voor Go-Live
- [ ] Resource Group aangemaakt
- [ ] App Service Plan geconfigureerd
- [ ] 2x Web Apps aangemaakt (backend + frontend)
- [ ] Key Vault aangemaakt met secrets
- [ ] Storage Account voor database
- [ ] SSL certificaat geconfigureerd
- [ ] DNS record aangemaakt
- [ ] Application Insights geconfigureerd
- [ ] Health checks getest
- [ ] Monitoring alerts ingesteld
---
## 📝 Belangrijke Notities
**Schaalbaarheid**: Deze setup is geoptimaliseerd voor **max. 20 gebruikers**.
- Basic B1 tier (1 vCPU, 1.75GB RAM) is ruim voldoende
- Geen auto-scaling nodig
- Geen load balancer nodig
- Eenvoudige, kosteneffectieve oplossing
**Als het aantal gebruikers groeit** (>50 gebruikers), overweeg dan:
- Upgrade naar B2 tier (€50-75/maand)
- Of Standard S1 tier voor betere performance
---
## 📋 Deployment Stappen Overzicht
### 1. Azure Resources Aanmaken
```bash
# Resource Group
az group create --name rg-cmdb-gui --location westeurope
# App Service Plan (Basic B1)
az appservice plan create --name plan-cmdb-gui --resource-group rg-cmdb-gui --sku B1 --is-linux
# Web Apps
az webapp create --name cmdb-backend --resource-group rg-cmdb-gui --plan plan-cmdb-gui
az webapp create --name cmdb-frontend --resource-group rg-cmdb-gui --plan plan-cmdb-gui
# Key Vault
az keyvault create --name kv-cmdb-gui --resource-group rg-cmdb-gui --location westeurope
```
### 2. Database Setup
- **PostgreSQL (Aanbevolen)**: Zie `docs/AZURE-POSTGRESQL-SETUP.md`
- **SQLite**: Geen extra setup nodig (database in container)
### 3. Configuration
- Environment variabelen via App Service Configuration
- Secrets via Key Vault references
- SSL certificaat via App Service (automatisch voor *.azurewebsites.net)
### 4. CI/CD
- Azure DevOps Pipelines: Zie `docs/AZURE-PIPELINES.md`
- Automatische deployment bij push naar main branch
---
## 📞 Contact & Documentatie
Voor volledige deployment guides, zie:
- `docs/AZURE-APP-SERVICE-DEPLOYMENT.md` - Complete stap-voor-stap guide
- `docs/AZURE-POSTGRESQL-SETUP.md` - Database setup
- `docs/AZURE-PIPELINES.md` - CI/CD pipelines
- `docs/PRODUCTION-DEPLOYMENT.md` - Production best practices

View File

@@ -0,0 +1,592 @@
# Green Field Deployment Guide
## Overzicht
Deze guide beschrijft hoe je de applicatie volledig opnieuw deployt met de nieuwe genormaliseerde database structuur. Aangezien het een green field deployment is, kunnen we alles schoon opzetten.
---
## Stap 1: Database Setup
### Option A: PostgreSQL (Aanbevolen voor productie)
#### 1.1 Azure Database for PostgreSQL
```bash
# Via Azure Portal of CLI
az postgres flexible-server create \
--resource-group <resource-group> \
--name <server-name> \
--location <location> \
--admin-user <admin-user> \
--admin-password <admin-password> \
--sku-name Standard_B1ms \
--tier Burstable \
--version 14
```
#### 1.2 Database Aanmaken
**Note:** The application uses a single database for all data. All tables (CMDB cache, classification history, and session state) are stored in the same database.
```sql
-- Connect to PostgreSQL
CREATE DATABASE cmdb_insight;
-- Create user (optional, can use admin user)
CREATE USER cmdb_user WITH PASSWORD 'secure_password';
GRANT ALL PRIVILEGES ON DATABASE cmdb_insight TO cmdb_user;
```
#### 1.3 Connection String
```env
DATABASE_TYPE=postgres
DATABASE_URL=postgresql://cmdb_user:secure_password@<server-name>.postgres.database.azure.com:5432/cmdb_insight?sslmode=require
```
### Option B: SQLite (Voor development/testing)
```env
DATABASE_TYPE=sqlite
# Database files worden automatisch aangemaakt in backend/data/
```
---
## Stap 2: Environment Variables
### 2.1 Basis Configuratie
Maak `.env` bestand in project root:
```env
# Server
PORT=3001
NODE_ENV=production
FRONTEND_URL=https://your-domain.com
# Database (zie Stap 1)
DATABASE_TYPE=postgres
DATABASE_URL=postgresql://...
# Jira Assets
JIRA_HOST=https://jira.zuyderland.nl
JIRA_SCHEMA_ID=<your_schema_id>
JIRA_SERVICE_ACCOUNT_TOKEN=<service_account_token>
# Jira Authentication Method
JIRA_AUTH_METHOD=oauth
# OAuth Configuration (als JIRA_AUTH_METHOD=oauth)
JIRA_OAUTH_CLIENT_ID=<client_id>
JIRA_OAUTH_CLIENT_SECRET=<client_secret>
JIRA_OAUTH_CALLBACK_URL=https://your-domain.com/api/auth/callback
JIRA_OAUTH_SCOPES=READ WRITE
# Session
SESSION_SECRET=<generate_secure_random_string>
# AI (configureer per gebruiker in profile settings)
# ANTHROPIC_API_KEY, OPENAI_API_KEY, TAVILY_API_KEY worden per gebruiker ingesteld
```
### 2.2 Session Secret Genereren
```bash
# Generate secure random string
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
---
## Stap 3: Schema Discovery
### 3.1 Schema Genereren
```bash
cd backend
npm run generate-schema
```
Dit:
- Haalt schema op van Jira Assets API
- Genereert `backend/src/generated/jira-schema.ts`
- Genereert `backend/src/generated/jira-types.ts`
### 3.2 Schema Populeren in Database
Bij eerste start van de applicatie:
- `schemaDiscoveryService` leest `OBJECT_TYPES` uit generated schema
- Populeert `object_types` en `attributes` tabellen
- Gebeurt automatisch bij initialisatie
---
## Stap 4: Application Build
### 4.1 Dependencies Installeren
```bash
# Root
npm install
# Backend
cd backend
npm install
# Frontend
cd frontend
npm install
```
### 4.2 Build
```bash
# Backend
cd backend
npm run build
# Frontend
cd frontend
npm run build
```
---
## Stap 5: Database Initialisatie
### 5.1 Automatische Initialisatie
Bij eerste start:
1. Normalized schema wordt aangemaakt
2. Schema discovery wordt uitgevoerd
3. Tabellen worden gevuld met object types en attributes
### 5.2 Handmatige Verificatie (Optioneel)
```sql
-- Check object types
SELECT * FROM object_types ORDER BY sync_priority;
-- Check attributes
SELECT COUNT(*) FROM attributes;
-- Check per type
SELECT object_type_name, COUNT(*) as attr_count
FROM attributes
GROUP BY object_type_name;
```
---
## Stap 6: Data Sync
### 6.1 Eerste Sync
```bash
# Via API (na deployment)
curl -X POST https://your-domain.com/api/cache/sync \
-H "Authorization: Bearer <token>"
```
Of via applicatie:
- Ga naar Settings → Cache Management
- Klik "Full Sync"
### 6.2 Sync Status Checken
```bash
curl https://your-domain.com/api/cache/status \
-H "Authorization: Bearer <token>"
```
---
## Stap 7: Docker Deployment
### 7.1 Build Images
```bash
# Backend
docker build -t cmdb-backend:latest -f backend/Dockerfile .
# Frontend
docker build -t cmdb-frontend:latest -f frontend/Dockerfile .
```
### 7.2 Docker Compose (Production)
```yaml
# docker-compose.prod.yml
version: '3.8'
services:
backend:
image: cmdb-backend:latest
environment:
- DATABASE_TYPE=postgres
- DATABASE_URL=${DATABASE_URL}
- JIRA_HOST=${JIRA_HOST}
- JIRA_SCHEMA_ID=${JIRA_SCHEMA_ID}
- JIRA_SERVICE_ACCOUNT_TOKEN=${JIRA_SERVICE_ACCOUNT_TOKEN}
- SESSION_SECRET=${SESSION_SECRET}
ports:
- "3001:3001"
frontend:
image: cmdb-frontend:latest
ports:
- "80:80"
depends_on:
- backend
nginx:
image: nginx:alpine
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- "443:443"
depends_on:
- frontend
- backend
```
### 7.3 Starten
```bash
docker-compose -f docker-compose.prod.yml up -d
```
---
## Stap 8: Azure App Service Deployment
### 8.1 Azure Container Registry
```bash
# Login
az acr login --name <registry-name>
# Tag images
docker tag cmdb-backend:latest <registry-name>.azurecr.io/cmdb-backend:latest
docker tag cmdb-frontend:latest <registry-name>.azurecr.io/cmdb-frontend:latest
# Push
docker push <registry-name>.azurecr.io/cmdb-backend:latest
docker push <registry-name>.azurecr.io/cmdb-frontend:latest
```
### 8.2 App Service Configuratie
**Backend App Service:**
- Container: `<registry-name>.azurecr.io/cmdb-backend:latest`
- Environment variables: Alle `.env` variabelen
- Port: 3001
**Frontend App Service:**
- Container: `<registry-name>.azurecr.io/cmdb-frontend:latest`
- Environment variables: `VITE_API_URL=https://backend-app.azurewebsites.net`
### 8.3 Deployment via Azure DevOps
Zie `azure-pipelines.yml` voor CI/CD pipeline.
---
## Stap 9: Verificatie
### 9.1 Health Checks
```bash
# Backend health
curl https://backend-app.azurewebsites.net/health
# Frontend
curl https://frontend-app.azurewebsites.net
```
### 9.2 Database Verificatie
```sql
-- Check object count
SELECT object_type_name, COUNT(*) as count
FROM objects
GROUP BY object_type_name;
-- Check attribute values
SELECT COUNT(*) FROM attribute_values;
-- Check relations
SELECT COUNT(*) FROM object_relations;
```
### 9.3 Functionaliteit Testen
1. **Login** - Test authenticatie
2. **Dashboard** - Check of data wordt getoond
3. **Application List** - Test filters
4. **Application Detail** - Test edit functionaliteit
5. **Sync** - Test manual sync
---
## Stap 10: Monitoring & Maintenance
### 10.1 Logs
```bash
# Azure App Service logs
az webapp log tail --name <app-name> --resource-group <resource-group>
# Docker logs
docker-compose logs -f backend
```
### 10.2 Database Monitoring
```sql
-- Database size (single database contains all data)
SELECT pg_database_size('cmdb_insight');
-- Table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Index usage
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
```
### 10.3 Performance Monitoring
- Monitor query performance
- Check sync duration
- Monitor database connections
- Check memory usage
---
## Troubleshooting
### Database Connection Issues
```bash
# Test connection
psql $DATABASE_URL -c "SELECT 1"
# Check firewall rules (Azure)
az postgres flexible-server firewall-rule list \
--resource-group <resource-group> \
--name <server-name>
```
### Schema Discovery Fails
```bash
# Check Jira connection
curl -H "Authorization: Bearer $JIRA_SERVICE_ACCOUNT_TOKEN" \
$JIRA_HOST/rest/insight/1.0/objectschema/list
# Regenerate schema
cd backend
npm run generate-schema
```
### Sync Issues
```bash
# Check sync status
curl https://your-domain.com/api/cache/status
# Manual sync for specific type
curl -X POST https://your-domain.com/api/cache/sync/ApplicationComponent
```
---
## Rollback Plan
Als er problemen zijn:
1. **Stop applicatie**
2. **Revert code** (git)
3. **Herstart applicatie**
Aangezien het green field is, is er geen data migration nodig voor rollback.
---
## Post-Deployment Checklist
- [ ] Database verbinding werkt
- [ ] Schema discovery succesvol
- [ ] Eerste sync voltooid
- [ ] Alle object types gesynct
- [ ] Queries werken correct
- [ ] Filters werken
- [ ] Edit functionaliteit werkt
- [ ] Authentication werkt
- [ ] Logs zijn zichtbaar
- [ ] Monitoring is ingesteld
---
## Performance Tips
1. **Database Indexes** - Zijn automatisch aangemaakt
2. **Connection Pooling** - PostgreSQL adapter gebruikt pool (max 20)
3. **Query Optimization** - Gebruik `queryWithFilters()` voor gefilterde queries
4. **Sync Frequency** - Incremental sync elke 30 seconden (configureerbaar)
---
## Security Checklist
- [ ] `SESSION_SECRET` is sterk en uniek
- [ ] Database credentials zijn secure
- [ ] HTTPS is ingeschakeld
- [ ] CORS is correct geconfigureerd
- [ ] OAuth callback URL is correct
- [ ] Environment variables zijn niet gecommit
---
## Extra Tips & Best Practices
### Database Performance
1. **Connection Pooling**
- PostgreSQL adapter gebruikt automatisch connection pooling (max 20)
- Monitor pool usage in production
2. **Query Optimization**
- Gebruik `queryWithFilters()` voor gefilterde queries (veel sneller)
- Indexes zijn automatisch aangemaakt
- Monitor slow queries
3. **Sync Performance**
- Batch size: 50 objects per batch (configureerbaar via `JIRA_API_BATCH_SIZE`)
- Incremental sync: elke 30 seconden (configureerbaar via `SYNC_INCREMENTAL_INTERVAL_MS`)
### Monitoring
1. **Application Logs**
- Check voor schema discovery errors
- Monitor sync duration
- Check query performance
2. **Database Metrics**
- Table sizes groeien
- Index usage
- Connection pool usage
3. **Jira API**
- Monitor rate limiting
- Check API response times
- Monitor sync success rate
### Backup Strategy
1. **Database Backups**
- Azure PostgreSQL: automatische dagelijkse backups
- SQLite: maak periodieke copies van `.db` files
2. **Configuration Backup**
- Backup `.env` file (securely!)
- Document alle environment variables
### Scaling Considerations
1. **Database**
- PostgreSQL kan schalen (vertical scaling)
- Overweeg read replicas voor grote datasets
2. **Application**
- Stateless design - kan horizontaal schalen
- Session storage in database (scalable)
3. **Cache**
- Normalized structure is efficient
- Indexes zorgen voor goede performance
### Troubleshooting Common Issues
#### Issue: Schema Discovery Fails
**Symptoom:** Error bij startup, geen object types in database
**Oplossing:**
```bash
# Check Jira connection
curl -H "Authorization: Bearer $JIRA_SERVICE_ACCOUNT_TOKEN" \
$JIRA_HOST/rest/insight/1.0/objectschema/list
# Regenerate schema
cd backend
npm run generate-schema
# Restart application
```
#### Issue: Sync is Slow
**Symptoom:** Full sync duurt lang
**Oplossing:**
- Check Jira API response times
- Verhoog batch size (maar niet te veel - rate limiting)
- Check database connection pool
#### Issue: Queries zijn Langzaam
**Symptoom:** Filters werken traag
**Oplossing:**
- Check of indexes bestaan: `\d+ attribute_values` in PostgreSQL
- Gebruik `queryWithFilters()` in plaats van JavaScript filtering
- Check query execution plan
#### Issue: Memory Usage Hoog
**Symptoom:** Applicatie gebruikt veel geheugen
**Oplossing:**
- Normalized storage gebruikt minder geheugen dan JSONB
- Check of oude cacheStore nog ergens gebruikt wordt
- Monitor object reconstruction (kan N+1 queries veroorzaken)
### Development vs Production
**Development:**
- SQLite is prima voor testing
- Lokale database in `backend/data/`
- Geen SSL nodig
**Production:**
- PostgreSQL is aanbevolen
- Azure Database for PostgreSQL
- SSL vereist
- Connection pooling
- Monitoring ingeschakeld
### Migration van Development naar Production
1. **Schema is hetzelfde** - geen migratie nodig
2. **Data sync** - eerste sync haalt alles op van Jira
3. **Environment variables** - update voor productie
4. **OAuth callback URL** - update naar productie domain
---
**End of Guide**