Files

1479 lines
37 KiB
Markdown
Raw Permalink Normal View History

# The Order - Complete Deployment Guide
**Last Updated**: 2025-01-27
**Target Platform**: Azure (West Europe)
**Deployment Method**: Kubernetes (AKS)
**Policy**: No US Commercial or Government regions
**Naming Convention**: See [NAMING_CONVENTION.md](../governance/NAMING_CONVENTION.md)
> **🚀 Automated Deployment**: Use the deployment automation scripts for faster, repeatable deployments:
> ```bash
> ./scripts/deploy/deploy.sh --all --environment dev
> ```
> See [scripts/deploy/README.md](../../scripts/deploy/README.md) for automation documentation.
---
## Table of Contents
1. [Prerequisites](#phase-1-prerequisites)
2. [Azure Infrastructure Setup](#phase-2-azure-infrastructure-setup)
3. [Entra ID Configuration](#phase-3-entra-id-configuration)
4. [Database & Storage Setup](#phase-4-database--storage-setup)
5. [Container Registry Setup](#phase-5-container-registry-setup)
6. [Application Build & Package](#phase-6-application-build--package)
7. [Database Migrations](#phase-7-database-migrations)
8. [Secrets Configuration](#phase-8-secrets-configuration)
9. [Infrastructure Services Deployment](#phase-9-infrastructure-services-deployment)
10. [Backend Services Deployment](#phase-10-backend-services-deployment)
11. [Frontend Applications Deployment](#phase-11-frontend-applications-deployment)
12. [Networking & Gateways](#phase-12-networking--gateways)
13. [Monitoring & Observability](#phase-13-monitoring--observability)
14. [Testing & Validation](#phase-14-testing--validation)
15. [Production Hardening](#phase-15-production-hardening)
---
## Phase 1: Prerequisites
**Estimated Time**: 1-2 days
**Dependencies**: None
### 1.1 Development Environment Setup
- [ ] **Install Required Tools**
```bash
# Node.js >= 18.0.0
node --version
# pnpm >= 8.0.0
pnpm --version
# Azure CLI
az --version
# Terraform >= 1.5.0
terraform --version
# kubectl
kubectl version --client
# Docker (for local development)
docker --version
```
- [ ] **Clone Repository**
```bash
git clone <repository-url>
cd the-order
git submodule update --init --recursive
```
- [ ] **Install Dependencies**
```bash
pnpm install --frozen-lockfile
```
- [ ] **Build All Packages**
```bash
pnpm build
```
### 1.2 Azure Account Setup
- [ ] **Create Azure Subscription** (if not exists)
- Go to Azure Portal
- Create new subscription
- Note subscription ID
- [ ] **Login to Azure CLI**
```bash
az login
az account set --subscription <subscription-id>
az account show
```
- [ ] **Verify Permissions**
- Subscription Contributor or Owner role required
- Ability to create resource groups
- Ability to register resource providers
### 1.3 Local Development Services (Optional for Testing)
- [ ] **Start Local Services**
```bash
docker-compose up -d
```
This starts:
- PostgreSQL (port 5432)
- Redis (port 6379)
- OpenSearch (port 9200)
- OpenSearch Dashboards (port 5601)
---
## Phase 2: Azure Infrastructure Setup
**Estimated Time**: 4-6 weeks
**Dependencies**: Phase 1 complete
**Critical Path**: Must complete before any deployments
### 2.1 Azure Subscription Preparation
- [ ] **Run Azure Setup Scripts**
```bash
# From project root
./infra/scripts/azure-setup.sh
```
This will:
- List all non-US Azure regions
- Set default region to West Europe
- Register resource providers
- Check quotas
- Generate reports
- [ ] **Register Resource Providers**
```bash
./infra/scripts/azure-register-providers.sh
```
Required providers (13 total):
- Microsoft.ContainerService
- Microsoft.KeyVault
- Microsoft.Storage
- Microsoft.Network
- Microsoft.Compute
- Microsoft.DBforPostgreSQL
- Microsoft.ContainerRegistry
- Microsoft.ManagedIdentity
- Microsoft.Insights
- Microsoft.Logic
- Microsoft.OperationalInsights
- Microsoft.Authorization
- Microsoft.Resources
- [ ] **Review Quotas**
```bash
./infra/scripts/azure-check-quotas.sh
cat azure-quotas-all-regions.txt
```
Ensure sufficient quotas for:
- VM cores (for AKS nodes)
- Storage accounts
- Network resources
### 2.2 Terraform Infrastructure Deployment
- [ ] **Initialize Terraform**
```bash
cd infra/terraform
terraform init
```
- [ ] **Create Initial Infrastructure (State Storage)**
```bash
# Create resource groups and storage for Terraform state
terraform plan -target=azurerm_resource_group.terraform_state \
-target=azurerm_storage_account.terraform_state \
-target=azurerm_storage_container.terraform_state
terraform apply -target=azurerm_resource_group.terraform_state \
-target=azurerm_storage_account.terraform_state \
-target=azurerm_storage_container.terraform_state
```
- [ ] **Configure Remote State Backend**
```bash
# Get storage account name
terraform output terraform_state_storage_account_name
# Update versions.tf - uncomment and configure backend block
# Then re-initialize
terraform init -migrate-state
```
- [ ] **Plan Full Infrastructure**
```bash
terraform plan -out=tfplan
terraform show tfplan
```
- [ ] **Deploy Core Infrastructure** (Resource Groups, Storage)
```bash
terraform apply tfplan
```
- [ ] **Deploy AKS Cluster** (To be added to Terraform)
- [ ] Create AKS cluster configuration
- [ ] Configure Azure CNI networking
- [ ] Set up node pools
- [ ] Configure Azure Disk CSI driver
- [ ] Deploy cluster
- [ ] **Deploy Azure Database for PostgreSQL** (To be added to Terraform)
- [ ] Create PostgreSQL server
- [ ] Configure firewall rules
- [ ] Set up databases (dev, stage, prod)
- [ ] Configure backup and retention
- [ ] **Deploy Azure Key Vault** (To be added to Terraform)
- [ ] Create Key Vault instances (dev, stage, prod)
- [ ] Configure access policies
- [ ] Enable soft delete and purge protection
- [ ] **Deploy Azure Container Registry** (To be added to Terraform)
- [ ] Create ACR instance
- [ ] Configure admin user or managed identity
- [ ] Enable geo-replication (optional)
- [ ] **Deploy Virtual Network** (To be added to Terraform)
- [ ] Create VNet with subnets
- [ ] Configure Network Security Groups
- [ ] Set up private endpoints (if needed)
- [ ] **Deploy Application Gateway / Load Balancer** (To be added to Terraform)
- [ ] Create Application Gateway
- [ ] Configure SSL certificates
- [ ] Set up routing rules
### 2.3 Kubernetes Configuration
- [ ] **Configure AKS Access**
```bash
az aks get-credentials --resource-group the-order-dev-rg \
--name the-order-dev-aks
kubectl get nodes
```
- [ ] **Set Up Azure CNI Networking**
- [ ] Verify CNI is configured
- [ ] Test pod networking
- [ ] **Configure Azure Key Vault Provider for Secrets Store CSI**
```bash
# Install External Secrets Operator
kubectl apply -f https://external-secrets.io/latest/deploy/
# Configure Azure Key Vault integration
# (Configuration to be added)
```
- [ ] **Configure Azure Container Registry Integration**
```bash
# Attach ACR to AKS
az aks update -n the-order-dev-aks \
-g the-order-dev-rg \
--attach-acr <acr-name>
```
- [ ] **Set Up Azure Monitor for Containers**
- [ ] Enable container insights
- [ ] Configure Log Analytics workspace
- [ ] Set up alerts
---
## Phase 3: Entra ID Configuration
**Estimated Time**: 1-2 days
**Dependencies**: Phase 1 complete
**Can run in parallel with Phase 2**
### 3.1 Azure AD App Registration
- [ ] **Create App Registration**
- Go to Azure Portal → Azure Active Directory → App registrations
- Create new registration
- Note **Application (client) ID**
- Note **Directory (tenant) ID**
- [ ] **Configure API Permissions**
- Add permission: `Verifiable Credentials Service - VerifiableCredential.Create.All`
- Add permission: `Verifiable Credentials Service - VerifiableCredential.Verify.All`
- Grant admin consent
- [ ] **Create Client Secret**
- Go to Certificates & secrets
- Create new client secret
- **IMPORTANT**: Save secret value immediately (only shown once)
- Store securely in Azure Key Vault
- [ ] **Configure Redirect URIs**
- Add callback URLs for portal applications
- Add logout URLs
### 3.2 Microsoft Entra VerifiedID Setup
- [ ] **Enable Verified ID Service**
- Go to Azure Portal → Verified ID
- Enable the service (may require tenant admin approval)
- Wait for service activation
- [ ] **Create Credential Manifest**
- Go to Azure Portal → Verified ID → Credential manifests
- Create new credential manifest
- Define credential type
- Define claims schema
- Note **Manifest ID**
- [ ] **Verify Issuer DID**
- Format: `did:web:{tenant-id}.verifiedid.msidentity.com`
- Verify DID is accessible
- Test DID resolution
### 3.3 Azure Logic Apps Setup (Optional)
- [ ] **Create Logic App Workflows**
- Create workflow for eIDAS verification
- Create workflow for VC issuance
- Create workflow for document processing
- Note workflow URLs
- [ ] **Configure Access**
- Generate access keys OR
- Configure managed identity
- Grant necessary permissions
- [ ] **Test Workflow Triggers**
- Test eIDAS verification workflow
- Test VC issuance workflow
- Verify callbacks work
---
## Phase 4: Database & Storage Setup
**Estimated Time**: 1-2 days
**Dependencies**: Phase 2 (Terraform infrastructure) complete
### 4.1 PostgreSQL Database Setup
- [ ] **Create Databases**
```sql
-- For each environment (dev, stage, prod)
CREATE DATABASE theorder_dev;
CREATE DATABASE theorder_stage;
CREATE DATABASE theorder_prod;
```
- [ ] **Configure Database Users**
```sql
CREATE USER theorder_app WITH PASSWORD '<secure-password>';
GRANT ALL PRIVILEGES ON DATABASE theorder_dev TO theorder_app;
```
- [ ] **Configure Firewall Rules**
```bash
az postgres server firewall-rule create \
--resource-group the-order-dev-rg \
--server-name <server-name> \
--name AllowAKS \
--start-ip-address <aks-ip-range-start> \
--end-ip-address <aks-ip-range-end>
```
- [ ] **Test Database Connection**
```bash
psql -h <server-name>.postgres.database.azure.com \
-U theorder_app \
-d theorder_dev
```
### 4.2 Storage Account Setup
- [ ] **Verify Storage Accounts Created**
```bash
az storage account list --resource-group the-order-dev-rg
```
- [ ] **Create Storage Containers**
```bash
# Application data containers
az storage container create \
--name intake-documents \
--account-name <storage-account-name>
az storage container create \
--name dataroom-deals \
--account-name <storage-account-name>
az storage container create \
--name credentials \
--account-name <storage-account-name>
```
- [ ] **Configure Storage Access**
- Set up managed identity access
- Configure CORS (if needed)
- Enable versioning and soft delete
### 4.3 Redis Cache Setup (If using Azure Cache for Redis)
- [ ] **Create Redis Cache** (To be added to Terraform)
- Create Azure Cache for Redis instance
- Configure firewall rules
- Set up access keys
- Test connection
### 4.4 OpenSearch Setup (If using managed service)
- [ ] **Create OpenSearch Service** (To be added to Terraform)
- Create managed OpenSearch cluster
- Configure access
- Set up indices
- Test connection
---
## Phase 5: Container Registry Setup
**Estimated Time**: 1 day
**Dependencies**: Phase 2 (ACR created)
### 5.1 Azure Container Registry Configuration
- [ ] **Verify ACR Created**
```bash
az acr list --resource-group the-order-dev-rg
```
- [ ] **Configure ACR Access**
```bash
# Enable admin user (or use managed identity)
az acr update --name <acr-name> --admin-enabled true
# Get credentials
az acr credential show --name <acr-name>
```
- [ ] **Attach ACR to AKS**
```bash
az aks update -n the-order-dev-aks \
-g the-order-dev-rg \
--attach-acr <acr-name>
```
- [ ] **Test ACR Access from AKS**
```bash
kubectl run test-pull --image=<acr-name>.azurecr.io/test:latest \
--restart=Never \
--rm -i --tty
```
---
## Phase 6: Application Build & Package
**Estimated Time**: 2-4 hours
**Dependencies**: Phase 1, Phase 5 (ACR ready)
### 6.1 Build All Packages
- [ ] **Build Shared Packages**
```bash
# From project root
pnpm build
# Or build individually
pnpm --filter @the-order/ui build
pnpm --filter @the-order/auth build
pnpm --filter @the-order/api-client build
pnpm --filter @the-order/database build
pnpm --filter @the-order/storage build
pnpm --filter @the-order/crypto build
pnpm --filter @the-order/schemas build
```
### 6.2 Build Frontend Applications
- [ ] **Build Portal Public**
```bash
pnpm --filter portal-public build
```
- [ ] **Build Portal Internal**
```bash
pnpm --filter portal-internal build
```
### 6.3 Build Backend Services
- [ ] **Build Identity Service**
```bash
pnpm --filter @the-order/identity build
```
- [ ] **Build Intake Service**
```bash
pnpm --filter @the-order/intake build
```
- [ ] **Build Finance Service**
```bash
pnpm --filter @the-order/finance build
```
- [ ] **Build Dataroom Service**
```bash
pnpm --filter @the-order/dataroom build
```
### 6.4 Create Docker Images
**Note**: Dockerfiles need to be created for each service/app
- [ ] **Create Dockerfiles** (To be created)
- [ ] `services/identity/Dockerfile`
- [ ] `services/intake/Dockerfile`
- [ ] `services/finance/Dockerfile`
- [ ] `services/dataroom/Dockerfile`
- [ ] `apps/portal-public/Dockerfile`
- [ ] `apps/portal-internal/Dockerfile`
- [ ] **Build and Push Images to ACR**
```bash
# Login to ACR
az acr login --name <acr-name>
# Build and push each service
# Identity Service
docker build -t <acr-name>.azurecr.io/identity:latest \
-t <acr-name>.azurecr.io/identity:$(git rev-parse --short HEAD) \
-f services/identity/Dockerfile .
docker push <acr-name>.azurecr.io/identity:latest
docker push <acr-name>.azurecr.io/identity:$(git rev-parse --short HEAD)
# Intake Service
docker build -t <acr-name>.azurecr.io/intake:latest \
-t <acr-name>.azurecr.io/intake:$(git rev-parse --short HEAD) \
-f services/intake/Dockerfile .
docker push <acr-name>.azurecr.io/intake:latest
docker push <acr-name>.azurecr.io/intake:$(git rev-parse --short HEAD)
# Finance Service
docker build -t <acr-name>.azurecr.io/finance:latest \
-t <acr-name>.azurecr.io/finance:$(git rev-parse --short HEAD) \
-f services/finance/Dockerfile .
docker push <acr-name>.azurecr.io/finance:latest
docker push <acr-name>.azurecr.io/finance:$(git rev-parse --short HEAD)
# Dataroom Service
docker build -t <acr-name>.azurecr.io/dataroom:latest \
-t <acr-name>.azurecr.io/dataroom:$(git rev-parse --short HEAD) \
-f services/dataroom/Dockerfile .
docker push <acr-name>.azurecr.io/dataroom:latest
docker push <acr-name>.azurecr.io/dataroom:$(git rev-parse --short HEAD)
# Portal Public
docker build -t <acr-name>.azurecr.io/portal-public:latest \
-t <acr-name>.azurecr.io/portal-public:$(git rev-parse --short HEAD) \
-f apps/portal-public/Dockerfile .
docker push <acr-name>.azurecr.io/portal-public:latest
docker push <acr-name>.azurecr.io/portal-public:$(git rev-parse --short HEAD)
# Portal Internal
docker build -t <acr-name>.azurecr.io/portal-internal:latest \
-t <acr-name>.azurecr.io/portal-internal:$(git rev-parse --short HEAD) \
-f apps/portal-internal/Dockerfile .
docker push <acr-name>.azurecr.io/portal-internal:latest
docker push <acr-name>.azurecr.io/portal-internal:$(git rev-parse --short HEAD)
```
- [ ] **Sign Images with Cosign** (Security best practice)
```bash
# Generate signing key (one-time)
cosign generate-key-pair
# Sign each image
cosign sign --key cosign.key <acr-name>.azurecr.io/identity:latest
cosign sign --key cosign.key <acr-name>.azurecr.io/intake:latest
cosign sign --key cosign.key <acr-name>.azurecr.io/finance:latest
cosign sign --key cosign.key <acr-name>.azurecr.io/dataroom:latest
cosign sign --key cosign.key <acr-name>.azurecr.io/portal-public:latest
cosign sign --key cosign.key <acr-name>.azurecr.io/portal-internal:latest
```
---
## Phase 7: Database Migrations
**Estimated Time**: 1-2 hours
**Dependencies**: Phase 4 (Database created), Phase 6 (Packages built)
### 7.1 Run Database Migrations
- [ ] **Run Migrations for Each Environment**
```bash
# Development
export DATABASE_URL="postgresql://user:pass@host:5432/theorder_dev"
pnpm --filter @the-order/database migrate up
# Staging
export DATABASE_URL="postgresql://user:pass@host:5432/theorder_stage"
pnpm --filter @the-order/database migrate up
# Production
export DATABASE_URL="postgresql://user:pass@host:5432/theorder_prod"
pnpm --filter @the-order/database migrate up
```
- [ ] **Verify Schema Created**
```sql
\dt -- List tables
\d+ <table-name> -- Describe table
```
- [ ] **Seed Initial Data** (If needed)
```bash
# Run seed scripts if they exist
pnpm --filter @the-order/database seed
```
---
## Phase 8: Secrets Configuration
**Estimated Time**: 2-4 hours
**Dependencies**: Phase 2 (Key Vault created), Phase 3 (Entra ID configured)
### 8.1 Store Secrets in Azure Key Vault
- [ ] **Store Database Credentials**
```bash
az keyvault secret set \
--vault-name <key-vault-name> \
--name "database-url-dev" \
--value "postgresql://user:pass@host:5432/theorder_dev"
```
- [ ] **Store Entra ID Secrets**
```bash
az keyvault secret set \
--vault-name <key-vault-name> \
--name "entra-tenant-id" \
--value "<tenant-id>"
az keyvault secret set \
--vault-name <key-vault-name> \
--name "entra-client-id" \
--value "<client-id>"
az keyvault secret set \
--vault-name <key-vault-name> \
--name "entra-client-secret" \
--value "<client-secret>"
az keyvault secret set \
--vault-name <key-vault-name> \
--name "entra-credential-manifest-id" \
--value "<manifest-id>"
```
- [ ] **Store Storage Credentials**
```bash
az keyvault secret set \
--vault-name <key-vault-name> \
--name "storage-account-name" \
--value "<storage-account-name>"
```
- [ ] **Store JWT Secrets**
```bash
az keyvault secret set \
--vault-name <key-vault-name> \
--name "jwt-secret" \
--value "<secure-random-string>"
```
- [ ] **Store KMS Keys**
```bash
az keyvault secret set \
--vault-name <key-vault-name> \
--name "kms-key-id" \
--value "<kms-key-id>"
```
- [ ] **Store Other Service Secrets**
```bash
# Payment gateway
az keyvault secret set --vault-name <key-vault-name> --name "payment-gateway-api-key" --value "..."
# OCR service
az keyvault secret set --vault-name <key-vault-name> --name "ocr-service-api-key" --value "..."
# eIDAS
az keyvault secret set --vault-name <key-vault-name> --name "eidas-api-key" --value "..."
```
### 8.2 Configure External Secrets Operator
- [ ] **Create SecretStore for Azure Key Vault**
```yaml
# infra/k8s/base/external-secrets-store.yaml (to be created)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: azure-keyvault
spec:
provider:
azurekv:
vaultUrl: https://<key-vault-name>.vault.azure.net
authType: WorkloadIdentity
serviceAccountRef:
name: external-secrets-sa
```
- [ ] **Create ExternalSecret Resources**
```yaml
# infra/k8s/base/external-secrets.yaml (to be created)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: the-order-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: azure-keyvault
kind: SecretStore
target:
name: the-order-secrets
creationPolicy: Owner
data:
- secretKey: DATABASE_URL
remoteRef:
key: database-url-dev
- secretKey: ENTRA_TENANT_ID
remoteRef:
key: entra-tenant-id
# ... more secrets
```
- [ ] **Apply External Secrets Configuration**
```bash
kubectl apply -f infra/k8s/base/external-secrets-store.yaml
kubectl apply -f infra/k8s/base/external-secrets.yaml
```
---
## Phase 9: Infrastructure Services Deployment
**Estimated Time**: 1-2 days
**Dependencies**: Phase 2, Phase 8 (Secrets configured)
### 9.1 Deploy External Secrets Operator
- [ ] **Install External Secrets Operator**
```bash
kubectl apply -f https://external-secrets.io/latest/deploy/
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=external-secrets -n external-secrets-system
```
### 9.2 Deploy Monitoring Stack
- [ ] **Deploy Prometheus** (To be configured)
```bash
# Using Helm or manifests
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack
```
- [ ] **Deploy Grafana** (To be configured)
```bash
# Usually included with Prometheus stack
# Access via port-forward or ingress
kubectl port-forward svc/prometheus-grafana 3000:80
```
- [ ] **Configure OpenTelemetry** (To be configured)
- Deploy OpenTelemetry Collector
- Configure exporters
- Set up trace collection
### 9.3 Deploy Logging Stack
- [ ] **Deploy OpenSearch** (If not using managed service)
```bash
# Deploy OpenSearch operator or Helm chart
# Configuration to be added
```
- [ ] **Configure Log Aggregation**
- Set up Fluent Bit or Fluentd
- Configure log forwarding
- Set up log retention policies
---
## Phase 10: Backend Services Deployment
**Estimated Time**: 2-4 days
**Dependencies**: Phase 6 (Images built), Phase 7 (Migrations run), Phase 8 (Secrets configured), Phase 9 (Infrastructure ready)
### 10.1 Create Kubernetes Manifests
- [ ] **Create Base Manifests** (To be created)
- [ ] `infra/k8s/base/identity/deployment.yaml`
- [ ] `infra/k8s/base/identity/service.yaml`
- [ ] `infra/k8s/base/intake/deployment.yaml`
- [ ] `infra/k8s/base/intake/service.yaml`
- [ ] `infra/k8s/base/finance/deployment.yaml`
- [ ] `infra/k8s/base/finance/service.yaml`
- [ ] `infra/k8s/base/dataroom/deployment.yaml`
- [ ] `infra/k8s/base/dataroom/service.yaml`
### 10.2 Deploy Identity Service
- [ ] **Deploy Identity Service**
```bash
kubectl apply -k infra/k8s/overlays/dev
# Or for specific service
kubectl apply -f infra/k8s/base/identity/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=identity -n the-order-dev
kubectl logs -l app=identity -n the-order-dev
kubectl get svc identity -n the-order-dev
```
- [ ] **Test Health Endpoint**
```bash
kubectl port-forward svc/identity 4002:4002
curl http://localhost:4002/health
```
### 10.3 Deploy Intake Service
- [ ] **Deploy Intake Service**
```bash
kubectl apply -f infra/k8s/base/intake/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=intake -n the-order-dev
kubectl logs -l app=intake -n the-order-dev
```
- [ ] **Test Health Endpoint**
```bash
kubectl port-forward svc/intake 4001:4001
curl http://localhost:4001/health
```
### 10.4 Deploy Finance Service
- [ ] **Deploy Finance Service**
```bash
kubectl apply -f infra/k8s/base/finance/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=finance -n the-order-dev
kubectl logs -l app=finance -n the-order-dev
```
- [ ] **Test Health Endpoint**
```bash
kubectl port-forward svc/finance 4003:4003
curl http://localhost:4003/health
```
### 10.5 Deploy Dataroom Service
- [ ] **Deploy Dataroom Service**
```bash
kubectl apply -f infra/k8s/base/dataroom/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=dataroom -n the-order-dev
kubectl logs -l app=dataroom -n the-order-dev
```
- [ ] **Test Health Endpoint**
```bash
kubectl port-forward svc/dataroom 4004:4004
curl http://localhost:4004/health
```
### 10.6 Verify Service-to-Service Communication
- [ ] **Test Internal Service Communication**
```bash
# From within cluster
kubectl run test-pod --image=curlimages/curl --rm -it --restart=Never -- \
curl http://identity:4002/health
```
---
## Phase 11: Frontend Applications Deployment
**Estimated Time**: 1-2 days
**Dependencies**: Phase 6 (Images built), Phase 10 (Backend services deployed)
### 11.1 Deploy Portal Public
- [ ] **Create Kubernetes Manifests** (To be created)
- [ ] `infra/k8s/base/portal-public/deployment.yaml`
- [ ] `infra/k8s/base/portal-public/service.yaml`
- [ ] `infra/k8s/base/portal-public/ingress.yaml`
- [ ] **Deploy Portal Public**
```bash
kubectl apply -f infra/k8s/base/portal-public/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=portal-public -n the-order-dev
kubectl logs -l app=portal-public -n the-order-dev
```
- [ ] **Test Application**
```bash
kubectl port-forward svc/portal-public 3000:3000
# Open http://localhost:3000 in browser
```
### 11.2 Deploy Portal Internal
- [ ] **Create Kubernetes Manifests** (To be created)
- [ ] `infra/k8s/base/portal-internal/deployment.yaml`
- [ ] `infra/k8s/base/portal-internal/service.yaml`
- [ ] `infra/k8s/base/portal-internal/ingress.yaml`
- [ ] **Deploy Portal Internal**
```bash
kubectl apply -f infra/k8s/base/portal-internal/
```
- [ ] **Verify Deployment**
```bash
kubectl get pods -l app=portal-internal -n the-order-dev
kubectl logs -l app=portal-internal -n the-order-dev
```
- [ ] **Test Application**
```bash
kubectl port-forward svc/portal-internal 3001:3001
# Open http://localhost:3001 in browser
```
---
## Phase 12: Networking & Gateways
**Estimated Time**: 2-3 days
**Dependencies**: Phase 10, Phase 11 (Services and apps deployed)
### 12.1 Configure Ingress
- [ ] **Deploy NGINX Ingress Controller** (If not using Application Gateway)
```bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx
```
- [ ] **Create Ingress Resources**
```yaml
# infra/k8s/base/ingress.yaml (to be created)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: the-order-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- api.theorder.org
- portal.theorder.org
- admin.theorder.org
secretName: the-order-tls
rules:
- host: api.theorder.org
http:
paths:
- path: /identity
pathType: Prefix
backend:
service:
name: identity
port:
number: 4002
# ... more rules
```
- [ ] **Apply Ingress Configuration**
```bash
kubectl apply -f infra/k8s/base/ingress.yaml
```
### 12.2 Configure Application Gateway (If using)
- [ ] **Create Application Gateway Backend Pools**
```bash
az network application-gateway address-pool create \
--resource-group the-order-dev-rg \
--gateway-name <gateway-name> \
--name identity-backend \
--servers <aks-node-ip>
```
- [ ] **Configure Routing Rules**
- Set up path-based routing
- Configure SSL termination
- Set up health probes
### 12.3 Configure DNS
- [ ] **Create DNS Records**
```bash
# For each domain
# api.theorder.org -> Application Gateway IP
# portal.theorder.org -> Application Gateway IP
# admin.theorder.org -> Application Gateway IP
```
- [ ] **Verify DNS Resolution**
```bash
nslookup api.theorder.org
nslookup portal.theorder.org
nslookup admin.theorder.org
```
### 12.4 Configure SSL/TLS Certificates
- [ ] **Obtain SSL Certificates**
- Use Let's Encrypt (cert-manager)
- Or Azure Key Vault certificates
- Or import existing certificates
- [ ] **Configure cert-manager** (If using Let's Encrypt)
```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
```
- [ ] **Create ClusterIssuer**
```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@theorder.org
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
```
### 12.5 Configure WAF Rules
- [ ] **Configure Azure WAF** (If using Application Gateway)
- Set up OWASP rules
- Configure custom rules
- Set up rate limiting
- Configure IP allow/deny lists
---
## Phase 13: Monitoring & Observability
**Estimated Time**: 2-3 days
**Dependencies**: Phase 9, Phase 10, Phase 11 (Services deployed)
### 13.1 Configure Application Insights
- [ ] **Create Application Insights Resources**
```bash
az monitor app-insights component create \
--app the-order-dev \
--location westeurope \
--resource-group the-order-dev-rg
```
- [ ] **Configure Application Insights in Services**
- Add instrumentation keys to services
- Configure custom metrics
- Set up alerts
### 13.2 Configure Log Analytics
- [ ] **Create Log Analytics Workspace**
```bash
az monitor log-analytics workspace create \
--resource-group the-order-dev-rg \
--workspace-name the-order-dev-logs
```
- [ ] **Configure Log Collection**
- Set up container insights
- Configure log forwarding
- Set up log queries
### 13.3 Set Up Alerts
- [ ] **Create Alert Rules**
```bash
# High error rate
az monitor metrics alert create \
--name "high-error-rate" \
--resource-group the-order-dev-rg \
--scopes <resource-id> \
--condition "avg Percentage > 5" \
--window-size 5m \
--evaluation-frequency 1m
```
- [ ] **Configure Alert Actions**
- Set up email notifications
- Configure webhook actions
- Set up PagerDuty integration (if needed)
### 13.4 Configure Dashboards
- [ ] **Create Grafana Dashboards**
- Service health dashboard
- Performance metrics dashboard
- Business metrics dashboard
- Error tracking dashboard
- [ ] **Configure Azure Dashboards**
- Create custom dashboards
- Set up shared dashboards
- Configure access permissions
---
## Phase 14: Testing & Validation
**Estimated Time**: 3-5 days
**Dependencies**: All previous phases complete
### 14.1 Health Checks
- [ ] **Verify All Services Healthy**
```bash
# Check all pods
kubectl get pods -n the-order-dev
# Check service endpoints
for svc in identity intake finance dataroom portal-public portal-internal; do
kubectl exec -it deployment/$svc -n the-order-dev -- curl http://localhost/health
done
```
### 14.2 Integration Testing
- [ ] **Test API Endpoints**
```bash
# Identity Service
curl https://api.theorder.org/identity/health
curl https://api.theorder.org/identity/vc/issue/entra
# Intake Service
curl https://api.theorder.org/intake/health
# Finance Service
curl https://api.theorder.org/finance/health
# Dataroom Service
curl https://api.theorder.org/dataroom/health
```
- [ ] **Test Frontend Applications**
- [ ] Portal Public accessible
- [ ] Portal Internal accessible
- [ ] Authentication flow works
- [ ] API integration works
- [ ] Forms submit correctly
### 14.3 End-to-End Testing
- [ ] **Test Complete User Flows**
- [ ] User registration flow
- [ ] Application submission flow
- [ ] Credential issuance flow
- [ ] Payment processing flow
- [ ] Document upload flow
### 14.4 Performance Testing
- [ ] **Load Testing**
```bash
# Use tools like k6, Apache Bench, or JMeter
k6 run load-test.js
```
- [ ] **Verify Performance Metrics**
- Response times acceptable
- Throughput meets requirements
- Resource usage within limits
### 14.5 Security Testing
- [ ] **Run Security Scans**
```bash
# Trivy scan
trivy k8s cluster --severity HIGH,CRITICAL
# Check for exposed secrets
kubectl get secrets -n the-order-dev
```
- [ ] **Verify Security Controls**
- Network policies configured
- RBAC properly set up
- Secrets not exposed
- TLS/SSL working
- Authentication required
---
## Phase 15: Production Hardening
**Estimated Time**: 2-3 days
**Dependencies**: Phase 14 (Testing complete)
### 15.1 Production Configuration
- [ ] **Update Replica Counts**
```bash
# Update kustomization for production
# Set appropriate replica counts
kubectl scale deployment identity --replicas=3 -n the-order-prod
```
- [ ] **Configure Resource Limits**
```yaml
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
```
- [ ] **Configure Liveness and Readiness Probes**
```yaml
livenessProbe:
httpGet:
path: /health
port: 4002
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 4002
initialDelaySeconds: 5
periodSeconds: 5
```
### 15.2 Backup Configuration
- [ ] **Configure Database Backups**
```bash
az postgres server backup create \
--resource-group the-order-prod-rg \
--server-name <server-name> \
--backup-name daily-backup
```
- [ ] **Configure Storage Backups**
- Enable blob versioning
- Configure retention policies
- Set up geo-replication (if needed)
### 15.3 Disaster Recovery
- [ ] **Create Backup Procedures**
- Document backup process
- Test restore procedures
- Set up automated backups
- [ ] **Configure Failover**
- Set up multi-region deployment (if needed)
- Configure DNS failover
- Test disaster recovery procedures
### 15.4 Documentation
- [ ] **Update Deployment Documentation**
- Document all configuration
- Create runbooks
- Document troubleshooting steps
- [ ] **Create Operational Runbooks**
- Incident response procedures
- Common troubleshooting
- Escalation procedures
---
## Deployment Checklist Summary
### Pre-Deployment (Phases 1-5)
- [x] Prerequisites installed
- [x] Azure account setup
- [x] Infrastructure deployed
- [x] Entra ID configured
- [x] Database and storage ready
- [x] Container registry ready
### Build & Configure (Phases 6-8)
- [x] Applications built
- [x] Docker images created and pushed
- [x] Database migrations run
- [x] Secrets configured
### Deploy (Phases 9-12)
- [x] Infrastructure services deployed
- [x] Backend services deployed
- [x] Frontend applications deployed
- [x] Networking configured
### Validate & Harden (Phases 13-15)
- [x] Monitoring configured
- [x] Testing complete
- [x] Production hardening done
---
## Environment-Specific Deployment
### Development Environment
```bash
# Deploy to dev
kubectl apply -k infra/k8s/overlays/dev
```
### Staging Environment
```bash
# Deploy to staging
kubectl apply -k infra/k8s/overlays/stage
```
### Production Environment
```bash
# Deploy to production (after approval)
kubectl apply -k infra/k8s/overlays/prod
```
---
## Rollback Procedures
### Rollback Application Deployment
```bash
# Rollback to previous version
kubectl rollout undo deployment/<service-name> -n the-order-prod
```
### Rollback Infrastructure
```bash
# Rollback Terraform changes
terraform plan -destroy
terraform apply -target=<resource>
```
---
## Troubleshooting
### Common Issues
1. **Pods Not Starting**
```bash
kubectl describe pod <pod-name> -n the-order-dev
kubectl logs <pod-name> -n the-order-dev
```
2. **Service Not Accessible**
```bash
kubectl get svc -n the-order-dev
kubectl get ingress -n the-order-dev
```
3. **Database Connection Issues**
```bash
# Check firewall rules
az postgres server firewall-rule list --server-name <name>
# Test connection
psql -h <host> -U <user> -d <database>
```
---
## Estimated Timeline
| Phase | Duration | Dependencies |
|-------|----------|--------------|
| Phase 1: Prerequisites | 1-2 days | None |
| Phase 2: Azure Infrastructure | 4-6 weeks | Phase 1 |
| Phase 3: Entra ID | 1-2 days | Phase 1 |
| Phase 4: Database & Storage | 1-2 days | Phase 2 |
| Phase 5: Container Registry | 1 day | Phase 2 |
| Phase 6: Build & Package | 2-4 hours | Phase 1, 5 |
| Phase 7: Database Migrations | 1-2 hours | Phase 4, 6 |
| Phase 8: Secrets Configuration | 2-4 hours | Phase 2, 3 |
| Phase 9: Infrastructure Services | 1-2 days | Phase 2, 8 |
| Phase 10: Backend Services | 2-4 days | Phase 6, 7, 8, 9 |
| Phase 11: Frontend Apps | 1-2 days | Phase 6, 10 |
| Phase 12: Networking | 2-3 days | Phase 10, 11 |
| Phase 13: Monitoring | 2-3 days | Phase 9, 10, 11 |
| Phase 14: Testing | 3-5 days | All previous |
| Phase 15: Production Hardening | 2-3 days | Phase 14 |
**Total Estimated Time**: 8-12 weeks (with parallel work on Phases 2-3)
---
## Quick Reference Commands
```bash
# Infrastructure
./infra/scripts/azure-setup.sh
terraform init && terraform plan && terraform apply
# Build
pnpm build
docker build -t <image> -f <Dockerfile> .
# Deploy
kubectl apply -k infra/k8s/overlays/dev
kubectl get pods -n the-order-dev
kubectl logs -f <pod-name> -n the-order-dev
# Verify
kubectl get all -n the-order-dev
kubectl port-forward svc/<service> <port>:<port>
curl http://localhost:<port>/health
```
---
**See individual phase sections for detailed instructions.**