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:
378
docs/Core deployment guides/AZURE-ACR-SETUP.md
Normal file
378
docs/Core deployment guides/AZURE-ACR-SETUP.md
Normal 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.
|
||||
405
docs/Core deployment guides/AZURE-APP-SERVICE-DEPLOYMENT.md
Normal file
405
docs/Core deployment guides/AZURE-APP-SERVICE-DEPLOYMENT.md
Normal 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! 🚀**
|
||||
275
docs/Core deployment guides/AZURE-PIPELINES.md
Normal file
275
docs/Core deployment guides/AZURE-PIPELINES.md
Normal 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!
|
||||
371
docs/Core deployment guides/AZURE-POSTGRESQL-SETUP.md
Normal file
371
docs/Core deployment guides/AZURE-POSTGRESQL-SETUP.md
Normal 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!**
|
||||
177
docs/Core deployment guides/AZURE-QUICK-REFERENCE.md
Normal file
177
docs/Core deployment guides/AZURE-QUICK-REFERENCE.md
Normal 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
|
||||
592
docs/Core deployment guides/GREEN-FIELD-DEPLOYMENT-GUIDE.md
Normal file
592
docs/Core deployment guides/GREEN-FIELD-DEPLOYMENT-GUIDE.md
Normal 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**
|
||||
Reference in New Issue
Block a user