
Onyx 的 Terraform 提供商资源用 onyx_llm_provider 声明式管理 LLM 提供商与模型清单【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer本篇技术指南围绕 Onyx 项目开源 AI 平台中的 Terraform Provideronyx_llm_provider资源展开讲解如何用 Infrastructure as Code 的方式在 Onyx 部署中声明式地创建 OpenAI、Anthropic、Azure、Bedrock、Vertex AI、Ollama 等 LLM 提供商并全量托管其启用的模型列表。读完本文你将掌握该资源的完整 Schema 语义、api_key与 write-only_wo双形态密钥机制、model_configurations的全量替换行为、Auto 模式、删除保护以及terraform import的实践要点。资源定位Onyx 应用配置层的 Terraform ProviderOnyx 仓库中的terraform-provider-onyx是一个独立的 Terraform Provider它通过 Onyx 的 admin API 管理的是运行在 Onyx 部署内部的应用配置——包括 LLM 提供商、部署默认模型、API Key、工作区设置与 Embedding 提供商——而不是托管 Onyx 运行所需的底层基础设施后者属于deployment/terraform/的职责详见 terraform-provider-onyx/README.md。onyx_llm_provider正是这套 Provider 中管理 LLM 提供商的核心资源对应后端管理接口/admin/llm/provider。它的核心设计原则可以概括为一句话model_configurations是完整清单list of record——凡是从配置中移除的模型都会在下次apply时被服务端同步删除而api_key与custom_config在 API 读取时会被掩码因此脱离 Terraform 的out-of-band改动无法被探测为 drift。前置准备Provider 认证与配置在创建任何onyx_llm_provider资源前需要先准备好 Provider 本身的认证信息。Provider 需要一个属于Admin组或具有不限权限的 PAT的 API Key可通过 Onyx 管理后台的 API Keys 页面创建或调用接口创建key 必须绑定 Admin 组否则没有管理员权限具体流程参见 terraform-provider-onyx/README.md。Provider 的典型配置如下出自 terraform-provider-onyx/README.mdprovider onyx { endpoint https://your-onyx.example.com # 或 ONYX_SERVER_URL api_key var.onyx_api_key # 或 ONYX_API_KEY # api_prefix 默认是 /apiweb 代理。直接指向后端时如 http://localhost:8080设为 。 # 也可以用 ONYX_API_PREFIX 环境变量覆盖。 }这里有一个值得注意的安全细节Provider 自身的api_key属于 Provider 配置Terraform 根本不会把它写入 state因此建议通过ONYX_API_KEY环境变量注入而不是写进.tf文件。快速上手声明一个 OpenAI 提供商关联文档给出的最小可运行示例完整展示了资源的典型用法。以下示例改编自 terraform-provider-onyx/docs/resources/llm_provider.md创建一个名为openai-prod的 OpenAI 提供商并启用三个模型resource onyx_llm_provider openai { name openai-prod provider_type openai # api_key 会保存在 Terraform state 中。若想彻底不落盘 # 可改用 write-only 成对参数需要 Terraform 1.11 及以上 # api_key_wo var.openai_api_key # api_key_wo_version 1 api_key var.openai_api_key # 完整的启用模型集合凡是在这里未列出的模型 # 都会在 apply 时从该提供商上移除。 model_configurations [ { name gpt-5 }, { name gpt-5-mini custom_display_name GPT-5 Mini (cheap tier) }, { name gpt-5-nano is_visible false }, ] }这段配置同时演示了三个核心机制api_key与api_key_wo二选一不能同时设置model_configurations是全量集合未列出的模型将被服务端删除单个模型可以覆盖custom_display_name管理员自定义显示名和is_visible是否在 UI 中可选。Schema 全解析每个参数的含义与默认值以下字段说明完整继承自资源 Schema 定义并与 llm_provider_resource.go 中的实际声明一一对应。必填字段Required字段类型说明model_configurationsAttributes Set该提供商上启用的模型完整集合。apply 会把服务端列表替换为与之一模一样的集合。provider_typeStringLiteLLM 的 provider key例如openai、anthropic、azure、bedrock、vertex_ai、ollama。必须为小写。provider_type在源码层面有额外的格式校验正则^[a-z0-9_-]$即只能是小写字母、数字、下划线和连字符llm_provider_resource.go。后端在接收时还会做一次归一化——去除首尾空白并转小写见 models.py 的normalize_provider校验器两端行为一致。可选字段Optional字段类型说明agentsSet of Number该提供商被限制可用的 Agentpersonaid 集合。api_baseString自定义 API Base URL例如 Azure 或自托管网关。api_keyString, Sensitive提供商 API Key。Onyx API 在读取时会掩码因此 Terraform 无法探测脱离 Terraform 的改动配置中的值被视为权威值。优先使用api_key_wo以免密钥进入 state二者不能同时设置。api_key_woString, Sensitive, Write-only只存在于配置中的提供商 API Key。Terraform 每次 apply 都会发送它但不会存储任何内容密钥永远不会进入 state。配合api_key_wo_version实现轮换。需要 Terraform 1.11 及以上。api_key_wo_versionNumberapi_key_wo的轮换计数器。Terraform 从不存储 write-only 值因此无法感知密钥本身是否变化调大该数字即可让下一次 apply 发送当前密钥。注意不要用密钥本身派生该数字——与密钥不同这个数字会保存在 state 中。api_versionStringAPI 版本Azure 专用。custom_configMap of String, Sensitive提供商特定配置键值对例如 Vertex 的 service-account JSON、Bedrock 的凭据。读取时与api_key一样会被掩码。优先使用custom_config_wo二者不能同时设置。custom_config_woMap of String, Sensitive, Write-only只存在于配置中的提供商特定配置键值对。Terraform 每次 apply 发送、从不落盘。配合custom_config_wo_version轮换。需要 Terraform 1.11 及以上。custom_config_wo_versionNumbercustom_config_wo的轮换计数器机制与api_key_wo_version相同。deployment_nameString部署名Azure 专用。force_deleteBoolean允许在提供商仍持有部署默认模型的情况下销毁它。默认为false此时销毁会失败。groupsSet of Number该提供商被限制可用的用户组 idEnterprise Edition。is_auto_modeBooleanOnyx Auto 模式模型列表由 Onyx 自己管理。启用后服务端接管model_configurationsTerraform 停止对该列表做 drift 检查update 时会重新断言服务端当前的模型而非配置中的模型因此注册表托管的模型永远不会被误删。is_publicBoolean该提供商是否对所有用户可用。默认值为true见 llm_provider_resource.go。nameString提供商配置的显示名。只读字段Read-Only字段类型说明idString数字形式的提供商 id由服务端分配。model_configurations 嵌套结构model_configurations是 Set 类型的嵌套属性每个元素对应一个启用的模型必填字段类型说明nameString提供商所认识的模型名例如gpt-5-mini。可选字段类型说明custom_display_nameString管理员指定的显示名覆盖。display_nameString来自源 API 的显示名动态提供商如 OpenRouter / Ollama。is_visibleBoolean该模型是否在 UI 中可选。默认truellm_provider_resource.go。max_input_tokensNumber覆盖模型的 max input tokens不设置则使用模型已知的默认值。supports_image_inputBoolean覆盖图像输入支持不设置则让 Onyx 自行推断。supports_reasoningBoolean覆盖推理模型分类不设置则让 Onyx 自行推断。后端对应的写入模型ModelConfigurationUpsertRequest见 models.py还支持reasoning_effort_max、reasoning_effort_default、temperature_default等更细粒度的推理/采样参数并会对temperature_default做 0–2 范围校验、对reasoning_effort_default是否落在reasoning_effort_max之内做一致性校验。当前 Terraform 资源只暴露了与 UI 管理强相关的字段子集这一点在阅读后端模型时可以留意。密钥的双形态设计api_key 与 write-only_wo成对参数这是本资源最值得深入理解的安全机制。在 Onyx 的后端读取路径中LLMProviderView的api_key和custom_config会被显式掩码后再返回——_mask_provider_credentials会把 api_key 以及custom_config中敏感键对应的值替换为掩码串见 api.py。这意味着密钥 drift 不可探测在管理后台手动轮换了密钥terraform plan看不到任何差异配置中的值始终是权威值并会在下一次 apply 时重新断言。刷新不能覆盖真实值Terraform 的Read必须把上一次 state 中的真实密钥原样带下去绝不能用掩码占位符污染 statellm_provider_resource.go 的注释明确说明了这一处理。普通形态的api_key会被 Terraform 写入 state 文件——任何能读取 state 文件的人都能看到密钥。因此 Provider 为每个密钥型字段提供了 write-only 孪生参数_wo后缀api_key↔api_key_wocustom_config↔custom_config_wowrite-only 参数是 Terraform 1.11 引入的能力Terraform 会把这类值从 plan 和 state 中一并剥离让它只存在于你的配置文件里。其底层实现见 write_only.goresolveWriteOnly在构造请求体之前会从 configuration而不是 plan/state中读取_wo孪生值若配置了_wo就用它否则回退到普通属性。这同时解决了 Onyx API全字段替换更新带来的一个隐患——由于更新会替换所有字段若密钥只存在于 state 而配置里没有一次不相关的 update 就可能把已存储的密钥清掉_wo值每次 apply 都在配置中因此始终能随请求一并发送。轮换 write-only 密钥_wo_version 计数器一个 Terraform 从不存储的值是它无法做 diff 的值。直接修改api_key_wo本身不会产生任何 plan 差异——Terraform 根本不知道它变了。因此每个_wo孪生都配了一个_wo_version计数器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 }] }轮换密钥时把api_key_wo_version从 1 改成 2这个 diff 会触发下一次 apply 发送当前配置中的密钥。实现细节见 write_only.go该计数器由writeOnlyVersionAttribute统一构造并带有AlsoRequires校验设置了_wo_version就必须同时设置对应的_wo参数。两个关键注意事项不要用密钥本身派生计数器例如md5(var.token)计数器保存在 state 中用密钥派生等于变相把密钥信息写进了 state。计数器只决定何时触发 apply。因为 Onyx 更新是全量替换只要发生 apply无论是什么改动触发的Provider 都会把当前密钥随请求一并发送这一行为在 Provider 级 README 中有明确说明见 terraform-provider-onyx/README.md。导入时的一个额外 applyterraform import读取的是服务端当前状态。若 Onyx 对某个密钥不掩码返回写入型密钥在创建时可能以明文返回它会落入普通属性。因此使用_wo形式的配置在导入后通常还需要额外执行一次 apply第一次 apply 会把密钥从 state 中清除让资源切换到 write-only 路径terraform-provider-onyx/README.md。model_configurations 的全量替换语义与 Auto 模式model_configurations是完整清单——这是本资源最重要的行为契约。观察资源实现可以发现无论是 Create 还是 Update都会调用同一个buildUpsertRequest把配置中的完整模型列表组装进请求体并经由客户端的UpsertLLMProvider以PUT/admin/llm/provider?is_creation...提交llm_provider_resource.go、llm_provider.go。请求体刻意不设置omitempty——PUT 是全量替换必须断言完整的期望状态。由此推导出的行为缩容即删除从配置中移除某个模型apply 后该模型在服务端被删除。这一点在验收测试中有直接覆盖TestAccLLMProviderResource的第 4 个步骤把模型列表从 2 个缩到 1 个并断言服务端模型名集合精确等于剩余的那个llm_provider_resource_test.go。删除默认模型会失败如果把当前作为部署默认deployment default的模型从列表中移除服务端校验会拒绝该操作。正确做法是先通过onyx_llm_provider_default资源把默认指向别的模型再缩容。关联资源 llm_provider_default.md 正是为此设计把默认模型独立成单例资源后Terraform 的depends_on引用provider_id onyx_llm_provider.openai.id能自动保证先重指默认再删除/缩容原提供商的正确销毁顺序。读取是展示视图服务端读取模型列表时隐藏了过时和重复日期的模型因此没有任何写操作能保留列表读取不到的行——管理后台 UI 也有同样的行为。后端已通过keep_existing_models字段修复了该问题见 models.py但 Provider 侧仍需按当前 API 行为工作。is_auto_mode把模型清单的所有权交还给 Onyx设置is_auto_mode true后模型列表改由 Onyx 自动管理例如从提供商拉取模型目录的场景。此时 Provider 的行为发生三处变化llm_provider_resource.goRead不再用远程数据 reconcilemodel_configurations而是保留 prior statellm_provider_resource.goUpdate在构造请求体前先读取服务端当前的模型列表并用服务端的列表覆盖配置中的列表再提交——因为 Auto 模式下没有服务端模型保护必须重新断言服务端当前模型才能保证注册表托管的模型不被误删llm_provider_resource.go由于该读操作与写操作并非原子文档与 README 均提示这是与 admin UI 一致的行为terraform-provider-onyx/README.md。Read 时的字段调和reconcile在非 Auto 模式下Read会调用reconcileModelConfigurations按模型名对齐远程列表刷新is_visible与custom_display_name这类持久化字段而对max_input_tokens、supports_image_input、supports_reasoning、display_name等服务端补全的解析值保留 prior state以避免产生幽灵 driftllm_provider_resource.go。这解释了为何导入时文档建议忽略model_configurations的校验——它们携带了服务端补全的值。删除保护force_delete 与部署默认模型force_delete控制销毁行为的边界。后端删除接口DELETE /admin/llm/provider/{provider_id}?force...的行为是当force为 false 时如果该提供商持有部署的 chat 默认模型服务端直接拒绝并抛出RESOURCE_IN_USE见 api.py。而删除持有其他流程如 vision默认的提供商则会被允许——那是刻意为之会顺带清空对应默认。因此在 Terraform 侧force_delete默认false此时销毁持有默认模型的提供商必然失败报错信息会明确提示要么先重指默认要么设置force_delete truellm_provider_resource.go。最佳实践仍是优先通过onyx_llm_provider_default资源重指默认让依赖顺序自然解决而不是滥用force_delete。导入现有提供商terraform import按数字 id 导入llm_provider_resource.go 通过ImportStatePassthroughID直接把 import id 透传为资源的id#!/bin/sh # 按数字形式的 provider id 导入。api_key/custom_config 被 API 掩码 # 导入后保持 null直到在配置中显式设置。 terraform import onyx_llm_provider.openai 3导入后需要注意三点这也是验收测试中ImportStateVerifyIgnore忽略api_key、model_configurations、force_delete的原因见 llm_provider_resource_test.goapi_key被掩码导入后为 null需要在配置中补上model_configurations携带服务端补全的字段值首次 plan 可能与配置有细微出入若配置使用_wo形式首次 apply 会完成从 state 中清除密钥的切换。源码与测试验证行为即契约本资源的行为由三层代码共同保证可循以下路径深入资源生命周期Create / Read / Update / Delete / Import 的完整实现见 llm_provider_resource.go包括state 以 plan 为准、仅叠加服务端分配的 id的 Create 策略以及 Update 中state 持有真实从未被掩码的密钥只要任意一侧有值就重发并置 changed 标志的处理llm_provider_resource.go。API 客户端请求/响应模型与端点封装见 llm_provider.go其中GetLLMProvider由于 API 没有按 id 查询的端点采用拉全量列表再按 id 扫描的方式实现llm_provider.go。write-only 机制resolveWriteOnly、writeOnlyVersionAttribute、私有 state 标记等通用实现见 write_only.go。验收测试TestAccLLMProviderResource跑真实 CRUD 周期覆盖创建、导入、改名加模型、缩容删模型四个步骤并专门断言配置的密钥必须原样保留在 state 中不被掩码读回污染llm_provider_resource_test.go。后端对应模型LLMProviderUpsertRequest、ModelConfigurationUpsertRequest、LLMProviderView的定义见 models.py掩码与删除保护的实现见 api.py。已知限制与设计要点小结根据 terraform-provider-onyx/README.md使用onyx_llm_provider时请牢记以下由 API 行为决定、需要主动设计绕开而非等待修复的限制限制应对方式密钥 drift 不可探测读取被掩码把配置中的值视为权威定期通过 apply 重新断言model_configurations是完整清单未列出的模型会被删除缩容前先重指部署默认删除持有默认模型的提供商失败先经onyx_llm_provider_default重指默认或设置force_delete true模型列表读取是展示视图隐藏过时/重复模型与 admin UI 行为一致keep_existing_models已由后端修复相关资源本资源文档terraform-provider-onyx/docs/resources/llm_provider.md部署默认模型资源terraform-provider-onyx/docs/resources/llm_provider_default.mdProvider 总览与认证、密钥管理、全部已知限制terraform-provider-onyx/README.md资源实现terraform-provider-onyx/internal/provider/llm_provider_resource.gowrite-only 通用机制terraform-provider-onyx/internal/provider/write_only.goAPI 客户端封装terraform-provider-onyx/internal/client/llm_provider.go验收测试terraform-provider-onyx/internal/provider/llm_provider_resource_test.go后端请求/响应模型backend/onyx/server/manage/llm/models.py后端管理 API掩码与删除保护backend/onyx/server/manage/llm/api.py【免费下载链接】danswerOpen Source AI Platform - AI Chat with advanced features that works with every LLM项目地址: https://gitcode.com/GitHub_Trending/da/danswer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考