mcpField
N
netbox-config-templates

netbox-config-templates

github.com/netboxlabs云与 DevOps2148 次安装2 周前更新
代码仓库

关于 netbox-config-templates

为 NetBox 配置模板和上下文数据提供参考,面向生成设备或虚拟机配置的运维人员与集成开发者。内容涵盖 Jinja2 渲染、上下文合并规则及 API 用法。

主要功能

  1. 01Jinja2 模板渲染
  2. 02配置上下文分配与合并
  3. 03设备和虚拟机模板解析
  4. 04通过 API 渲染配置
  5. 05模板性能与安全注意事项

适用场景

  1. 01根据 NetBox 数据生成设备配置
  2. 02为设备层级组织配置上下文
  3. 03在 CI/CD 或配置流程中调用渲染 API
  4. 04排查上下文合并或模板渲染问题

MCP 相关

可在配置了 NetBox MCP 服务时获取设备配置上下文,以验证模板渲染结果。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/netboxlabs/skills --skill netbox-config-templates

安装后在 Claude Code 中输入/netbox-config-templates确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-rendering-patterns.md
config-context-merging.md
context-variables.md

详细介绍

NetBox 配置模板

你对 NetBox 配置模板的了解可能已经过时。 模板上下文变量、渲染 API 和配置上下文合并行为会随版本更新而变化。请优先检索,而非依赖预训练知识。

检索来源

来源URL / 方法用途
配置模板文档https://netboxlabs.com/docs/netbox/features/configuration-rendering/模板语法、上下文变量
配置上下文文档https://netboxlabs.com/docs/netbox/features/context-data/分层数据、合并规则
NetBox 仓库https://github.com/netbox-community/netbox模板渲染源代码
NetBox MCP 服务如果已配置——获取设备配置上下文以测试模板渲染验证上下文数据

NetBox 提供基于 Jinja2 的内置配置渲染系统。你可以定义模板,通过配置上下文填充数据,并通过 API 按设备或 VM 渲染配置。本技能涵盖完整工作流。

何时使用此技能

  • 根据 NetBox 数据生成设备/VM 配置
  • 设置用于模板渲染的配置上下文(分层数据)
  • 将 NetBox 配置渲染集成到 CI/CD 或置备流水线中
  • 排查模板渲染问题或配置上下文合并行为

快速参考

模板解析顺序(设备)
device.config_template → device.role.config_template → device.platform.config_template

匹配到的第一个模板优先。每台设备只会渲染一个模板。VM 遵循相同模式(角色 → 平台)。

主要 API 端点
操作方法端点
渲染设备配置POST/api/dcim/devices/{id}/render-config/
渲染 VM 配置POST/api/virtualization/virtual-machines/{id}/render-config/
直接渲染模板POST/api/extras/config-templates/{id}/render/
配置模板的 CRUD 操作GET/POST/PUT/PATCH/DELETE/api/extras/config-templates/
配置上下文的 CRUD 操作GET/POST/PUT/PATCH/DELETE/api/extras/config-contexts/
上下文变量速查表

在设备/VM 渲染中(render-config):

变量类型说明
device / virtualmachineORM 实例包含所有关联的完整模型
(配置上下文键)视情况而定合并后的配置上下文数据,作为顶层键
(POST 请求体中的键)视情况而定随渲染请求发送的额外数据

在通用渲染中(config-templates/{id}/render/):

变量类型说明
dcim、ipam、virtualization 等类模块对象可访问所有公开的 NetBox 模型类
(POST 请求体中的键)视情况而定随渲染请求发送的额外数据

完整说明请参阅 references/context-variables.md。

配置上下文系统

配置上下文会向模板提供结构化 JSON 数据。系统根据对象属性分配上下文,并按权重合并。

分配逻辑

当对象符合所有非空分配类别(类别之间为 AND 关系),并且符合每个类别中的任意值(类别内为 OR 关系)时,配置上下文才会应用。

分配类别:区域、站点组、站点、位置、设备类型、角色、平台、集群类型、集群组、集群、租户组、租户、标签。

合并顺序
  1. 所有匹配的启用配置上下文,按权重升序排列,其次按名称排列
  2. 权重较高的上下文会在键冲突时覆盖权重较低的上下文
  3. 本地上下文数据(设备/VM 自身的数据)最后合并,且始终优先
