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

# Self-hosting

> Deploy Adaptive Engine with Kubernetes and Helm

Deploy Adaptive Engine on your own infrastructure using the [Helm chart](https://github.com/adaptive-ml/adaptive-helm-chart).

<Info>
  Self-hosted deployments have no external connectivity or telemetry requirements.
</Info>

## Prerequisites

### Infrastructure

1. **Kubernetes cluster** with:
   * GPU VM(s) for `harmony` compute plane
   * CPU VM(s) for `control-plane` and `recipe-runner`
2. **PostgreSQL 16+** (local or remote)
3. **Redis** (local or remote)
4. **Shared storage** (POSIX or S3-compatible)
5. **OIDC provider** (Google Workspace, Azure Entra ID, Cognito, Keycloak, etc.)
6. **Domain name** routing to the deployment

### Kubernetes requirements

* Kubernetes 1.28+
* Helm 3.8.0+
* NVIDIA GPU operator
* CUDA 12.8+ with driver 570.172.08+

## Deployment checklist

<Steps>
  <Step title="Verify GPU quota">
    Ensure cloud GPU quotas accommodate your instance types and counts.
  </Step>

  <Step title="Provision infrastructure">
    Deploy Kubernetes cluster, database, Redis, storage, and configure OIDC.
  </Step>

  <Step title="Get container registry access">
    Obtain access to Adaptive Engine private registry (requires commercial contract).
  </Step>

  <Step title="Configure Helm values">
    Pull the chart and customize `values.yaml`.
  </Step>

  <Step title="Deploy">
    Run `helm install`.
  </Step>
</Steps>

<Warning>
  Set administrator emails in `values.yaml` before those users first log in.
</Warning>

## Helm configuration

### Container registry

```yaml theme={null}
containerRegistry: <aws_account_id>.dkr.ecr.<region>.amazonaws.com
harmony:
  image:
    repository: adaptive-repository
    tag: harmony:latest
controlPlane:
  image:
    repository: adaptive-repository
    tag: control-plane:latest
```

### Resource limits

```yaml theme={null}
harmony:
  replicaCount: 1
  gpusPerReplica: 8  # Match available GPUs per node
  resources:
    limits:
      cpu: 8
      memory: 64Gi
    requests:
      cpu: 8
      memory: 60Gi
```

### Secrets

```yaml theme={null}
secrets:
  modelRegistryUrl: "s3://bucket-name/model_registry"
  sharedDirectoryUrl: "s3://bucket-name/shared"
  dbUrl: "postgres://user:password@host:5432/db_name"
  cookiesSecret: "must-be-64-chars-or-more-change-me-secret-abc123..."

  auth:
    oidc:
      providers:
        - name: "Google"
          key: "google"
          issuer_url: "https://accounts.google.com"
          client_id: "your-client-id"
          client_secret: "your-client-secret"
          scopes: ["email", "profile"]
          pkce: true
          allow_sign_up: true
```

<Warning>
  If `allow_sign_up: true`, any OIDC member can access Adaptive Engine. Set to `false` and create users via SDK to restrict access.
</Warning>

## Shared cluster configuration

### Separate namespace

```bash theme={null}
helm install adaptive adaptive/adaptive \
  --values ./values.yaml \
  --namespace adaptive-engine \
  --create-namespace
```

### Node selectors

Schedule Harmony on specific GPU nodes:

```yaml theme={null}
harmony:
  nodeSelector:
    eks.amazonaws.com/nodegroup: p5-h100
```

### Dedicated GPU nodes

Taint GPU nodes to prevent other workloads:

```bash theme={null}
kubectl taint nodes <node_name> dedicated=adaptive-engine:NoSchedule
```

Add matching toleration in `values.yaml`:

```yaml theme={null}
harmony:
  tolerations:
  - key: dedicated
    operator: Equal
    value: adaptive-engine
    effect: NoSchedule
```

## Database TLS

### Basic encryption

```yaml theme={null}
dbUrl: "postgres://user:password@host/db?sslmode=require"
```

### Certificate verification

For full verification (`sslmode=verify-full`):

1. Download the database server certificate
2. Create a ConfigMap:
   ```bash theme={null}
   kubectl create configmap -n <namespace> db-ca --from-file=rds-ca-rsa2048-g1.pem
   ```
3. Mount in `values.yaml`:
   ```yaml theme={null}
   volumes:
     - name: db-ca
       configMap:
         name: db-ca
   volumeMounts:
     - name: db-ca
       mountPath: /mnt/db-ca/
       readOnly: true
   ```
4. Reference in connection string:
   ```yaml theme={null}
   dbUrl: "postgres://user:password@host/db?sslmode=verify-full&sslrootcert=/mnt/db-ca/rds-ca-rsa2048-g1.pem"
   ```
