AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Netbox Config Templates

skill-netboxlabs-skills-netbox-config-templates · by netboxlabs

>

No reviews yet
0 installs
20 views
0.0% view→install

Install

$ agentstack add skill-netboxlabs-skills-netbox-config-templates

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-netboxlabs-skills-netbox-config-templates)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Netbox Config Templates? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

NetBox Config Templates

> Your knowledge of NetBox config templates may be outdated. Template context variables, rendering API, and config context merge behavior evolve between releases. Prefer retrieval over pre-trained knowledge.

Retrieval Sources

| Source | URL / Method | Use for | |--------|-------------|---------| | Config templates docs | https://netboxlabs.com/docs/netbox/customization/config-templates/ | Template syntax, context variables | | Config contexts docs | https://netboxlabs.com/docs/netbox/customization/config-contexts/ | Hierarchical data, merge rules | | NetBox repo | https://github.com/netbox-community/netbox | Template rendering source code | | NetBox MCP server | If configured — fetch device config contexts to test template rendering | Verify context data |

NetBox provides a built-in Jinja2-based configuration rendering system. You define templates, populate data through config contexts, and render per-device or per-VM configurations via the API. This skill covers the entire workflow.

When to Use This Skill

  • Generating device/VM configurations from NetBox data
  • Setting up config contexts (hierarchical data) for template rendering
  • Integrating NetBox config rendering into CI/CD or provisioning pipelines
  • Troubleshooting template rendering issues or config context merge behavior

Quick Reference

Template Resolution Order (Device)

device.config_template → device.role.config_template → device.platform.config_template

First match wins. Only one template renders per device. VMs follow the same pattern (role → platform).

Key API Endpoints

| Action | Method | Endpoint | |--------|--------|----------| | Render device config | POST | /api/dcim/devices/{id}/render-config/ | | Render VM config | POST | /api/virtualization/virtual-machines/{id}/render-config/ | | Render template directly | POST | /api/extras/config-templates/{id}/render/ | | CRUD config templates | GET/POST/PUT/PATCH/DELETE | /api/extras/config-templates/ | | CRUD config contexts | GET/POST/PUT/PATCH/DELETE | /api/extras/config-contexts/ |

Context Variables Cheat Sheet

In device/VM rendering (render-config):

| Variable | Type | Description | |----------|------|-------------| | device / virtualmachine | ORM instance | Full model with all relations | | (config context keys) | varies | Merged config context data as top-level keys | | (POST body keys) | varies | Extra data sent with the render request |

In general-purpose rendering (config-templates/{id}/render/):

| Variable | Type | Description | |----------|------|-------------| | dcim, ipam, virtualization, etc. | module-like | Access to all public NetBox model classes | | (POST body keys) | varies | Extra data sent with the render request |

See [references/context-variables.md](references/context-variables.md) for the complete breakdown.

Config Context System

Config contexts provide structured JSON data to templates. They are assigned based on object attributes and merged by weight.

Assignment Logic

A config context applies when the object matches all non-empty assignment categories (AND across categories) and any value within each category (OR within a category).

Assignment categories: Regions, Site groups, Sites, Locations, Device types, Roles, Platforms, Cluster types, Cluster groups, Clusters, Tenant groups, Tenants, Tags.

Merge Order

  1. All matching active config contexts, ordered by weight ascending, then name
  2. Higher-weight contexts overwrite lower-weight on key collision
  3. Local context data (on the device/VM itself) merges last and always wins

⚠️ Lists Are Replaced, Not Merged

deepmerge() merges dicts recursively but replaces non-dict values entirely:

// 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

Design data structures with this in mind. Use dicts with unique keys when you need additive merging.

Hierarchy Resolution

For hierarchical models (Region, Site Group, etc.), a context assigned to a parent also applies to all descendants. A context assigned to "Americas" region matches devices in "US-East" sub-region.

For a deep dive on merging, see [references/config-context-merging.md](references/config-context-merging.md). For config context data modeling best practices, see [netbox-data-modeling](../netbox-data-modeling/SKILL.md).

Writing Templates

Accessing Device Data

The device (or virtualmachine) variable is a full Django ORM instance:

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 %}

Using Config Context Data

Config context keys appear as top-level template variables:

{% 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 %}

Template Inheritance (DataSource Required)

{% extends %} and {% include %} only work when templates are stored in a DataSource (git repo, S3, etc.). Templates defined with inline template_code cannot resolve other templates.

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

