Skip to content

Experimental features

Caution

These features are considered highly experimental and might break things in unexpected ways.

These experimental features are to be considered as a technology preview. Please be aware of the following when enabling these features:

  • The feature implementation is possibly subject to change between releases as we are still settling on the final design.
  • The feature might be removed in a future release without notice.
  • The feature might have unexpected consequences if enabled as it has not been fully tested.
  • Do NOT run these features in production (unless you like to live dangerously).

When an experimental feature is enabled, the script logs a warning at the start of every run.

As always, feel free to submit an issue when running into problems while testing these features.

Config Context Rendering

Note

Added in v4.1. This feature is under active development.

With render_config_context = True, the zabbix key of the NetBox config context is rendered as a Jinja2 template before it is used. This lets you build config context values from the data of the device or VM, and transform them with filters.

render_config_context = True

Only the zabbix key is rendered, and all settings that read config context use the rendered result, such as templates, interfaces, usermacros, tags and the description. If rendering fails, or the result is not valid JSON, the host is skipped and the error is logged.

Consider the following demo NetBox device. Run the script with -vv to see this data for your own devices:

{
    "id": 3,
    "url": "http://127.0.0.1:8000/api/dcim/devices/3/",
    "display_url": "http://127.0.0.1:8000/dcim/devices/3/",
    "display": "ACME-UT210-HV01",
    "name": "ACME-UT210-HV01",
    "device_type": {
        "id": 2,
        "url": "http://127.0.0.1:8000/api/dcim/device-types/2/",
        "display": "F13",
        "manufacturer": {
            "id": 3,
            "url": "http://127.0.0.1:8000/api/dcim/manufacturers/3/",
            "display": "MegaMacro",
            "name": "MegaMacro",
            "slug": "megamacro",
            "description": ""
        },
        "model": "F13",
        "slug": "f13",
        "description": ""
    },
    "role": {
        "id": 2,
        "url": "http://127.0.0.1:8000/api/dcim/device-roles/2/",
        "display": "Hypervisor",
        "name": "Hypervisor",
        "slug": "hypervisor",
        "description": "",
        "device_count": 0,
        "virtualmachine_count": 0,
        "_depth": 0
    },
    "tenant": null,
    "platform": {
        "id": 2,
        "url": "http://127.0.0.1:8000/api/dcim/platforms/2/",
        "display": "HVstuff",
        "name": "HVstuff",
        "slug": "hvstuff",
        "description": "",
        "device_count": 0,
        "virtualmachine_count": 0,
        "_depth": 0
    },
    "serial": "",
    "asset_tag": null,
    "site": {
        "id": 1,
        "url": "http://127.0.0.1:8000/api/dcim/sites/1/",
        "display": "ACME HQ",
        "name": "ACME HQ",
        "slug": "acme-hq",
        "description": ""
    },
    "location": null,
    "rack": null,
    "position": 10.0,
    "face": {
        "value": "front",
        "label": "Front"
    },
    "latitude": null,
    "longitude": null,
    "parent_device": null,
    "status": {
        "value": "active",
        "label": "Active"
    },
    "airflow": null,
    "primary_ip": {
        "id": 3,
        "url": "http://127.0.0.1:8000/api/ipam/ip-addresses/3/",
        "display": "192.168.42.100/24",
        "family": {
            "value": 4,
            "label": "IPv4"
        },
        "address": "192.168.42.100/24",
        "description": ""
    },
    "primary_ip4": {
        "id": 3,
        "url": "http://127.0.0.1:8000/api/ipam/ip-addresses/3/",
        "display": "192.168.42.100/24",
        "family": {
            "value": 4,
            "label": "IPv4"
        },
        "address": "192.168.42.100/24",
        "description": ""
    },
    "primary_ip6": null,
    "oob_ip": null,
    "cluster": null,
    "virtual_chassis": null,
    "vc_position": null,
    "vc_priority": null,
    "description": "",
    "comments": "",
    "config_template": null,
    "config_context": {
        "zabbix": {
            "snmp": {
                "bulk": 1,
                "version": 2,
                "community": "{$SNMP_COMMUNITY}"
            },
            "templates": [
                "ICMP Ping"
            ],
            "interface_port": 161,
            "interface_type": 2
        }
    },
    "local_context_data": null,
    "tags": [],
    "custom_fields": {
        "zabbix_hostid": 10797,
        "zabbix_proxy": null,
        "zabbix_proxy_group": null
    },
    "created": "2025-09-08T12:23:47.348414Z",
    "last_updated": "2026-04-08T13:34:33.788247Z",
    "console_port_count": 0,
    "console_server_port_count": 0,
    "power_port_count": 0,
    "power_outlet_count": 0,
    "interface_count": 5,
    "front_port_count": 0,
    "rear_port_count": 0,
    "device_bay_count": 0,
    "module_bay_count": 0,
    "inventory_item_count": 0
}

This data, without the config_context key, is passed to the template as a dictionary called data. The extended data options, such as extended_site_properties, add more data to it.

Now, let's assume we need to put last_updated in the usermacro {$NB.LAST.UPDATE}, as a Unix timestamp so triggers can compare it with other time based items.

We can do this by adding the following config context, with render_config_context enabled:

{
    "zabbix": {
        "usermacros": {
            "{$NB.LAST.UPDATE}": {
                "type": "text",
                "value": "{{ data['last_updated'] | strftime('%s') }}"
            }
        }
    }
}
The verbose sync log (-v) shows how the macro was calculated and synced to the Zabbix host:

2026-04-08 15:55:51,380 - NetBox-Zabbix-sync - INFO - Host ACME-UT210-HV01: updated with data {'macros': [{'macro': '{$NB.LAST.UPDATE}', 'value': '1775649343', 'type': '0', 'description': ''}]}.

This is just a simple example. See Advanced interface configuration for another one.

Filters

In addition to the built-in filters, the j2ipaddr filters are available to transform IP address information.

We've also added some custom filters, and more will follow in the future:

Custom Filter Description Parameters
dict_keys() Filters specific keys from a list of dictionaries. keys := List of keys
json_path() Filters data using JSONPath path := JSONPath string
regex_search() Searches for regex matches, think of grep. find := Regexp
regex_replace() Search and replace based on regex. find := Regexp, replace := String
strftime() Formats a date and time string with a format. The time zone is dropped before formatting, so %s uses the local time zone of the machine running the sync. fmt := Date format string. Default: %Y-%m-%d %H:%M:%S