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

# Install on Kubernetes

> Deploy the Helm chart with your database, storage and model credentials.

Obtain the chart bundle, release images and registry credentials from EigenPal. The commands below assume the chart is in `./eigenpal`.

## Prepare services and secrets

Provide PostgreSQL, an existing S3-compatible bucket, and HTTPS ingress. Create these Secrets in the installation namespace:

* `eigenpal-db`: `DATABASE_URL`, `BETTER_AUTH_SECRET`.
* `eigenpal-s3`: `S3_ENDPOINT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET`, `S3_REGION`.
* `eigenpal-admin`: `ADMIN_EMAIL`, `ADMIN_PASSWORD`, `ADMIN_NAME`.
* `eigenpal-wrapping-key`: `EIGENPAL_SECRETS_WRAPPING_KEY`.
* `eigenpal-cron`: `CRON_SECRET`.

Use a session secret of at least 32 characters. Keep it and the wrapping key across upgrades. Add model credentials through [configEnv](https://docs.eigenpal.com/self-hosting/configuration.md#add-a-model). The chart's predefined AI keys use `eigenpal-ai`.

For private image pulls, create a `kubernetes.io/dockerconfigjson` Secret named `eigenpal-quay` using the supplied registry credentials.

## Install

Save these values as `values.yaml`. Replace `<release>` and the ingress host, add your [model configuration](https://docs.eigenpal.com/self-hosting/configuration.md#add-a-model), and configure `ingress.tls` for your certificate.

```yaml theme={null}
image:
  registry: quay.io/eigenpal
  app:
    tag: '<release>'
  worker:
    tag: '<release>'
  pullSecrets: [eigenpal-quay]

tenant:
  mode: single-tenant
telemetry:
  enabled: false
postgres:
  enabled: false
minio:
  enabled: false

secrets:
  create: false
  database:
    existingSecret: eigenpal-db
  auth:
    existingSecret: eigenpal-db
    secretKey: BETTER_AUTH_SECRET
  s3:
    existingSecret: eigenpal-s3
  admin:
    existingSecret: eigenpal-admin
  ai:
    existingSecret: eigenpal-ai
  secretsWrappingKey:
    existingSecret: eigenpal-wrapping-key
  cron:
    existingSecret: eigenpal-cron

ingress:
  enabled: true
  host: studio.example.internal
```

For a workflow-only installation, [disable agent sandboxes](https://docs.eigenpal.com/self-hosting/agent-sandboxes.md#disable-agent-filesystem-sandboxes) on app and worker.

```bash theme={null}
helm lint ./eigenpal -f values.yaml
helm upgrade --install eigenpal ./eigenpal \
  --namespace eigenpal --create-namespace \
  --values values.yaml --wait --wait-for-jobs --timeout 15m
```

Check that the migration Job succeeds and app/worker pods become ready. Sign in as the configured administrator, then run a workflow using your model provider.

## Platform-specific settings

> [accordion] OpenShift and scheduling
>
> Where your restricted SCC assigns IDs, set `podSecurityContext.runAsUser: null` and `fsGroup: null`. Keep the non-root and capability restrictions required by your cluster.
>
> Set resources, replicas, node selectors, tolerations, affinity and disruption budgets in the [Helm values](https://docs.eigenpal.com/self-hosting/helm-values.md). The chart does not provision worker autoscaling.

> [accordion] Migration jobs and evaluation services
>
> With external infrastructure, migrations run as a pre-install/pre-upgrade hook. They apply object-storage changes, optional pre-schema scripts, database migrations, then optional post-schema scripts. `migrate.scripts` is off for fresh installations; enable it when the upgrade path requires legacy-data migrations.
>
> For evaluation-only in-cluster PostgreSQL, set `migrate.hook: false` so the database can start before migrations. In-cluster MinIO also needs bucket initialization. Use the supplied evaluation overlay for those dependencies.

Read [Operations](https://docs.eigenpal.com/self-hosting/operations.md) before upgrading an existing installation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.