{% block interfaces %}
{% for iface in device.interfaces.all() %}
interface {{ iface.name }}
{% endfor %}
{% endblock %}

ORM Queries in Templates

Both device and general-purpose rendering expose NetBox models:

{# 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 %}

Warning: ORM queries run unsandboxed against the database. A careless .all() on a large table will be slow. There is no query limiting.

Jinja2 Environment

  • Templates run in a SandboxedEnvironment — no file I/O, no arbitrary imports
  • Custom filters can be added via JINJA2_FILTERS in NetBox configuration
  • Built-in env() filter (NetBox 4.6.2+) — returns a system environment variable's value: {{ 'WEBHOOK_TOKEN_3' | env }}. Gated by the JINJA_ENVIRONMENT_PARAMS config list (an fnmatch wildcard allowlist of permitted variable names); returns None for any name not matched. On 4.6.1 and earlier there are no built-in custom filters — only standard Jinja2 filters.
  • Per-template environment_params can customize behavior (e.g., undefined: jinja2.StrictUndefined), but on NetBox 4.6.1+ the keys are allowlisted — see below.

> NetBox 4.6.1+ — environment_params allowlist (CVE-2026-29514). A patched RCE via environment_params (shared by ConfigTemplate and ExportTemplate) restricts which keys are accepted (JINJA_ENV_PARAMS_ALLOWED). Allowed: the standard delimiter/whitespace/scalar params (trim_blocks, lstrip_blocks, autoescape, keep_trailing_newline, block/comment/variable *_string delimiters, etc.) and undefined — but undefined must be one of jinja2.StrictUndefined, jinja2.Undefined, jinja2.ChainableUndefined, jinja2.DebugUndefined. extensions, finalize, loader, and bytecode_cache are blocked and a template setting them is rejected. The skill's examples (StrictUndefined, trim_blocks, lstrip_blocks) remain valid; do not recommend the blocked keys.

Common Vendor Patterns

Strategy 1: Platform-Based Template Assignment (Recommended)

Assign different config templates to different Platforms:

| Platform | Config Template | |----------|----------------| | junos | junos-base.j2 | | ios-xe | ios-xe-base.j2 | | eos | eos-base.j2 |

Template resolves via: device → role → platform. This is the cleanest approach.

Strategy 2: Conditional Logic in a Single Template

{% 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 %}

Works for small differences but becomes unwieldy. Prefer Strategy 1 for production.

API Rendering Patterns

Render a Device Config

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"]

Use Accept: text/plain header to get raw config output without JSON wrapping.

Override Config Context at Render Time

# 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
)

Render a Template Directly (No Device)

# 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]},
)

For detailed API examples including pynetbox and error handling, see [references/api-rendering-patterns.md](references/api-rendering-patterns.md).

Pitfalls

Performance

  • Exclude config_context from list endpoints: GET /api/dcim/devices/?exclude=config_context — computing merged config context per device is expensive. Always exclude on bulk queries.
  • ORM queries in templates have no guardrails — avoid unbounded .all() on large tables.

Template Behavior

  • Template resolution is first-match only — device → role → platform. A device still has one assigned template. NetBox 4.6+ lets you render any other template against a device's context without changing assignments by passing config_template_id in the render-config request body (or ?config_template_id= on the UI render URL) — useful for CI/dry-run rendering of alternative templates. (Requires view permission on Config Template plus render_config on the device.)
  • No template versioning — templates are mutable. Only NetBox's change log provides history.
  • Render debugging (NetBox 4.6+) — when developing templates in a script/plugin, call render_jinja2(..., debug=True) to enable Jinja2's debug extension ({% debug %}) for inspecting the available context.
  • extends/include requires DataSource — inline template_code cannot reference other templates.

Config Context Surprises

  • Lists replace, don't append — the most common surprise. See merge rules above.
  • POST data silently overrides config context — intentional but can be confusing when debugging unexpected values.
  • environment_params vary per template — undefined variable handling may differ between templates if configured differently.

References

  • [references/context-variables.md](references/context-variables.md) — Complete context variable reference for all rendering modes
  • [references/config-context-merging.md](references/config-context-merging.md) — Deep dive on hierarchy, weight, and merge behavior
  • [references/api-rendering-patterns.md](references/api-rendering-patterns.md) — Detailed API examples with pynetbox and requests

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.