File: README.md
[ ](https://www.onyx.app/?utm_source=onyx_repo&utm_medium=github&utm_campaign=readme)
Onyx - The Open Source AI Platform
Onyx is the application layer for LLMs - bringing a feature-rich interface that can be easily hosted by anyone.
Onyx enables LLMs through advanced capabilities like RAG, web search, code execution, file creation, deep research and more.
Connect your applications with over 50+ indexing based connectors provided out of the box or via MCP.
[!TIP]
Deploy with a single command:textcurl -fsSL https://onyx.app/install_onyx.sh | bash
โญ Features
- ๐ Agentic RAG: Get best in class search and answer quality based on hybrid index + AI Agents for information retrieval
- Benchmark to release soon!
- ๐ฌ Deep Research: Get in depth reports with a multi-step research flow.
- Top of leaderboard as of Feb 2026.
- ๐ค Custom Agents: Build AI Agents with unique instructions, knowledge, and actions.
- ๐ Web Search: Browse the web to get up to date information.
- Supports Serper, Google PSE, Brave, SearXNG, and others.
- Comes with an in house web crawler and support for Firecrawl/Exa.
- ๐ Artifacts: Generate documents, graphics, and other downloadable artifacts.
- โถ๏ธ Actions & MCP: Let Onyx agents interact with external applications, comes with flexible Auth options.
- ๐ป Code Execution: Execute code in a sandbox to analyze data, render graphs, or modify files.
- ๐๏ธ Voice Mode: Chat with Onyx via text-to-speech and speech-to-text.
- ๐จ Image Generation: Generate images based on user prompts.
Onyx supports all major LLM providers, both self-hosted (like Ollama, LiteLLM, vLLM, etc.) and proprietary (like Anthropic, OpenAI, Gemini, etc.).
To learn more - check out our docs!
๐ Deployment Modes
Onyx supports deployments in Docker, Kubernetes, Helm/Terraform and provides guides for major cloud providers.
Detailed deployment guides found here.
Onyx supports two separate deployment options: standard and lite.
Onyx Lite
The Lite mode can be thought of as a lightweight Chat UI. It requires less resources (under 1GB memory) and runs a less complex stack.
It is great for users who want to test out Onyx quickly or for teams who are only interested in the Chat UI and Agents functionalities.
Standard Onyx
The complete feature set of Onyx which is recommended for serious users and larger teams. Additional components not included in Lite mode:
- Vector + Keyword index for RAG.
- Background containers to run job queues and workers for syncing knowledge from connectors.
- AI model inference servers to run deep learning models used during indexing and inference.
- Performance optimizations for large scale use via in memory cache (Redis) and blob store (MinIO).
[!TIP]
To try Onyx for free without deploying, visit Onyx Cloud.
๐ข Onyx for Enterprise
Onyx is built for teams of all sizes, from individual users to the largest global enterprises:
- ๐ฅ Collaboration: Share chats and agents with other members of your organization.
- ๐ Single Sign On: SSO via Google OAuth, OIDC, or SAML. Group syncing and user provisioning via SCIM.
- ๐ก๏ธ Role Based Access Control: RBAC for sensitive resources like access to agents, actions, etc.
- ๐ Analytics: Usage graphs broken down by teams, LLMs, or agents.
- ๐ต๏ธ Query History: Audit usage to ensure safe adoption of AI in your organization.
- ๐ป Custom code: Run custom code to remove PII, reject sensitive queries, or to run custom analysis.
- ๐จ Whitelabeling: Customize the look and feel of Onyx with custom naming, icons, banners, and more.
๐ Licensing
There are two editions of Onyx:
- Onyx Community Edition (CE) is available freely under the MIT license and covers all of the core features for Chat, RAG, Agents, and Actions.
- Onyx Enterprise Edition (EE) includes extra features that are primarily useful for larger organizations.
For feature details, check out our website.
๐ช Community
Join our open source community on Discord!
๐ก Contributing
Looking to contribute? Please check out the Contribution Guide for more details.
File: backend/alembic/README.md
Alembic DB Migrations
These files are for creating/updating the tables in the Relational DB (Postgres).
Onyx migrations use a generic single-database configuration with an async dbapi.
To generate new migrations:
From onyx/backend, run:alembic revision -m <DESCRIPTION_OF_MIGRATION>
Note: you cannot use the --autogenerate flag as the automatic schema parsing does not work.
Manually populate the upgrade and downgrade in your new migration.
More info can be found here: https://alembic.sqlalchemy.org/en/latest/autogenerate.html
Running migrations
To run all un-applied migrations:alembic upgrade head
To undo migrations:alembic downgrade -X
where X is the number of migrations you want to undo from the current state
Multi-tenant migrations
For multi-tenant deployments, you can use additional options:
Upgrade all tenants:
alembic -x upgrade_all_tenants=true upgrade headUpgrade specific schemas:
# Single schema
alembic -x schemas=tenant_12345678-1234-1234-1234-123456789012 upgrade head
# Multiple schemas (comma-separated)
alembic -x schemas=tenant_12345678-1234-1234-1234-123456789012,public,another_tenant upgrade headUpgrade tenants within an alphabetical range:
# Upgrade tenants 100-200 when sorted alphabetically (positions 100 to 200)
alembic -x upgrade_all_tenants=true -x tenant_range_start=100 -x tenant_range_end=200 upgrade head
# Upgrade tenants starting from position 1000 alphabetically
alembic -x upgrade_all_tenants=true -x tenant_range_start=1000 upgrade head
# Upgrade first 500 tenants alphabetically
alembic -x upgrade_all_tenants=true -x tenant_range_end=500 upgrade headContinue on error (for batch operations):
alembic -x upgrade_all_tenants=true -x continue=true upgrade headThe tenant range filtering works by:
- Sorting tenant IDs alphabetically
- Using 1-based position numbers (1st, 2nd, 3rd tenant, etc.)
- Filtering to the specified range of positions
- Non-tenant schemas (like 'public') are always included
File: backend/alembic_tenants/README.md
These files are for public table migrations when operating with multi tenancy.
If you are not a Onyx developer, you can ignore this directory entirely.
File: backend/generated/README.md
- Generated Files
- Generated files live here. This directory should be git ignored.
File: backend/onyx/connectors/README.md
Writing a new Onyx Connector
This README covers how to contribute a new Connector for Onyx. It includes an overview of the design, interfaces,
and required changes.
Thank you for your contribution!
Connector Overview
Connectors come in 3 different flows:
- Load Connector:
- Bulk indexes documents to reflect a point in time. This type of connector generally works by either pulling all
documents via a connector's API or loads the documents from some sort of a dump file.
- Bulk indexes documents to reflect a point in time. This type of connector generally works by either pulling all
- Poll Connector:
- Incrementally updates documents based on a provided time range. It is used by the background job to pull the latest
changes and additions since the last round of polling. This connector helps keep the document index up to date
without needing to fetch/embed/index every document which would be too slow to do frequently on large sets of
documents.
- Incrementally updates documents based on a provided time range. It is used by the background job to pull the latest
- Slim Connector:
- This connector should be a lighter weight method of checking all documents in the source to see if they still exist.
- This connector should be identical to the Poll or Load Connector except that it only fetches the IDs of the documents, not the documents themselves.
- This is used by our pruning job which removes old documents from the index.
- The optional start and end datetimes can be ignored.
- Event Based connectors:
- Connectors that listen to events and update documents accordingly.
- Currently not used by the background job, this exists for future design purposes.
Connector Implementation
Refer to interfaces.py
and this first contributor created Pull Request for a new connector (Shoutout to Dan Brown):
Reference Pull Request
For implementing a Slim Connector, refer to the comments in this PR:
Slim Connector PR
All new connectors should have tests added to the backend/tests/daily/connectors directory. Refer to the above PR for an example of adding tests for a new connector.
Implementing the new Connector
The connector must subclass one or more of LoadConnector, PollConnector, CheckpointedConnector, or CheckpointedConnectorWithPermSync
The __init__ should take arguments for configuring what documents the connector will and where it finds those
documents. For example, if you have a wiki site, it may include the configuration for the team, topic, folder, etc. of
the documents to fetch. It may also include the base domain of the wiki. Alternatively, if all the access information
of the connector is stored in the credential/token, then there may be no required arguments.
load_credentials should take a dictionary which provides all the access information that the connector might need.
For example this could be the user's username and access token.
Refer to the existing connectors for load_from_state and poll_source examples. There is not yet a process to listen
for EventConnector events, this will come down the line.
Development Tip
It may be handy to test your new connector separate from the rest of the stack while developing.
Follow the below template:
if __name__ == "__main__":
import time
test_connector = NewConnector(space="engineering")
test_connector.load_credentials({
"user_id": "foobar",
"access_token": "fake_token"
})
all_docs = test_connector.load_from_state()
current = time.time()
one_day_ago = current - 24 * 60 * 60 # 1 day
latest_docs = test_connector.poll_source(one_day_ago, current)Note: Be sure to set PYTHONPATH to onyx/backend before running the above main.
Supporting "Include Attachments"
If the source has attachments (files attached to pages, tickets, etc.), let admins opt out of
indexing them by following the shared convention:
- Accept an
include_attachments: boolkwarg in the connector's__init__. The value flows in
automatically fromconnector_specific_config; no factory or API changes are needed.- New connectors should default it to
False. - When retrofitting a connector that already indexes attachments unconditionally, default it to
Trueโ existing connector rows have noinclude_attachmentskey stored, so the constructor
default is what they get and their behavior must not change.
- New connectors should default it to
- Gate every attachment enumeration path on the flag: the main indexing pass and the
slim-doc pass (pruning / permission sync) if the connector has one. The slim pass must admit
exactly the same documents as the main pass โ emitting attachment slim docs the main pass
skipped leaves permanentchunk_count IS NULLrows, while correctly omitting them lets pruning
clean up previously indexed attachments after an admin turns the setting off. - In the frontend form, add
buildIncludeAttachmentsOption(<default>)fromweb/src/lib/connectors/connectors.tsxto the connector'sconnectorConfigsentry (use the
same default as the backend), and addinclude_attachments?: booleanto the connector's config
interface in that file.
ConfluenceConnector and DrupalWikiConnector are reference implementations.
Additional Required Changes:
Backend Changes
- Add a new type to
DocumentSource - Add a mapping from DocumentSource (and optionally connector type) to the right connector class
here
Frontend Changes
- Add the new Connector definition to the
SOURCE_METADATA_MAPhere. - Add the definition for the new Form to the
connectorConfigsobject here.
Docs Changes
Create the new connector page (with guiding images!) with how to get the connector credentials and how to set up the
connector in Onyx. Then create a Pull Request in https://github.com/onyx-dot-app/documentation.
Before opening PR
- Be sure to fully test changes end to end with setting up the connector and updating the index with new docs from the
new connector. To make it easier to review, please attach a video showing the successful creation of the connector via the UI (starting from theAdd Connectorpage). - Add a folder + tests under
backend/tests/daily/connectorsdirector. For an example, checkout the test for Confluence. In the PR description, include a guide on how to setup the new source to pass the test. Before merging, we will re-create the environment and make sure the test(s) pass. - Be sure to run the linting/formatting, refer to the formatting and linting section in
CONTRIBUTING.md
File: backend/slackbot_images/README.md
This folder is kept for backwards compatibility with released Slackbot versions that
hardcode GitHub raw URLs under backend/slackbot_images.
New Slackbot source icons live in web/public/slackbot-source-icons.
TODO(wenxi-onyx): Remove this directory after 2026-07-24, once stable releases have
moved off these legacy GitHub raw URLs.
File: deployment/aws_ecs_fargate/cloudformation/README.md
Onyx AWS ECS Fargate CloudFormation Deployment
This directory contains CloudFormation templates and scripts to deploy Onyx on AWS ECS Fargate.
Configuration
All configuration parameters are stored in a single JSON file: onyx_config.json. This file contains all the parameters needed for the different CloudFormation stacks.
Example:
{
"OnyxNamespace": "onyx",
"Environment": "production",
"EFSName": "onyx-efs",
"AWSRegion": "us-east-2",
"VpcID": "YOUR_VPC_ID",
"SubnetIDs": "YOUR_SUBNET_ID1,YOUR_SUBNET_ID2",
"DomainName": "YOUR_DOMAIN e.g ecs.onyx.app",
"ValidationMethod": "DNS",
"HostedZoneId": ""
}Required Parameters
Environment: Used to prefix all stack names during deployment. This is required.OnyxNamespace: Namespace for the Onyx deployment.EFSName: Name for the Elastic File System.AWSRegion: AWS region where resources will be deployed.VpcID: ID of the VPC where Onyx will be deployed.SubnetIDs: Comma-separated list of subnet IDs for deployment.DomainName: Domain name for the Onyx deployment.ValidationMethod: Method for domain validation (typically "DNS").- [optional]
HostedZoneId: Route 53 hosted zone ID (only if using Route 53 for DNS).
The deployment script automatically extracts the needed parameters for each CloudFormation template based on the parameter names defined in the templates.
Deployment Order
The deployment follows this order:
Infrastructure stacks:
- EFS
- Cluster
- ACM
Service stacks:
- Postgres
- Redis
- Vespa Engine
- Model Server (Indexing)
- Model Server (Inference)
- Backend API Server
- Backend Background Server
- Web Server
- Nginx
Usage
To deploy:
./deploy.shTo uninstall:
./uninstall.shFile: deployment/docker_compose/README.md
Welcome to Onyx
To set up Onyx there are several options, Onyx supports the following for deployment:
- Quick guided install via the install.sh script
- Pulling the repo and running
docker compose up -dfrom the deployment/docker_compose directory
- Note, it is recommended to copy over the env.template file to .env and edit the necessary values
- For large scale deployments leveraging Kubernetes, there are two options, Helm or Terraform.
This README focuses on the easiest guided deployment which is via install.sh.
For more detailed guides, please refer to the documentation: https://docs.onyx.app/deployment/overview
install.sh script
curl -fsSL https://raw.githubusercontent.com/onyx-dot-app/onyx/main/deployment/docker_compose/install.sh > install.sh && chmod +x install.sh && ./install.shThe script installs the Onyx CLI (onyx-cli) and hands over to onyx-cli deploy install, which is
where the guided installation lives. Any flags you pass are forwarded to it. If you already have the
CLI (pip install onyx-cli), skip the script and run onyx-cli deploy install directly.
This provides a guided installation of Onyx via Docker Compose. It will deploy the latest version of Onyx
and set up the volumes to ensure data is persisted across deployments or upgrades.
The deployment files are stored in ~/.config/onyx (an existing onyx_data directory from an older
install is detected and kept in place; --dir targets another location). Note that no application
critical data is stored in that directory so even if you delete it, the data needed to restore the app
will not be destroyed.
The data about chats, users, etc. are instead stored as named Docker Volumes. This is managed by Docker
and where it is stored will depend on your Docker setup. You can always delete these as well by runningonyx-cli deploy uninstall.
To shut down the deployment without deleting, use onyx-cli deploy stop.
Managing the deployment
Beyond installing, the CLI covers the rest of the lifecycle:
| Command | What it does |
|---|---|
onyx-cli deploy status |
Installed version, containers, and health (--json for scripts) |
onyx-cli deploy logs [service...] |
Logs of the deployment's containers |
onyx-cli deploy stop |
Stop the containers, keep the data |
onyx-cli deploy upgrade [--tag vX.Y.Z] |
Upgrade in place (see below) |
onyx-cli deploy uninstall |
Remove the containers, volumes, and deployment directory |
Upgrading the deployment
Onyx maintains backwards compatibility across all minor versions following SemVer, so upgrading isonyx-cli deploy upgrade (add --tag vX.Y.Z to pin a version). It rewrites only IMAGE_TAG, preserves
your .env edits, and backs up hand-edited files.
If you are more comfortable running docker compose commands, you can also run commands directly from
the directory with the docker-compose.yml file. First bring the containers down (docker compose down),
verify the version you want in the environment file (see below), (if using latest tag, be sure to rundocker compose pull) and run docker compose up to restart the services on the latest version
Environment variables
The Docker Compose files try to look for a .env file in the same directory. The installer sets it up
from a file called env.template. Feel free to edit the .env file to customize your deployment. The most
important / common changed values are located near the top of the file. Later onyx-cli deploy runs
keep your edits.
IMAGE_TAG is the version of Onyx to run. It is recommended to leave it as latest to get all updates with each redeployment.
Every image publishes a -dev twin for each of its tags (e.g. latest-dev, v1.2.3-dev), so a singleIMAGE_TAG=latest-dev selects the dev variant of the whole deployment. Today only the backend image actually differs:
its -dev twin adds interactive debugging tools (vim, nano, curl, ps, psql) that the default image leaves out to stay
minimal. The web-server, model-server, and sandbox -dev tags are identical to their plain counterparts and exist so
that one version string covers every image.
File: deployment/helm/README.md
Installing the chart
Helm repository (default)
helm repo add onyx https://onyx-dot-app.github.io/onyx
helm repo update
helm install onyx onyx/onyx -n onyx --create-namespaceChart tarballs are attached to GitHub releases named helm/onyx-<version>, andindex.yaml on the gh-pages branch points at them. This is an implementation
detail: the repository URL above does not change and helm repo add,helm search repo and helm upgrade all work as before.
OCI registry (alternative)
The same chart is published to GHCR:
helm install onyx oci://ghcr.io/onyx-dot-app/charts/onyx \
--version 0.8.16 -n onyx --create-namespacehelm repo add does not accept oci:// URLs, so an OCI install needs an
explicit --version. There is no helm repo update or helm search repo for
OCI and no helm command that lists the available versions. Read them from thehelm/onyx-<version> releases
or from the Helm repository index:
helm search repo onyx/onyx --versions # needs `helm repo add` from aboveTo inspect one version before installing it:
helm show chart oci://ghcr.io/onyx-dot-app/charts/onyx --version 0.8.16Both channels ship identical bytes from the same build. Use the Helm repository
unless you specifically need OCI.
Recent chart changes (0.5.0)
If you are upgrading from an earlier 0.4.x release, read MIGRATION.md first. The 0.5.0 release dropped the bundled Vespa subchart; chart 0.5.6 ships a guard that fails helm upgrade if the legacy da-vespa StatefulSet is still in the namespace so you don't lose the indexed data silently.
Other 0.5.0 changes:
- Redis โ the chart now bundles the
redis-operatorsubchart alongside theredissubchart. The operator installs the CRD that the Redis CR binds to,
sohelm installworks on a clean cluster without a separate CRD step. - PostgreSQL โ a CloudNativePG
ClusterCR is now rendered fromtemplates/postgres-cluster.yaml, sohelm installprovisions postgres
out of the box. The Cluster is named<release>-pg(service:<release>-pg-rw). Setpostgresql.enabled: falseand overrideconfigMap.POSTGRES_HOSTif you use an external database (RDS, etc.). - REDIS_HOST โ the configmap no longer appends
-masterto the redis
service name. If you previously overrodeREDIS_HOSTor had clients that
hard-coded the-mastersuffix, update them to point at the
redis-operator standalone service. - CNPG CRDs โ copied into
crds/cnpg-crds.yamlso Helm pre-installs
them before templates. The subchart's own CRD template is disabled
(postgresql.crds.create: false). Runscripts/check-cnpg-crds.shafter
bumping the CNPG subchart version to verify the copy is in sync. - Pre-delete hook โ a cleanup Job (
templates/pre-delete-cleanup.yaml)
deletes operator-managed CRs beforehelm uninstalltears down the
operators, ensuring finalizers are processed and namespace cleanup
completes promptly.
Dependency updates (when subchart versions are bumped)
- If updating subcharts, you need to run this before committing!
- cd charts/onyx
- helm dependency update .
Prerequisites
Redis operator (automatic with bundled Redis)
When redis.enabled: true (the chart default), the chart bundles and automatically
installs the redis-operator subchart alongside the redis subchart. The operator
provides the CRD that the Redis CR binds to, so helm install works on a clean
cluster without manual preparation.
No separate pre-install step is needed โ the chart handles the redis-operator
CRD and controller automatically as part of helm install onyx onyx/onyx.
If you don't want the bundled Redis (recommended for production environments using
managed Redis like AWS ElastiCache), see Using an external Redis
below and set redis.enabled: false to skip the operator entirely.
Onyx Craft with Kubernetes sandboxes
When configMap.ENABLE_CRAFT="true", the target cluster must run Kubernetes>= 1.33. Craft Helm deployments provision Kubernetes sandbox pods; Docker
is not a Helm deployment backend for Craft and configMap.SANDBOX_BACKEND is
not a bypass for this requirement.
Craft sandbox pods use native restartable init sidecar containers:sandbox-init runs and completes first, sidecar starts next as aninitContainers entry with restartPolicy: Always, and the main sandbox app
container starts after the sidecar's startup restore gate is ready.
The chart fails during render/install on older clusters so the incompatibility
is caught before sandbox provisioning. This guard does not apply to non-Craft
installs.
Using an external Redis
To point Onyx at an externally-managed Redis (e.g. AWS ElastiCache) and skip
the bundled Redis + operator entirely:
redis:
enabled: false
configMap:
# Override the chart-computed REDIS_HOST. Use the cluster/primary endpoint
# from your managed Redis. Avoid underscores โ they are invalid in K8s DNS
# labels and look identical to a hung service.
REDIS_HOST: "<elasticache-primary-endpoint>"
REDIS_PORT: "6379"
REDIS_SSL: "true" # set to "true" if in-transit encryption is enabled
auth:
redis:
enabled: true
# Pre-create a Secret in the release namespace holding the Redis password
# under the key `redis_password`.
existingSecret: "elasticache-auth-secret"
secretKeys:
REDIS_PASSWORD: redis_passwordSourcing secrets from an external secret manager (ESO)
The chart can render an ExternalSecret CR that has External Secrets
Operator materialize a single Kubernetes Secret
from an upstream provider (AWS Secrets Manager, GCP Secret Manager, Vault,
etc.). All auth.* sections then read their per-section keys from that
materialized Secret, and any loose env-var secrets are projected into pods
via envFrom.
Prerequisite: the chart does not install ESO. Install it separately and
create a SecretStore or ClusterSecretStore (e.g. aws-secrets-manager)
before enabling externalSecret. See https://external-secrets.io/ for setup.
The upstream secret should be a JSON object whose top-level keys map 1:1 to
the keys the chart expects in the materialized Secret (the union of everyauth.<section>.secretKeys value plus any loose env-var names you project viaextraEnvFromSecret).
externalSecret:
enabled: true
# Identifier of the upstream secret (e.g. AWS Secrets Manager secret name).
refPath: "onyx/<customer>/app-secrets"
# Name of the materialized k8s Secret. Point auth.*.existingSecret here.
secretName: onyx-app-secrets
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
refreshInterval: 1h
# Inject every key from onyx-app-secrets as an env var on backend pods.
# Use for secrets that today live as plaintext in `configMap:` blocks.
extraEnvFromSecret: onyx-app-secrets
auth:
postgresql:
existingSecret: onyx-app-secrets
secretKeys:
POSTGRES_USER: postgres_user
POSTGRES_PASSWORD: postgres_password
redis:
existingSecret: onyx-app-secrets
secretKeys:
REDIS_PASSWORD: redis_password
# ...repeat for any other auth section that should read from the shared Secret.When externalSecret.enabled: false (the default) the chart renders exactly
as before โ no ExternalSecret CR is created and envFrom is unchanged.
First-install reconciliation window
The Helm release renders both the ExternalSecret CR and the Deployments that
reference the materialized Secret in the same apply. ESO reconciles the CR
asynchronously, typically within a few seconds. During that brief window,
backend pods will be in CreateContainerConfigError because theirenvFrom: secretRef references a Secret that does not yet exist. The kubelet
retries pod creation automatically; once ESO materializes the Secret, pods
transition to Running without manual intervention.
We intentionally leave the secretRef non-optional. Marking it optional would
allow pods to boot with empty env vars and fail later in a way that is harder
to diagnose; the brief CreateContainerConfigError is the clearer failure
mode if anything is misconfigured (wrong SM path, missing IRSA permissions,
missing keys in the upstream blob).
If you need pods to be Ready before traffic is routed, rely on the existing
readiness probes โ they will not pass until the env vars are present.
Model-server pods
indexing-model-deployment and inference-model-deployment deliberately do
not consume extraEnvFromSecret. Model servers only need model-config
env vars (already in the chart's configMap), so injecting application-level
secrets like POSTGRES_PASSWORD would needlessly widen their secret-exposure
surface.
Values that come from docker-compose (do not copy them)
The Onyx docker-compose stack uses service-name hostnames like api_server,inference_model_server, and cache. Those names contain underscores, which
are invalid in Kubernetes DNS labels โ DNS lookups for them will fail and
the symptom is often a blank login page or TypeError: fetch failed in web
pod logs.
The chart computes correct K8s service hostnames for you. If you are
adapting an .env file from docker-compose, remove these keys from your
Helm configMap: and let the chart fill them in:
| Key | Don't set to (docker-compose) | Chart-computed default |
|---|---|---|
REDIS_HOST |
cache |
`redis.redisStandalone.name |
INTERNAL_URL |
http://api_server:8080 |
http://<release>-api-service:8080 |
API_SERVER_HOST |
api_server |
computed |
MODEL_SERVER_HOST |
inference_model_server |
<release>-inference-model-service |
INDEXING_MODEL_SERVER_HOST |
indexing_model_server |
<release>-indexing-model-service |
Other docker-compose-style values you should set deliberately:
DOMAINshould be your public hostname (e.g.onyx.example.com), notlocalhost. It affects cookies and CORS.WEB_DOMAINshould be the full origin (e.g.https://onyx.example.com).
Watch for typos likehhttps://...; they silently break email links and
OAuth redirects.
Local testing
This section covers chart-maintainer testing; for the Onyx Craft local-kind developer workflow, see docs/craft/dev/local-kubernetes.md.
One time setup
- brew install kind
- Ensure you have no config at ~/.kube/config
- kind create cluster
- mv ~/.kube/config ~/.kube/kind-config
Automated install and test with ct
- export KUBECONFIG=~/.kube/kind-config
- kubectl config use-context kind-kind
- from source root run the following. This does a very basic test against the web server
- ct install --all --helm-extra-set-args="--set=nginx.enabled=false" --debug --config ct.yaml
Output template to file and inspect
- cd charts/onyx
- helm template test-output . --set auth.opensearch.values.opensearch_admin_password='StrongPassword123!' > test-output.yaml
- Craft Kubernetes sandbox version guard check:
- expect failure:
helm template test-output . -f values-ci.yaml --kube-version 1.32.0 --show-only templates/craft-kubernetes-version-check.yaml - expect success:
helm template test-output . -f values-ci.yaml --kube-version 1.33.0 --show-only templates/craft-kubernetes-version-check.yaml
- expect failure:
Test the entire cluster manually
- cd charts/onyx
- helm install onyx . -n onyx --set postgresql.primary.persistence.enabled=false --set auth.opensearch.values.opensearch_admin_password='StrongPassword123!'
- the postgres flag is to keep the storage ephemeral for testing. You probably don't want to set that in prod.
- the OpenSearch admin password must be set on first install unless you are supplying
auth.opensearch.existingSecret. - no flag for ephemeral vespa storage yet, might be good for testing
- kubectl -n onyx port-forward service/onyx-nginx 8080:80
- this will forward the local port 8080 to the installed chart for you to run tests, etc.
- When you are finished
- helm uninstall onyx -n onyx
- Vespa leaves behind a PVC. Delete it if you are completely done.
- k -n onyx get pvc
- k -n onyx delete pvc vespa-storage-da-vespa-0
- If you didn't disable Postgres persistence earlier, you may want to delete that PVC too.
Run as non-root user
By default, some onyx containers run as root. If you'd like to explicitly run the onyx containers as a non-root user, update the values.yaml file for the following components:
celery_shared,api,webserver,indexCapability,inferenceCapabilityyamlsecurityContext: runAsNonRoot: true runAsUser: 1001vespayamlpodSecurityContext: fsGroup: 1000 securityContext: privileged: false runAsUser: 1000
Resourcing
In the helm charts, we have resource suggestions for all Onyx-owned components.
These are simply initial suggestions, and may need to be tuned for your specific use case.
Please talk to us in Slack if you have any questions!
Autoscaling options
The chart renders Kubernetes HorizontalPodAutoscalers by default. To keep this behavior, leaveautoscaling.engine as hpa and adjust the per-component autoscaling.* values as needed.
If you would like to use KEDA ScaledObjects instead:
- Install and manage the KEDA operator in your cluster yourself (for example via the official KEDA Helm chart). KEDA is no longer packaged as a dependency of the Onyx chart.
- Set
autoscaling.engine: kedain yourvalues.yamland enable autoscaling for the components you want to scale.
When autoscaling.engine is set to keda, the chart will render the existing ScaledObject templates; otherwise HPAs will be rendered.
File: deployment/README.md
Documentation for how to deploy Onyx can be found in our official docs:
https://docs.onyx.app/deployment/overview
Maintaining the compose files (contributors)
docker_compose/docker-compose.yml, docker-compose.prod.yml anddocker-compose.prod-no-letsencrypt.yml are generated from the single source of truthdocker_compose/docker-compose.template.yml โ do not hand-edit them. To change any of the three,
edit the template (per-variant differences are expressed with #!for / #!only / #!value
directives, documented in ods generate-compose --help) and regenerate:
ods generate-compose --writeThe generator lives in tools/ods (internal/composegen) and ships with the onyx-devtools
package. The docker-compose-sync pre-commit hook runs it automatically for commits touching the
template or the generated files, so a stray edit to a generated file gets reverted on the next
commit.
onyx-cli embeds copies of the guided-install deployment files (the generateddocker-compose.yml and docker-compose.prod.yml, the lite/craft overlays, the env templates,
the nginx config, and docker_compose/README.md) undercli/internal/deploy/deployfiles/embedded/. The same ods generate-compose --write run refreshes
them after rendering the variants, and a drift test in the cli module (go test ./...) gates
staleness. If you change any of those files, re-run the generator and commit the refreshed embedded
copies.
Note that docker_compose/README.md ships inside every self-hosted install, so keep it
user-facing โ contributor notes like this one belong here instead.