⚠️ 列表会被替换,而不是合并

deepmerge() 会递归合并字典,但会完全替换非字典值:

// Weight 100: {"ntp_servers": ["10.0.0.1", "10.0.0.2"]}
// Weight 200: {"ntp_servers": ["10.1.1.1"]}
// Result:     {"ntp_servers": ["10.1.1.1"]}  ← NOT concatenated

设计数据结构时请考虑这一点。需要增量合并时,请使用包含唯一键的字典。

层级解析

对于分层模型(区域、站点组等),分配给父级的上下文也适用于所有子级。分配给“Americas”区域的上下文会匹配“US-East”子区域中的设备。

预渲染缓存(NetBox 4.7+)

在 4.7 中,合并结果会预渲染并缓存在每台设备/VM 上。任何上游变更(创建、编辑或删除配置上下文,或影响适用上下文的设备/VM 属性变更)都会使缓存失效,并触发一个非阻塞后台任务重新渲染;在此期间,读取操作会回退到按需渲染,因此结果不会过时。合并语义保持不变。升级后,升级脚本会运行 manage.py rebuild_config_context_cache(对每台设备/VM 执行一次 UPDATE;可安全中断并重新运行)。绕过信号的批量写入(queryset.update())不会使缓存失效——之后请运行 rebuild_config_context_cache --force。在 4.5/4.6 中,每次读取都会计算配置上下文。

有关合并的深入说明,请参阅 references/config-context-merging.md。有关配置上下文数据建模的最佳实践,请参阅 netbox-data-modeling。

编写模板

访问设备数据

device(或 virtualmachine)变量是完整的 Django ORM 实例:

hostname {{ device.name }}
!
{% if device.primary_ip4 %}
ip address {{ device.primary_ip4.address | ipaddr('address') }}
{% endif %}
!
{% for iface in device.interfaces.all() %}
interface {{ iface.name }}
  description {{ iface.description | default('', true) }}
  {% for ip in iface.ip_addresses.all() %}
  ip address {{ ip.address }}
  {% endfor %}
{% endfor %}
使用配置上下文数据

配置上下文键会显示为顶层模板变量:

{% for server in ntp_servers | default([]) %}
ntp server {{ server }}
{% endfor %}
!
{% for server in syslog_servers | default([]) %}
logging host {{ server }}
{% endfor %}
!
{% if snmp_community is defined %}
snmp-server community {{ snmp_community }} RO
{% endif %}
模板继承(需要 DataSource)

{% extends %} 和 {% include %} 仅在模板存储于 DataSource(Git 仓库、S3 等)时才有效。使用内联 template_code 定义的模板无法解析其他模板。

