terraform-provider-onyx/README.md
Manages Onyx application configuration declaratively via the Onyx admin API: LLM providers, the deployment default model, API keys, workspace settings, and embedding providers.
Not to be confused with
deployment/terraform/, which provisions the infrastructure Onyx runs on (EKS, RDS, ...). This provider configures what runs inside an Onyx deployment.
| Name | Manages | Import id |
|---|---|---|
onyx_api_key | API keys (/admin/api-key) | numeric id |
onyx_llm_provider | LLM providers + their model list (/admin/llm/provider) | numeric id |
onyx_llm_provider_default | The deployment default (and vision) model — a singleton | default |
onyx_settings | Workspace settings — a singleton, partially managed | settings |
onyx_embedding_provider | Cloud embedding provider credentials | provider type (e.g. openai) |
onyx_credential | Connector credentials (/manage/credential) | numeric id |
onyx_connector | Connector definitions (/manage/admin/connector) | numeric id |
data.onyx_llm_providers | Read-only list of providers + defaults | — |
data.onyx_embedding_providers | Read-only list of embedding providers | — |
data.onyx_settings | Read-only current settings (incl. license tier) | — |
data.onyx_connectors | Read-only list of connectors | — |
Generated per-resource docs live in docs/.
The provider needs an API key in the seeded Admin group (or an unrestricted PAT created by an admin user). Create one in the Onyx admin panel (API Keys) or via the API — pass the Admin group id, since a key with no group has no admin permissions:
curl -X POST https://your-onyx/api/admin/api-key \
-H "Cookie: fastapiusersauth=<admin session>" \
-H "Content-Type: application/json" \
-d '{"name": "terraform", "group_ids": [<admin group id>]}'
This first key is inherently chicken-and-egg: it must exist before Terraform can run, so
either leave it unmanaged, or terraform import it afterwards (its api_key attribute
stays null — the material is only ever returned at creation).
provider "onyx" {
endpoint = "https://your-onyx.example.com" # or ONYX_SERVER_URL
api_key = var.onyx_api_key # or ONYX_API_KEY
# api_prefix defaults to "/api" (the web proxy). Set to "" when pointing
# directly at the backend (e.g. http://localhost:8080). Also: ONYX_API_PREFIX.
}
API keys work regardless of the deployment's human AUTH_TYPE (basic/OIDC/SAML/cloud),
and on Onyx Cloud the tenant is embedded in the key itself.
api_key/custom_config on read, so
rotating them out-of-band (e.g. in the admin UI) is invisible to terraform plan. The
configured value is authoritative and is re-asserted on the next apply.onyx_settings and onyx_llm_provider_default don't really delete. Onyx has no
reset-settings API and no unset API for the text/vision defaults; destroy removes them
from state with a warning and leaves the live values alone. The chat-naming default is
the exception: it has an unset API and is cleared on destroy when managed.onyx_embedding_provider updates replace all fields. Keep api_key in
configuration — an update applied without it clears the stored key (the API has no
keep-stored-key flag). The currently-active embedding provider also cannot be deleted.model_configurations is the list of record. Models omitted from it are removed
server-side, and removing the model currently set as deployment default fails — repoint
onyx_llm_provider_default first (references order this correctly).onyx_credential payloads are write-only. The API always returns credential_json
masked, so it is never refreshed or diffed. admin_public, curator_public and groups
have no update endpoint and force replacement instead.onyx_connector does not own its access control. access_type and groups are
validated on write but stored on the cc-pair, so Terraform cannot refresh them. Onyx also
rewrites an unset prune_freq to 7 days on the first update, which the provider then
keeps as the value of record.onyx_connector does not set access control. Onyx applies it when a credential is
associated, so it belongs to the connector-credential pair. The connector endpoints still
require an access_type in the request body but ignore it, so the provider sends a fixed
value rather than offering a knob that would do nothing.admin_public = false from admins other than its creator, and that is indistinguishable
from a deleted one, so Terraform would drop it from state and recreate it. Keep
admin_public = true (the default) for credentials Terraform manages, or run Terraform
with the key that created them.Requires Go (see go.mod) and the Terraform CLI.
go build ./... # build
go test ./... # unit tests (no Onyx needed)
Point Terraform at your locally-built binary with a dev_overrides block in
~/.terraformrc:
provider_installation {
dev_overrides {
"onyx-dot-app/onyx" = "/path/to/onyx/terraform-provider-onyx"
}
direct {}
}
Then go build here and run terraform plan/apply (skip terraform init) in any config
using the provider.
Acceptance tests run real CRUD cycles against a live Onyx deployment (they create and destroy providers/keys and briefly modify workspace settings — use a dev deployment):
TF_ACC=1 ONYX_TF_ACC_SERVER_URL=http://localhost:8080 go test ./internal/provider/ -v
ONYX_TF_ACC_API_PREFIX defaults to "" (direct backend). Set /api when targeting
the web server.ONYX_TF_ACC_API_KEY to an existing admin key, or let the harness bootstrap
one by logging in as ONYX_TF_ACC_ADMIN_EMAIL/ONYX_TF_ACC_ADMIN_PASSWORD (defaults:
[email protected] / TestPassword123!; on a fresh deployment the first
registered user becomes admin automatically).Without TF_ACC these tests skip, so plain go test ./... (and the repo's Go CI) stays
green with no Onyx running.
To test against an API server that does not touch your dev database, give it a database of its own. This reuses the running Postgres, Redis, OpenSearch and MinIO containers (the container name follows your compose project, so adjust it if yours differs):
docker exec onyx-relational_db-1 psql -U postgres -c "CREATE DATABASE onyx_tf_acc;"
cd backend && POSTGRES_DB=onyx_tf_acc uv run alembic upgrade head
POSTGRES_DB=onyx_tf_acc AUTH_TYPE=basic LICENSE_ENFORCEMENT_ENABLED=false \
ENABLE_PAID_ENTERPRISE_EDITION_FEATURES=true \
USER_AUTH_SECRET="$(openssl rand -hex 32)" \
uv run uvicorn onyx.main:app --port 8081
Each variable earns its place. AUTH_TYPE=basic gives the harness a login to bootstrap
its key with. License enforcement must be off or API key creation answers 402. The
enterprise features flag registers the user-group routes, which the harness reads to find
the Admin group its key needs.
docs/ is generated — edit schema MarkdownDescriptions and examples/, then:
go generate . # runs tfplugindocs; needs terraform on PATH
The public Terraform Registry requires a standalone GitHub repo named exactly
terraform-provider-onyx with GPG-signed goreleaser artifacts. Until a release mirror is
set up, install via dev_overrides (above) or a private registry/filesystem mirror.