Onyx Terraform Provider 使用指南:通过 Onyx 管理 API 声明式管理 LLM Provider、API Key 与工作区配置
2026/9/10 1:46:13 网站建设 项目流程

Onyx Terraform Provider 使用指南:通过 Onyx 管理 API 声明式管理 LLM Provider、API Key 与工作区配置

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

本文以terraform-provider-onyx为核心,介绍如何使用 Terraform 通过 Onyx 管理 API 对 Onyx(AI 聊天平台)应用层配置进行声明式管理——涵盖 Provider 认证配置、可管理的资源与数据源、密钥安全实践(write-only 参数)以及已知 API 限制。读完本文,你将掌握从零接入 Onyx Provider、编写首个可落地的 Terraform 配置,以及安全托管 API Key 与 LLM Provider 的完整方案。

Provider 定位:管理"运行在 Onyx 内部"的配置

terraform-provider-onyx是 Onyx 官方 Terraform Provider,其目标是在 Terraform 中以声明式方式管理Onyx 应用配置:LLM Provider、部署默认模型、API Key、工作区设置、Embedding Provider 等,全部经由 Onyx 管理 API 完成读写。官方文档的描述非常精炼:

Manage Onyx application configuration (LLM providers, API keys, workspace settings, ...) declaratively via the Onyx admin API.

需要特别区分的是:仓库 deployment/terraform 目录用于部署 Onyx 运行所需的基础设施(EKS、RDS 等),而本 Provider 配置的是某个 Onyx 部署内部运行的东西。两者互补但职责完全不同——前者回答"Onyx 跑在哪里",后者回答"Onyx 里配了什么"。

Provider 源码位于 terraform-provider-onyx 目录,核心入口是 internal/provider/provider.go,基于 HashiCorp 的terraform-plugin-framework框架实现。

Provider 认证与三项核心配置参数

Provider 的全部配置集中在endpointapi_keyapi_prefix三个参数上,均可在.tf文件中声明,也可通过环境变量注入。依据 index.md 的 Schema 定义,参数说明如下:

参数类型说明环境变量
endpointStringOnyx 服务器源地址(origin),例如https://cloud.onyx.apphttp://localhost:3000ONYX_SERVER_URL
api_keyString, Sensitive位于种子Admin组的 Onyx API Key(on_...),或不受限的个人访问令牌(onyx_pat_...ONYX_API_KEY
api_prefixStringAPI 挂载的路径前缀,默认/api(Web 代理);直连后端(如http://localhost:8080)时设为""ONYX_API_PREFIX

最小可用配置

terraform { required_providers { onyx = { source = "onyx-dot-app/onyx" } } } variable "onyx_api_key" { type = string sensitive = true } # Credentials can also come from ONYX_SERVER_URL / ONYX_API_KEY env vars. provider "onyx" { endpoint = "https://onyx.internal.example.com" api_key = var.onyx_api_key # an API key in the Admin group ("on_...") }

其中api_prefix不写时默认取/api。当你直连后端服务(http://localhost:8080)时需显式置空,例如本地开发或接测试套件时。

配置优先级与校验逻辑

从源码看,provider.go 的Configure阶段对环境变量与属性做了明确的优先级合并:

  • endpoint:先取ONYX_SERVER_URL,若配置中显式设置了endpoint则以配置为准;
  • api_key:先取ONYX_API_KEY,配置中的api_key优先;
  • api_prefix:默认/apiONYX_API_PREFIX可覆盖,配置中的api_prefix优先级最高。

endpointapi_key最终为空,Provider 会直接报错并给出创建密钥的指引。同时,Provider 拒绝接收"未知(unknown)"的配置值——当endpoint/api_key/api_prefix派生自尚未 apply 的资源时,会在 plan 阶段直接报错,而不是静默当作空值处理。

客户端实现见 internal/client/client.go:请求会同时携带AuthorizationX-Onyx-Authorization两个 Bearer 头(后者优先被服务端检查,可穿透会消费Authorization头的代理),并以terraform-provider-onyx/<version>作为 User-Agent;对 429 限流一律重试,而 POST 等可能已产生副作用的请求遇到传输错误则不重放。

认证方式与 API Key 的获取

Provider 需要一个位于种子Admin组的 API Key(或无组限制的 PAT)。获取方式有两种:

  1. 管理面板:在 Onyx 管理后台的Settings -> Service Accounts中创建;
  2. 命令行:调用管理 API 手工铸造,注意必须传入 Admin 组 id——不带组的 Key 没有任何管理权限:
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>]}'

仓库提供了自动化脚本 examples/bootstrap/mint_api_key.sh,完整执行"注册 → 登录 → 解析 Admin 组 → 铸造 Key"的流程,适合 CI 或脚本化首次部署。它强制要求ONYX_ADMIN_EMAILONYX_ADMIN_PASSWORD而不提供默认值:在无用户的部署上,脚本会注册该账号,且第一个注册的用户自动成为管理员——若给默认密码,等于在任何可达部署上悄悄创建一个已知口令的管理员。

值得注意的两点:

  • API Key 的有效性与部署的人类用户AUTH_TYPE(basic/OIDC/SAML/cloud)无关;
  • 在 Onyx Cloud 上,租户信息内嵌于 Key 本身。

资源与数据源总览

Provider 注册了 13 个资源与 4 个数据源(见 provider.go 的Resources/DataSources方法)。依据 README.md 汇总如下:

名称管理内容Import id
onyx_api_keyAPI Key(/admin/api-key数字 id
onyx_llm_providerLLM Provider 及其模型列表(/admin/llm/provider数字 id
onyx_llm_provider_default部署默认(及视觉)模型——单例default
onyx_settings工作区设置——单例,部分托管settings
onyx_embedding_provider云端 Embedding Provider 凭据provider 类型(如openai
onyx_credential连接器凭据(/manage/credential数字 id
onyx_connector连接器定义(/manage/admin/connector数字 id
onyx_cc_pair连接器-凭据配对(/manage/connector/.../credential/...数字 id
onyx_document_set文档集(/manage/admin/document-set数字 id
onyx_custom_tool自定义动作(/admin/tool/custom数字 id
onyx_agentAgent / 助手(/persona数字 id
onyx_mcp_serverOnyx 连接的 MCP 服务器(/admin/mcp数字 id
onyx_user_group用户组:成员、管理者、权限授予(仅企业版数字 id
data.onyx_llm_providers只读:Provider 列表 + 默认模型
data.onyx_embedding_providers只读:Embedding Provider 列表
data.onyx_settings只读:当前设置(含许可证tier
data.onyx_connectors只读:连接器列表

每个资源的生成文档位于 terraform-provider-onyx/docs 下的data-sources/与资源对应页面。

实战:一个完整的"第一天"配置

examples/bootstrap/ 提供了一个可运行的 day-one 配置:创建一个聊天模型、索引一个公开文档站点、将结果归入文档集,并添加一个从该文档集作答的 Agent,全部工作在 Community Edition 上可用(onyx_user_group是唯一例外,需开启企业特性)。

terraform { required_version = ">= 1.5" required_providers { onyx = { source = "onyx-dot-app/onyx" } } } # Reads ONYX_SERVER_URL and ONYX_API_KEY when the variables are unset. provider "onyx" { endpoint = var.onyx_server_url api_key = var.onyx_api_key }

工作区与聊天模型

# 仅管理此处设置的属性。销毁该资源不会重置已写入的设置。 resource "onyx_settings" "workspace" { company_name = var.company_name } resource "onyx_llm_provider" "openai" { name = "openai" provider_type = "openai" api_key = var.openai_api_key # 完整的启用模型集合:任何被省略的模型都会在 apply 时被移除。 model_configurations = [ { name = "gpt-5" }, { name = "gpt-5-mini" }, ] } # 引用 provider id 也保证了销毁顺序:默认模型先于持有它的 provider 被释放。 resource "onyx_llm_provider_default" "this" { provider_id = onyx_llm_provider.openai.id model_name = "gpt-5" }

onyx_settings是"部分托管"的单例——从源码 settings_resource.go 可见,未在配置中设置的属性在服务端保持不动,从配置中移除某属性意味着"停止管理"而非"重置"。可写属性包括company_namemaximum_chat_retention_daysanonymous_user_enabledinvite_only_enableddeep_research_enabledmulti_model_chat_enabledsearch_ui_enabledquery_history_typeuser_knowledge_enableddisable_default_assistantcraft_default_enabled等;只读属性则包括application_statustieree_features_enabledseat_countused_seats等(部分每次读取时从后端环境变量覆盖)。

知识库:连接器、凭据与配对

# Web 连接器读取公开页面,因此其凭据不含任何秘密。 resource "onyx_credential" "web" { source = "web" name = "public-web" credential_json = jsonencode({}) } resource "onyx_connector" "docs" { name = "docs-site" source = "web" input_type = "load_state" # 每天重新索引一次。 refresh_freq = 24 * 60 * 60 connector_specific_config = jsonencode({ base_url = var.docs_base_url web_connector_type = "recursive" }) } # 配对才是真正执行索引的对象,同时承载其产出文档的访问控制。 resource "onyx_cc_pair" "docs" { name = "docs-site" connector_id = onyx_connector.docs.id credential_id = onyx_credential.web.id access_type = "public" } resource "onyx_document_set" "docs" { name = "docs" description = "Public product documentation" cc_pair_ids = [onyx_cc_pair.docs.id] }

注意access_typegroups放在onyx_cc_pair上——Onyx 在凭据被关联时应用访问控制,连接器端点本身虽然要求access_type字段却会忽略它。

Agent 与企业版用户组

resource "onyx_agent" "docs" { name = "Docs" description = "Answers product questions from the documentation" system_prompt = <<-EOT You answer questions from the product documentation. If the documentation does not cover the question, say so. EOT document_set_ids = [onyx_document_set.docs.id] starter_messages = [ { name = "Getting started" message = "How do I get started?" }, ] } # 用户组需要企业版。Community Edition 上请保持关闭:Onyx 会拒绝这些路由。 resource "onyx_user_group" "platform" { count = var.enable_enterprise_features ? 1 : 0 name = "Platform" # 权限使用 Onyx 自己的令牌,而非枚举名。 permissions = [ "manage:connectors", "manage:document_sets", ] }

应用与清理

cp terraform.tfvars.example terraform.tfvars # 编辑 terraform.tfvars terraform init terraform plan terraform apply

凭据也可以走环境变量,从而避免写入terraform.tfvars

export ONYX_SERVER_URL=http://localhost:8080 export ONYX_API_KEY="$(ONYX_ADMIN_EMAIL=admin@example.com \ ONYX_ADMIN_PASSWORD='...' ./mint_api_key.sh)" export TF_VAR_openai_api_key="sk-..."

terraform destroy会销毁配对并后台移除其索引的文档;onyx_settings是例外——销毁只停止托管设置,不会重置它们。索引在 apply 后后台执行,Agent 需等待首个索引周期完成才能基于站点作答,可在管理后台Connectors下观察进度。

密钥安全:write-only 参数与轮换

每个 Provider 接收的密钥都有两种形态(见 README.md):

  • 普通属性:值写入 Terraform state,任何能读到 state 文件的人都能读到密钥;
  • _wo孪生属性:Terraform 的 write-only 参数,值会从 plan 与 state 中剥离,只存在于你的配置文件中。
资源存入 stateWrite-only
onyx_llm_providerapi_keycustom_configapi_key_wocustom_config_wo
onyx_embedding_providerapi_keyapi_key_wo
onyx_credentialcredential_jsoncredential_json_wo
onyx_mcp_serverapi_tokenadmin_credentialsapi_token_woadmin_credentials_wo
onyx_custom_toolcustom_headerscustom_headers_wo

两者只能二选一设置,不能同时给出。onyx_credential因载荷必填,必须且只能提供其一。示例:

resource "onyx_llm_provider" "openai" { name = "openai" provider_type = "openai" api_key_wo = var.openai_api_key api_key_wo_version = 1 model_configurations = [{ name = "gpt-5-mini" }] }

Write-only 参数要求Terraform 1.11 或更高,旧版 CLI 会拒绝包含它的配置。

三个无法使用 write-only 的例外

  1. onyx_api_key.api_key:这是 Onyx 铸造的 Key 而非你提供的,Terraform 只能通过 state 交回生成值,须将 state 文件视同持有该 Key;
  2. onyx_mcp_server.auth_template_headers:该属性是 computed(Onyx 为共享令牌自行写入模板),Terraform 不允许一个参数既是 computed 又是 write-only,其占位符值来自admin_credentials_wo
  3. Provider 自身的api_key:Provider 配置本就不会写入 state,建议直接用ONYX_API_KEY环境变量提供,而非写进.tf文件。

轮换 write-only 密钥

Terraform 从不存储的值也无法做 diff,因此仅修改api_key_wo不会触发任何计划。每个孪生属性配有一个_wo_version计数器:把它加一,产生的 diff 会让下一次 apply 发送当前密钥。

注意不要用密钥派生计数器(如md5(var.token))——计数器会存进 state,不能反推出密钥。计数器只决定何时触发 apply;由于 Onyx 更新时替换所有字段,Provider 每次 apply 都会发送当前密钥。

两个需要知晓的行为

  • onyx_custom_tool停止刷新其请求头:Onyx 原样返回 action headers(而非掩码),所以custom_headers能正常刷新、面板外的改动会出现在terraform plan中;但对custom_headers_wo做不到这一点(刷新会把密钥写进 state),因此面板中改动的 header 在下次 apply 覆盖前不会被报告——这是 write-only 形式唯一的让步。
  • 导入多一次 apply:导入读取的是服务端现状,若 Onyx 未掩码返回密钥,它会进入存储属性;第一次 apply 使用孪生属性时将其从 state 清除,资源随即转入 write-only 路径。

已知限制:API 设计使然,需要绕行而非等待

这些限制源于 Onyx API 本身的行为,属于需要设计规避的特性而非等待修复的 bug。Fixed upstream表示后端已改进,但修复尚未进入已发布的 Onyx,因此 Provider 保留绕行方案,限制仍然适用。完整清单见 README.md 的Known limitations章节,以下为要点:

密钥

  • 秘密漂移不可检测:API 读取时对密钥做掩码,面板轮换对terraform plan不可见;配置值是权威,下次 apply 会重新断言。

设置与部署默认值

  • onyx_settingsonyx_llm_provider_default并非真正删除:Onyx 没有重置设置 API,也没有取消文本/视觉默认值的 API,销毁只会把它们从 state 移除;聊天命名默认值有 unset API,会被真正清空。

LLM 与 Embedding Provider

  • onyx_embedding_provider更新会替换全部字段,配置中必须保留api_key(或api_key_wo),否则更新会清空已存密钥;当前生效的 Embedding Provider 不可删除。
  • model_configurations是"权威记录":被省略的模型会在服务端移除,移除当前部署默认模型会失败——先改指onyx_llm_provider_default(引用顺序已正确处理)。
  • 模型列表读取的是 API 的显示视图:隐藏过时与重复模型,写操作无法保留未返回的行;管理面板行为一致。Fixed upstream:upsert 已支持keep_existing_models

凭据与连接器

  • onyx_credential载荷永不被读回:API 总是掩码载荷;admin_publiccurator_publicgroups无更新端点,会强制替换。
  • 私有凭据可能看起来像被删除:admin_public = false的凭据对创建者以外的管理员隐藏,与删除不可区分,Terraform 会删了重建。托管凭据请保持默认admin_public = true
  • onyx_connector不拥有访问控制:access_typegroups在配对(cc_pair)上设置;未设置prune_freq时首次更新会变成 7 天,Provider 随后将其作为权威值。

Agent 与动作

  • 删除 Agent 留下墓碑:行被标记删除,名称仍被占用,同名重建会复活原 Agent,销毁-重建返回原 id 而非新 id。
  • 已删除的 Agent 返回 400 而非 404,Provider 依据 Agent 列表确认存在性。Fixed upstream:路由现返回类型化的PERSONA_NOT_FOUND
  • onyx_agent并非拥有全部字段:附加的文件夹与文档省略即清空、显式 null 则被拒绝,Provider 读取后写回,存在一个往返窗口可能回滚期间的并发附加。Fixed upstream:两个字段已可空。另外search_start_date只写不读,头像不受管理。
  • display_priority在 upsert 上仅创建时生效,后续写忽略,变更需第二次调用显示优先级端点。
  • 两个内置动作对 API 隐藏:OktaProfileToolMemoryTool不在 Agent 快照中,持有它们的 Agent 报告的tool_ids少于写入值且永不收敛。
  • 删除自定义动作会将其从每个使用它的 Agent(包括 Terraform 未管理的)上摘除,且无任何报错或警告。

用户组(企业版)

  • onyx_user_group仅企业版存在路由,Community Edition 上所有调用返回 404。
  • 用户组不管理"组能看见什么":连接器、文档集、Agent、LLM Provider、MCP 服务器与凭据各自携带自己的groups;组暴露只读的cc_pair_idsdocument_set_idsagent_ids,两侧不会争夺同一条边。
  • 移除成员可能覆盖并发的连接器共享;组同步期间 Onyx 拒绝成员变更/重命名/删除,而新组从"同步中"开始,Provider 会在每次操作前等待;同步中的组在成员与删除路由上返回 404 而非冲突,因此 404 不代表组已消失。Fixed upstream:门禁现抛出RESOURCE_SYNCING冲突。
  • 权限使用 Onyx 的 wire 令牌(如manage:connectors)而非枚举名;只有可切换的权限可设置,basicadmincraft_sandboxmanage:skills及隐含读令牌由 Onyx 管理。
  • 种子默认组(AdminBasic)只持有成员:管理名册可行,重命名、删除、权限与隐身变更会被拒绝。
  • Onyx 拒绝会让某人脱离所有组的移除,销毁组同样受检——若某成员只有这一个组,销毁会失败;管理员权限存续、经理自移除、权限放大均有防护。

MCP 服务器

  • 只管理无需交互登录的服务器:NONEAPI_TOKEN可用;OAUTHPT_OAUTH需要浏览器往返,plan 阶段即被拒绝。
  • 服务器暴露哪些工具不受管理:Onyx 通过调用服务器来学习工具,拒绝命名未见过工具的选择。
  • 省略的description会被清空而非保留;groupsusers同理,从配置移除即清空服务端(含管理面板添加的条目)。
  • 从管理面板添加但从未配置的服务器导入为空字符串:auth_typetransport未设置,首次 plan 后移入 schema 默认值,一次 apply 收敛。
  • 服务器 URL 不能指向 Onyx 主机:SSRF 防护在所有保护级别都拒绝localhost与链路本地地址。

本地开发、测试与文档生成

开发需要 Go(见 go.mod)与 Terraform CLI:

go build ./... # 构建 go test ./... # 单元测试(无需 Onyx)

使用本地构建

~/.terraformrc中写dev_overrides指向本地二进制:

provider_installation { dev_overrides { "onyx-dot-app/onyx" = "/path/to/onyx/terraform-provider-onyx" } direct {} }

然后go build,在任意使用该 Provider 的配置中直接terraform plan/apply(跳过terraform init)。

验收测试

验收测试针对真实 Onyx 部署执行完整 CRUD 周期(会创建/销毁 Provider 与 Key,并短暂修改工作区设置,请使用开发部署):

TF_ACC=1 ONYX_TF_ACC_SERVER_URL=http://localhost:8080 go test ./internal/provider/ -v
  • ONYX_TF_ACC_API_PREFIX默认为""(直连后端),走 Web 服务器时设为/api
  • 认证:设置ONYX_TF_ACC_API_KEY使用现有管理 Key,或让测试装置以ONYX_TF_ACC_ADMIN_EMAIL/ONYX_TF_ACC_ADMIN_PASSWORD登录自助引导(默认admin_user@example.com/TestPassword123!;全新部署上第一个注册用户自动成为管理员)。

未设置TF_ACC时这些测试自动跳过,因此go test ./...在无 Onyx 环境下保持绿色——CI 的pr-golang-tests.yml即如此,不跑验收套件;pr-terraform-provider-tests.yml是会跑验收套件的通道,它用 docker compose 拉起 api_server 与 background,并让套件跑两遍(自引导 Key 与先用mint_api_key.sh铸造的 Key)。onyx_cc_paironyx_document_setonyx_user_group测试还需要 Celery 与 beat(用户组测试尤其依赖 beat 的check-for-vespa-sync每 20 秒清除同步状态,否则每次重命名/成员变更/销毁都会等到超时);配对测试特意使用mock_connector源,以覆盖全生命周期而无需真实数据源。

文档生成

docs/是生成产物——编辑 schema 的MarkdownDescriptionexamples/后执行:

go generate . # 运行 tfplugindocs;需要 terraform 在 PATH 上

小结

terraform-provider-onyx将 Onyx 应用层配置完整地带入 Terraform 的声明式工作流:通过endpoint/api_key/api_prefix三个参数完成认证接入,13 个资源与 4 个数据源覆盖 API Key、LLM Provider、默认模型、工作区设置、连接器与凭据、文档集、Agent、MCP 服务器乃至企业版用户组;write-only 孪生属性与_wo_version计数器为密钥安全与轮换提供了 state 之外的路径。理解其"API 设计使然"的已知限制(秘密漂移不可检测、部分资源不可真删、删除行为与 404 语义等),即可在真实部署中做出正确的建模与绕行设计。

【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询