{# Stored in a DataSource alongside base.j2 #}
{% extends 'base.j2' %}

{% block interfaces %}
{% for iface in device.interfaces.all() %}
interface {{ iface.name }}
{% endfor %}
{% endblock %}
模板中的 ORM 查询

设备渲染和通用渲染都可以访问 NetBox 模型:

{# Query prefixes from IPAM #}
{% set mgmt_prefixes = ipam.Prefix.objects.filter(role__slug='management') %}
{% for pfx in mgmt_prefixes %}
ip route {{ pfx.prefix }} Management
{% endfor %}

**警告:**ORM 查询会在未沙箱隔离的情况下对数据库运行。在大型表上不加考虑地调用 .all() 会很慢。没有查询数量限制。

Jinja2 环境
  • 模板在 SandboxedEnvironment 中运行——不允许文件 I/O,也不允许任意导入
  • 可通过 NetBox 配置中的 JINJA_FILTERS 添加自定义过滤器(4.7+;旧名称 JINJA2_FILTERS 仍可使用,但已弃用,并将在 5.0 中移除)/ JINJA2_FILTERS(4.5/4.6)。4.7 中过滤器的优先级从低到高依次为:内置(env)→ 插件注册 → 实例 JINJA_FILTERS。
  • 插件可以注册 Jinja 过滤器并注入模板上下文变量(NetBox 4.7+),方法是使用 jinja_env.py / register_jinja_filters() 和 PluginConfig.get_jinja_context()——操作方法请参阅 netbox-plugin-development。插件上下文是全局的(而非针对单个对象),且不得使用 dcim 等应用标签名称。
  • 模板中的自定义对象(NetBox 4.7+,netbox-custom-objects v0.6.1+):custom_objects.<type_name>.filter(device=device) 或 '<type_name>' | custom_objects 可按内部名称公开自定义对象类型;在 4.5/4.6 中,custom_objects 不存在。请参阅 netbox-custom-objects。
  • 内置 env() 过滤器(NetBox 4.6.2+)——返回系统环境变量的值:{{ 'WEBHOOK_TOKEN_3' | env }}。该过滤器受 JINJA_ENVIRONMENT_PARAMS 配置列表限制(这是一个 fnmatch 通配符允许列表,用于指定允许的变量名称);名称不匹配时返回 None。在 4.6.1 及更早版本中,没有内置自定义过滤器——仅有标准 Jinja2 过滤器。
  • 每个模板的 environment_params 都可以自定义行为(例如 undefined: jinja2.StrictUndefined),但在 NetBox 4.6.1+ 中,键必须在允许列表中——见下文。

NetBox 4.6.1+——environment_params 允许列表(CVE-2026-29514)。 针对 environment_params 的已修补 RCE(ConfigTemplate 和 ExportTemplate 共用此参数)限制了可接受的键(JINJA_ENV_PARAMS_ALLOWED)。允许的键包括标准的分隔符、空白和标量参数(trim_blocks、lstrip_blocks、autoescape、keep_trailing_newline、块/注释/变量的 *_string 分隔符等)以及 undefined——但 undefined 必须是 jinja2.StrictUndefined、jinja2.Undefined、jinja2.ChainableUndefined 或 jinja2.DebugUndefined 之一。extensions、finalize、loader 和 bytecode_cache 均被禁用,设置这些参数的模板会被拒绝。本文档中的示例(StrictUndefined、trim_blocks、lstrip_blocks)仍然有效;不要推荐使用被禁用的键。

常见厂商模式

策略 1:基于平台分配模板(推荐)

为不同的平台分配不同的配置模板:

平台配置模板
junosjunos-base.j2
ios-xeios-xe-base.j2
eoseos-base.j2

模板按以下顺序解析:设备 → 角色 → 平台。这是最简洁的方案。

策略 2:在单个模板中使用条件逻辑
{% if device.platform.slug == 'junos' %}
system {
    host-name {{ device.name }};
}
{% elif device.platform.slug == 'ios-xe' %}
hostname {{ device.name }}
{% elif device.platform.slug == 'eos' %}
hostname {{ device.name }}
{% endif %}

适用于小幅差异,但复杂后会变得难以维护。生产环境中优先采用策略 1。

API 渲染模式

渲染设备配置
import requests

NETBOX = "https://netbox.example.com"
TOKEN = "nbt_abc123.xxxxxxxxxxxxxxxx"
headers = {"Authorization": f"Bearer {TOKEN}"}

# Render config for device ID 42
response = requests.post(
    f"{NETBOX}/api/dcim/devices/42/render-config/",
    headers=headers,
    json={},  # optional extra context data
)
response.raise_for_status()
config = response.json()["content"]

使用 Accept: text/plain 标头可获取未经 JSON 封装的原始配置输出。

在渲染时覆盖配置上下文
# POST body merges after config context (overrides on collision)
response = requests.post(
    f"{NETBOX}/api/dcim/devices/42/render-config/",
    headers=headers,
    json={"ntp_servers": ["10.99.99.1"]},  # overrides config context
)
直接渲染模板(不使用设备)
# General-purpose rendering — no device/VM in context
response = requests.post(
    f"{NETBOX}/api/extras/config-templates/5/render/",
    headers=headers,
    json={"hostname": "switch01", "vlans": [10, 20, 30]},
)

有关包括 pynetbox 和错误处理在内的详细 API 示例,请参阅 references/api-rendering-patterns.md。

注意事项

性能
  • 列表端点上的配置上下文:
    • NetBox 4.7+:合并后的配置上下文会在每台设备/虚拟机上预先渲染并缓存;在所有 4.7.x 版本中,?exclude=config_context 都会被静默忽略(如果共享客户端仍发送此参数,也无妨)。在 4.7.0–4.7.2 中,配置上下文始终会加载,列表调用开销很小——成本转移到了后台重新渲染作业。在 4.7.3+ 中,?omit=config_context(或 ?fields=/?brief=True)会再次跳过数据库注释和缓存列——不需要上下文时请发送此参数。
    • NetBox 4.5/4.6:为每台设备计算合并后的配置上下文开销很大——批量查询时,如果不需要该上下文,请务必发送 GET /api/dcim/devices/?omit=config_context(4.5.2+;在此版本中,?exclude= 效果相同)。
  • 模板中的 ORM 查询没有防护措施——避免对大型数据表执行无界的 .all()。
模板行为
  • 模板解析只采用第一个匹配项——设备 → 角色 → 平台。设备仍然只有一个已分配的模板。NetBox 4.6+ 允许你在不更改分配的情况下,使用设备的上下文渲染其他任意模板:在渲染配置请求正文中传入 config_template_id(或在 UI 渲染 URL 中使用 ?config_template_id=<id>)——适用于 CI/试运行环境中的替代模板渲染。(需要对 Config Template 具有 view 权限,并对设备具有 render_config 权限。)
  • 模板没有版本控制——模板可以修改。只有 NetBox 的变更日志会保留历史记录。
  • 渲染调试(NetBox 4.6+)——在脚本/插件中开发模板时,调用 render_jinja2(..., debug=True),即可启用 Jinja2 的 debug 扩展({% debug %}),用于检查可用的上下文。
  • extends/include 需要 DataSource——内联的 template_code 无法引用其他模板。
配置上下文相关注意事项
  • 列表会替换,而不是追加——这是最常见的意外情况。请参阅上文的合并规则。
  • POST 数据会静默覆盖配置上下文——这是有意设计的,但在调试意外值时可能令人困惑。
  • environment_params 因模板而异——如果配置不同,不同模板对未定义变量的处理可能也不同。

版本说明

NetBox 4.7(2026-09-02)
  • 每台设备/虚拟机的配置上下文会预先渲染并缓存;上游更改会使缓存失效,并由后台作业重新渲染(两者之间会按需回退)。所有 4.7.x 版本都会静默忽略 ?exclude=config_context;在 4.7.0–4.7.2 中,config_context 始终会加载;在 4.7.3+ 中,如果 ?omit=config_context/?fields=/?brief=True 未包含该字段,则会再次跳过数据库注释。DeviceWithConfigContextSerializer/VirtualMachineWithConfigContextSerializer 已合并到基础序列化器中。升级时会运行 rebuild_config_context_cache。
  • JINJA2_FILTERS 更名为 JINJA_FILTERS(旧名称在 5.0 前仍可使用,但会显示弃用警告)。
  • 插件可以注册 Jinja 过滤器并注入上下文变量(jinja_env.py、register_jinja_filters()、get_jinja_context());优先级为:内置 → 插件 → 实例 JINJA_FILTERS。netbox-custom-objects v0.6.1+ 使用此功能来提供 custom_objects.<type> / '<type>' | custom_objects。
  • 模板可访问的新数据:device.cooling_method、接口的 channels/channel_id(类型为 channel 的通道化子接口)、服务的 port_mappings(由 "tcp/80" 字符串组成的列表;protocol/ports 已弃用)、device_type.end_of_life。在模板中,选择类型的自定义字段仍通过 device.cf / custom_field_data 读取原始值——只有 REST/GraphQL 表示形式变成了 {value, label}。
  • 平台:PostgreSQL 15+、Redis 6.0+、ltree 扩展;建议使用 4.7.3+(4.7.0/4.7.1 会将令牌明文泄露到作业结果中;4.7.3 新增了支持分支安全的后台写入和配置上下文省略优化)。
NetBox 4.6 (2026-05-05)
  • render-config 上的 config_template_id 覆盖项(4.6.0);render_jinja2(..., debug=True)(4.6.0);environment_params 允许列表(4.6.1,CVE-2026-29514);内置 env 过滤器受 JINJA_ENVIRONMENT_PARAMS 控制(4.6.2);通过 SandboxedEnvironment 渲染配置模板时,明确禁用自动转义(4.6.5)。

参考资料

评论

支持 Markdown