Skip to main content

Deployment Runbook

How to deploy the CRM & Marketing Platform to Kubernetes.

Prerequisites

  • kubectl configured for target cluster
  • Access to Harbor registry
  • Infisical secrets configured

Kubernetes Resources

Deployments

DeploymentPurposeReplicas
crm-backendAPI server2
crm-workerBackground jobs2

Services

ServicePortType
crm-backend80 (→3000)ClusterIP

Ingress

HostPathBackend
crm-api.digiwedge.dev/crm-backend:80

Deployment Steps

1. Build and Push Image

# Build image
docker build -t harbor.digiwedge.dev/crm/backend:$VERSION apps/crm/crm-backend

# Push to registry
docker push harbor.digiwedge.dev/crm/backend:$VERSION

2. Run Database Migrations

# Apply migration job
kubectl apply -f k8s/migrate-job.yaml

# Wait for completion
kubectl wait --for=condition=complete job/crm-migrate -n crm --timeout=120s

# Check migration logs
kubectl logs job/crm-migrate -n crm

3. Deploy Application

# Update image
kubectl set image deployment/crm-backend \
crm-backend=harbor.digiwedge.dev/crm/backend:$VERSION -n crm

kubectl set image deployment/crm-worker \
crm-worker=harbor.digiwedge.dev/crm/backend:$VERSION -n crm

# Watch rollout
kubectl rollout status deployment/crm-backend -n crm
kubectl rollout status deployment/crm-worker -n crm

4. Verify Deployment

# Check pods are running
kubectl get pods -n crm

# Check health endpoint
curl https://crm-api.digiwedge.dev/health

# Check logs
kubectl logs -l app=crm-backend -n crm --tail=100

Rollback Procedure

# Rollback to previous version
kubectl rollout undo deployment/crm-backend -n crm
kubectl rollout undo deployment/crm-worker -n crm

# Or rollback to specific revision
kubectl rollout undo deployment/crm-backend --to-revision=N -n crm

Secrets Configuration

Secrets are managed via Infisical and synced using InfisicalSecret CRD.

Backend Secrets (/crm/backend)

SecretPurpose
CRM_DATABASE_URLPostgreSQL connection (SCL DB with ?schema=crm)
REDIS_URLRedis for BullMQ queues and caching
AUTH_JWKS_URLIDP JWKS endpoint for JWT verification
AUTH_ISSExpected JWT issuer
AUTH_AUDExpected JWT audience

Events Worker Secrets (/crm/events-worker)

SecretPurpose
CRM_DATABASE_URLPostgreSQL connection
REDIS_URLRedis for BullMQ queues

Social Secrets (/crm/social) - Future

SecretPurpose
FACEBOOK_APP_IDFacebook Graph API
FACEBOOK_APP_SECRETFacebook Graph API
TWITTER_CLIENT_IDTwitter/X API
TWITTER_CLIENT_SECRETTwitter/X API

Note: CRM uses IDP JWKS authentication (AUTH_JWKS_URL/AUTH_ISS/AUTH_AUD), NOT symmetric JWT_SECRET.

Health Checks

EndpointPurpose
/healthLiveness probe
/health/readyReadiness probe
/metricsPrometheus metrics

Troubleshooting

Pods not starting

# Check events
kubectl describe pod <pod-name> -n crm

# Check logs
kubectl logs <pod-name> -n crm --previous

Database connection issues

# Verify secret exists
kubectl get secret crm-secrets -n crm -o yaml

# Test connection from pod
kubectl exec -it <pod-name> -n crm -- \
psql $CRM_DATABASE_URL -c "SELECT 1"

Migration failed

# Check migration job logs
kubectl logs job/crm-migrate -n crm

# Reset and retry
kubectl delete job/crm-migrate -n crm
kubectl apply -f k8s/migrate-job.yaml