The SAALT Helm chart deploys a complete SAALT instance on Kubernetes or OpenShift with a single helm install. The chart is published as a Helm repository at https://docs.saalt.ai/helm.
What the chart deploys
| Component | Kind | Purpose |
|---|---|---|
| SAALT core | Deployment + Service (port 3000) | Web UI, API and background jobs. Runs database migrations on every start. |
| Document parser | Deployment | Converts uploaded files (PDF, Office, audio, scans) for Knowledge. |
| PostgreSQL with pgvector | StatefulSet (optional) | Main database and vector store. |
| Redis | StatefulSet (optional) | Cache and job queue shared by core and the document parser. |
| Storage volume | PersistentVolumeClaim (optional) | Uploaded files, mounted at /app/storage. |
The bundled PostgreSQL and Redis are enabled by default. You can turn them off and use managed services instead (see Use an external database and Redis).
Prerequisites
- A Kubernetes or OpenShift 4 cluster.
- Helm 3 or newer, and
kubectl(oroc) pointed at your cluster. - A default StorageClass, or the name of one to set in the values.
- Credentials for the SAALT container registry, stored as an image pull secret in the target namespace.
- At least one LLM provider API key (for example OpenAI, Anthropic or Google).
Quick start
-
Add the SAALT Helm repository:
Code -
Create the namespace and the image pull secret:
Code -
Install the chart:
Code -
Watch the first start. Core runs the database migrations before it starts serving:
Code -
Open it locally to try it before you set up a domain:
CodeThen open
http://localhost:3000.
APP_SECRET signs sessions and must stay the same across upgrades. Store it somewhere safe. If you lose it, every user is signed out.
Use a values file
Long --set lists are hard to maintain. Put your settings in a values.yaml file and pass it with -f:
Code
Code
All options are documented inline in the chart's default values. Print them with:
Code
Configure secrets
SAALT reads its configuration from environment variables. There are two ways to provide secret values:
secretsmap (quick start). Every key undersecrets:goes into a Secret that the chart creates and core loads. This is convenient, but the values end up in your values file and the Helm release history.- Your own Secret (recommended for production). Create the Secret yourself, for example with External Secrets, Sealed Secrets or Vault, and reference it with
core.envFrom. The chart never sees the values.
Code
Code
Use core.env for plain, non-secret values and core.extraEnv for single variables read from a Secret key:
Code
Variables the chart sets for you
| Variable | Set when |
|---|---|
APP_URL | Always, from appUrl. |
INTERNAL_APP_URL | Always. Lets the document parser reach core inside the cluster. |
NODE_ENV | Always (production). |
CLIENT_MODEL_CONFIG_ENABLED | Always (true). Models are managed in Admin → Models. |
DATABASE_URL | postgresql.enabled: true |
REDIS_HOST, REDIS_PORT, REDIS_PASSWORD | redis.enabled: true (set on core and the document parser) |
A value you put in core.env overrides the chart's value for the same variable. See Environment variables for every variable SAALT reads.
Expose SAALT
Pick the option that matches your cluster. All three point at the saalt Service on port 3000.
Ingress:
Code
Gateway API (HTTPRoute):
Code
OpenShift Route:
Code
Agent responses are streamed and can take several minutes. Raise the request or idle timeout of your ingress controller or load balancer to at least 600 seconds, otherwise long answers are cut off. The OpenShift Route sets this for you.
Install on OpenShift
The chart runs under OpenShift's default restricted-v2 security policy without any extra permissions. Set openshift: true:
Code
On OpenShift the chart doesn't pin container user IDs. OpenShift assigns them from the project's range instead. helm install detects OpenShift automatically, but tools that render the chart offline (helm template, Argo CD) can't, so set openshift: true explicitly there.
Example: OpenShift with LiteLLM
This quick start installs SAALT on OpenShift and sends all model traffic through a LiteLLM proxy that already runs in the cluster. LiteLLM exposes an OpenAI-compatible API in front of your model providers, so SAALT needs only one URL and one key. SAALT imports the model list from LiteLLM, and you pick the active models in the SAALT admin UI.
The example assumes:
- LiteLLM is reachable in-cluster at
http://litellm.litellm.svc.cluster.local:4000. - You have a LiteLLM virtual key (or the master key) for SAALT.
- Your OpenShift apps domain is
apps.example.com.
-
Create the project and the image pull secret:
Code -
Store the SAALT secrets.
LITELLM_API_KEYis the LiteLLM key SAALT uses to list models and send every model request:Code -
Save the values as
openshift-litellm.yaml:Code -
Install the chart:
Code -
Wait for the first start (database migrations run before the server listens), then open
https://saalt.apps.example.com:Code -
Activate models. Sign in as a super admin and open Admin → Models. The LiteLLM section lists every model from your LiteLLM
model_list, with pricing read from LiteLLM:- Tick the models SAALT users should be able to choose. Add tags if needed, for example
deep_research. - Above the table, choose the default primary model (chats and Agent reasoning), the default utility model (titles, summaries, routing) and, if you activated an embedding model, the default embedding model (Knowledge search).
Until you activate the first model, SAALT keeps using its built-in model list, so a fresh install always has models.
- Tick the models SAALT users should be able to choose. Add tags if needed, for example
You can also add a model by hand. In Admin → Models, click Add model and enter a display name, the model ID and the endpoint URL of any OpenAI-compatible server (for example http://vllm.example.svc:8000/v1). The endpoint's key must be in an environment variable whose name starts with CUSTOM_LLM_, such as CUSTOM_LLM_MY_VLLM. Add it to the saalt-config Secret, then restart core with oc rollout restart deploy/saalt so it picks up the new variable.
If the litellm project restricts traffic with NetworkPolicies, allow ingress on port 4000 from the saalt project. Otherwise SAALT can't reach the proxy, and chats fail with a connection error.
Use an external database and Redis
To use a managed PostgreSQL (with the pgvector extension) and a managed Redis, disable the bundled ones and provide the connection settings:
Code
Core and the document parser must use the same Redis.
Bundled database passwords
If you leave postgresql.auth.password and redis.auth.password empty, the chart generates random passwords on the first install and reuses them on every upgrade.
Tools that render the chart without cluster access, such as Argo CD or helm template, would generate a new password on every render and lock SAALT out of its database. In that case set the passwords yourself, or point to an existing Secret with a password key:
Code
Use URL-safe characters for the PostgreSQL password, because it goes into DATABASE_URL. Don't use quotes or backslashes in the Redis password.
File storage
By default core stores uploaded files on a 20 GiB ReadWriteOnce volume. With a ReadWriteOnce volume the chart restarts core with the Recreate strategy, which means a few seconds of downtime per upgrade.
For zero-downtime upgrades or more than one core replica, use a ReadWriteMany StorageClass:
Code
If you configure object storage for SAALT instead, set core.persistence.enabled: false.
Upgrade
Fetch the latest chart and upgrade:
Code
Core applies pending database migrations automatically when it starts. To pin a specific SAALT version instead of the chart's default, set core.image.tag and documentParser.image.tag.
Uninstall
Code
To protect your data, helm uninstall keeps the following:
- the storage volume
saalt-storage; - the generated
saalt-postgresqlandsaalt-redispassword Secrets; - the PostgreSQL and Redis data volumes.
Delete them manually if you want to remove all data. To reinstall under the same release name while keeping the data, Helm first has to adopt the kept Secrets:
Code
Add platform-specific resources
Use extraObjects to ship extra manifests with the release, such as an ExternalSecret or a load-balancer policy. Values are rendered as templates, so you can reference the release:
Code
Next steps
- Getting started — sign in and set up your first Space and Agent.
- Apps — add Apps to your instance. Apps run as their own services and are registered in SAALT, not deployed by this chart.