> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to DigitalOcean

> Deploy CaseBender on DigitalOcean

<Warning>
  Reference architecture only. This page is not a production-certified deployment
  procedure and predates the current activation, image-pinning, secret-management,
  and network-isolation baseline. Use the [supported on-premises guide](/en/quickstart)
  or complete an enterprise architecture review before deployment.
</Warning>

## Overview

This guide walks you through deploying CaseBender on DigitalOcean using pre-built Docker images with Kubernetes (DOKS) and managed services.

## Prerequisites

1. [DigitalOcean Account](https://cloud.digitalocean.com/)
2. [doctl](https://docs.digitalocean.com/reference/doctl/how-to/install/) CLI installed
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) installed
4. [Docker](https://docs.docker.com/get-docker/) installed

## Step 1: Initial Setup

### Install and Configure doctl

<CodeGroup>
  ```bash macOS theme={null}
  # Using Homebrew
  brew install doctl

  # Authenticate with API token

  doctl auth init

  # Configure Docker for Container Registry

  doctl registry login

  ```

  ```bash Linux theme={null}
  # Download latest release
  cd ~/Downloads
  wget https://github.com/digitalocean/doctl/releases/download/v1.XX.X/doctl-1.XX.X-linux-amd64.tar.gz

  # Extract and move to path
  tar xf ~/Downloads/doctl-1.XX.X-linux-amd64.tar.gz
  sudo mv ~/Downloads/doctl /usr/local/bin

  # Authenticate with API token
  doctl auth init

  # Configure Docker for Container Registry
  doctl registry login
  ```

  ```powershell Windows theme={null}
  # Using Chocolatey
  choco install doctl

  # Authenticate with API token
  doctl auth init

  # Configure Docker for Container Registry
  doctl registry login
  ```
</CodeGroup>

## Step 2: Create Kubernetes Cluster

```bash theme={null}
# 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
```

## Step 3: Set Up Managed Services

### Create Spaces for Object Storage

```bash theme={null}
# 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 Managed PostgreSQL

```bash theme={null}
# 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 Managed Redis

```bash theme={null}
# 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
```

## Step 4: Configure Container Registry

```bash theme={null}
# 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
```

## Step 5: Deploy to Kubernetes

### Create Namespace

```bash theme={null}
kubectl create namespace casebender
```

### Create Secrets

```bash theme={null}
# 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"
```

### Deploy Applications

Create `deployment.yaml`:

```yaml theme={null}
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
```

Apply the deployments:

```bash theme={null}
kubectl apply -f deployment.yaml
```

### Create Services

Create `service.yaml`:

```yaml theme={null}
apiVersion: v1
kind: Service
metadata:
  name: casebender-app
  namespace: casebender
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 3000
  selector:
    app: casebender-app
```

Apply the service:

```bash theme={null}
kubectl apply -f service.yaml
```

## Step 7: Set Up Ingress

### Install NGINX Ingress Controller

```bash theme={null}
# 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
```

### Configure Ingress

Create `ingress.yaml`:

```yaml theme={null}
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
```

Apply the ingress:

```bash theme={null}
kubectl apply -f ingress.yaml
```

## Step 8: Set Up SSL with cert-manager

```bash theme={null}
# 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
```

## Monitoring and Maintenance

### Set Up Monitoring

```bash theme={null}
# 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
```

### Configure Horizontal Pod Autoscaling

Create `hpa.yaml`:

```yaml theme={null}
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
```

Apply the HPA:

```bash theme={null}
kubectl apply -f hpa.yaml
```

## Backup and Disaster Recovery

### Database Backups

DigitalOcean managed databases automatically handle backups. You can also:

```bash theme={null}
# Create manual backup
doctl databases backup casebender-db
```

### Configure Database Failover

```bash theme={null}
# Enable automatic failover
doctl databases replica casebender-db create \
  --region sfo2
```

## Security Best Practices

1. Enable DigitalOcean Cloud Firewall
2. Use private networking
3. Implement network policies
4. Regular security updates
5. Enable audit logging

## Cost Optimization

1. Use appropriate node sizes
2. Implement autoscaling
3. Use block storage wisely
4. Monitor resource usage
5. Consider reserved droplets

## Next Steps

* Set up CI/CD pipeline
* Configure monitoring alerts
* Implement logging solution
* Review security measures
