Skip to main content
The Onyx Terraform provider manages the configuration inside a running Onyx deployment: LLM providers, connectors and their credentials, document sets, agents, actions, MCP servers, user groups, API keys, and workspace settings. Everything you would otherwise click through in the Admin Panel becomes a version-controlled .tf file that you can review, diff, and apply from CI.

onyx-dot-app/onyx on the Terraform Registry

The registry holds the full reference: every resource, every attribute, and the import syntax. This page covers what the provider is for and how to get started.

Two different Terraform surfaces

Onyx has two separate Terraform offerings. They solve different problems and are used at different times.
The two compose. Provision infrastructure with the modules, install Onyx with the Helm chart, then configure the deployment with this provider. You can run them from the same root module, but they are independent — the provider works against any reachable Onyx deployment, including Onyx Cloud, regardless of how it was deployed.

Requirements

  • Terraform 1.5 or later. Write-only secret arguments — the recommended way to keep credentials out of state — need 1.11 or later, and an older CLI rejects a configuration that uses one.
  • A reachable Onyx deployment. The provider is an API client; it does not install or upgrade Onyx.
  • An API key in the Admin group. An API key’s access comes from its group membership, so a key with no group cannot reach the admin endpoints the provider uses.

Get an API key

Create a key in the Admin Panel under API Keys — see Service Accounts — and give it admin access. An unrestricted Personal Access Token created by an admin also works. API keys authenticate the same way whatever the deployment’s human AUTH_TYPE is (basic, OIDC, SAML, or cloud), and on Onyx Cloud the tenant is embedded in the key itself.
This first key is a chicken-and-egg problem: it has to exist before Terraform can run. Either leave it unmanaged, or terraform import it afterwards. On import its api_key attribute stays null, because Onyx only ever returns the key material at creation.
For a scripted setup, examples/bootstrap/mint_api_key.sh runs the whole sequence: register, log in, resolve the Admin group, mint the key.
The script requires an admin email and password rather than defaulting them. On a deployment with no users it registers that account, and the first user to register becomes an admin — so a defaulted password would quietly create a known-password administrator on any reachable deployment.

Configure the provider

main.tf
string
Onyx server origin, for example https://cloud.onyx.app or http://localhost:3000. Also read from ONYX_SERVER_URL.
string
An API key (on_...) in the seeded Admin group, or an unrestricted personal access token (onyx_pat_...). Also read from ONYX_API_KEY.
string
default:"/api"
Path prefix the API is served under. The default matches the web proxy. Set it to "" when you point the provider directly at the backend, for example http://localhost:8080. Also read from ONYX_API_PREFIX.
Supply api_key from the ONYX_API_KEY environment variable rather than a .tf file. Provider configuration is the one place Terraform never writes to state, so an environment variable keeps the key out of both your repository and your state file.

What you can manage

Each entry links to its full schema on the Terraform Registry.

Resources

Data sources

Every resource supports terraform import, so you can bring a deployment configured by hand under Terraform without recreating anything. The import id is on each resource’s registry page.

A worked example

This wires a chat model to an indexed site and an agent that answers from it. It is the shape most configurations take: a provider, a credential, a connector, the pair that links them, a document set, and an agent.
A complete, runnable version of this configuration lives in examples/bootstrap/.

Keeping secrets out of state

Every secret the provider accepts comes in two forms. The plain attribute is stored in Terraform state, where anyone who can read the state file can read the secret. The _wo twin is a write-only argument: Terraform strips the value from both the plan and the state, so it exists only in your configuration. Prefer the twin. Set one or the other, never both.

Rotating a write-only secret

A value Terraform never stores is a value it cannot diff, so changing api_key_wo on its own plans nothing at all. Each twin has a _wo_version counter for exactly this: raise it, and the resulting diff makes the next apply send the current secret.
Do not derive the counter from the secret — md5(var.token) and similar. Unlike the secret, the counter is kept in state.
Two attributes cannot have a write-only twin. onyx_api_key.api_key is minted by Onyx rather than supplied by you, so Terraform can only hand it back through state — treat the state file as holding it. onyx_mcp_server.auth_template_headers is computed by Onyx, and Terraform does not allow an argument to be both computed and write-only.
Regardless of which form you use, encrypt your Terraform state and restrict who can read it. Several resources hold credentials for systems well outside Onyx.

Enterprise Edition

Most of the provider works on Community Edition. These parts need Enterprise Edition:
  • onyx_user_group — the routes live in the Enterprise application and answer 404 on Community Edition.
  • users and groups on onyx_document_set and onyx_persona — Community Edition rejects a private set or agent.
Enterprise Edition FeatureThese features require an Enterprise plan. View plans or contact sales to learn more.

Things the API cannot express

A few behaviours come from the Onyx API rather than the provider, and are worth knowing before you rely on them:
  • Secret drift is invisible. The API masks secrets on read, so rotating one in the Admin Panel does not show up in terraform plan. The configured value is authoritative and is re-asserted on the next apply.
  • onyx_settings and onyx_llm_provider_default do not really delete. Onyx has no reset API for either, so destroy removes them from state with a warning and leaves the live values alone.
  • model_configurations is the list of record. A model left out of it is removed from the provider server-side.
  • Deleting an agent leaves a tombstone. The name stays taken, and a later create under that name revives the same agent id rather than making a new one.
  • Deleting a custom action detaches it from every agent that uses it, including agents Terraform does not manage, with no error and no warning.
The provider README carries the full list, and each resource’s registry page repeats the ones that apply to it.

Source and releases

Pin the provider version in required_providers and let Terraform’s lock file pick up the checksums, the same as any other provider. The registry page always shows the current release.