English
Deploy CaseBender on DigitalOcean
# Using Homebrew brew install doctl # Authenticate with API token doctl auth init # Configure Docker for Container Registry doctl registry login
# Create DOKS cluster doctl kubernetes cluster create casebender \ --region nyc1 \ --size s-2vcpu-4gb \ --count 3 \ --version latest # Get kubeconfig doctl kubernetes cluster kubeconfig save casebender
# Create Spaces bucket doctl spaces create casebender-storage \ --region nyc3 # Create Spaces access key doctl spaces access-key create # Note: Save the access key and secret key securely # They will be needed for application configuration
# Create database cluster doctl databases create \ --engine pg \ --name casebender-db \ --region nyc1 \ --size db-s-2vcpu-4gb \ --version 14 \ --num-nodes 1 # Create database doctl databases db create casebender-db casebender # Get connection details doctl databases connection casebender-db --format ConnectionString
# Create Redis cluster doctl databases create \ --engine redis \ --name casebender-redis \ --region nyc1 \ --size db-s-1vcpu-2gb \ --version 7 # Get connection details doctl databases connection casebender-redis --format ConnectionString
# Create container registry doctl registry create casebender-registry # Get registry endpoint REGISTRY_ENDPOINT=$(doctl registry get-endpoint) # Pull CaseBender images docker pull casebender/casebender:latest docker pull casebender/workflow-processor:latest docker pull casebender/misp-processor:latest # Tag images for registry docker tag casebender/casebender:latest registry.digitalocean.com/casebender-registry/app:latest docker tag casebender/workflow-processor:latest registry.digitalocean.com/casebender-registry/workflow-processor:latest docker tag casebender/misp-processor:latest registry.digitalocean.com/casebender-registry/misp-processor:latest # Push images docker push registry.digitalocean.com/casebender-registry/app:latest docker push registry.digitalocean.com/casebender-registry/workflow-processor:latest docker push registry.digitalocean.com/casebender-registry/misp-processor:latest # Add registry to Kubernetes cluster doctl kubernetes cluster registry add casebender
kubectl create namespace casebender
# Create secrets for database and Redis kubectl create secret generic db-credentials \ --namespace casebender \ --from-literal=postgres-url="postgresql://doadmin:password@casebender-db-do-user-1234567-0.b.db.ondigitalocean.com:25060/casebender?sslmode=require" \ --from-literal=redis-url="rediss://default:password@casebender-redis-do-user-1234567-0.b.db.ondigitalocean.com:25061" # Create secrets for application kubectl create secret generic app-secrets \ --namespace casebender \ --from-literal=auth-secret="your-auth-secret" \ --from-literal=auth-salt="your-auth-salt"
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: casebender-app namespace: casebender spec: replicas: 2 selector: matchLabels: app: casebender-app template: metadata: labels: app: casebender-app spec: containers: - name: app image: registry.digitalocean.com/casebender-registry/app:latest ports: - containerPort: 3000 env: - name: AUTH_SECRET valueFrom: secretKeyRef: name: app-secrets key: auth-secret - name: AUTH_SALT valueFrom: secretKeyRef: name: app-secrets key: auth-salt - name: POSTGRES_PRISMA_URL valueFrom: secretKeyRef: name: db-credentials key: postgres-url - name: REDIS_URL valueFrom: secretKeyRef: name: db-credentials key: redis-url --- apiVersion: apps/v1 kind: Deployment metadata: name: workflow-processor namespace: casebender spec: replicas: 1 selector: matchLabels: app: workflow-processor template: metadata: labels: app: workflow-processor spec: containers: - name: processor image: registry.digitalocean.com/casebender-registry/workflow-processor:latest env: - name: POSTGRES_PRISMA_URL valueFrom: secretKeyRef: name: db-credentials key: postgres-url - name: REDIS_URL valueFrom: secretKeyRef: name: db-credentials key: redis-url --- apiVersion: apps/v1 kind: Deployment metadata: name: misp-processor namespace: casebender spec: replicas: 1 selector: matchLabels: app: misp-processor template: metadata: labels: app: misp-processor spec: containers: - name: processor image: registry.digitalocean.com/casebender-registry/misp-processor:latest env: - name: POSTGRES_PRISMA_URL valueFrom: secretKeyRef: name: db-credentials key: postgres-url - name: REDIS_URL valueFrom: secretKeyRef: name: db-credentials key: redis-url
kubectl apply -f deployment.yaml
service.yaml
apiVersion: v1 kind: Service metadata: name: casebender-app namespace: casebender spec: type: ClusterIP ports: - port: 80 targetPort: 3000 selector: app: casebender-app
kubectl apply -f service.yaml
# Add Helm repository helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update # Install NGINX Ingress Controller helm install nginx-ingress ingress-nginx/ingress-nginx \ --namespace casebender \ --set controller.publishService.enabled=true
ingress.yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: casebender-ingress namespace: casebender annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - your-domain.com secretName: casebender-tls rules: - host: your-domain.com http: paths: - path: / pathType: Prefix backend: service: name: casebender-app port: number: 80
kubectl apply -f ingress.yaml
# Install cert-manager kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml # Create ClusterIssuer cat <<EOF | kubectl apply -f - apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@domain.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx EOF
# Install metrics server kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # Deploy Prometheus and Grafana helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install prometheus prometheus-community/kube-prometheus-stack \ --namespace monitoring \ --create-namespace
hpa.yaml
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: casebender-app-hpa namespace: casebender spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: casebender-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 80
kubectl apply -f hpa.yaml
# Create manual backup doctl databases backup casebender-db
# Enable automatic failover doctl databases replica casebender-db create \ --region sfo2