Instructions for Codex and other coding agents working in this directory.
This project should provide an easy-to-install Docker Compose stack for basic Palo Alto and Fortinet firewall monitoring, with useful capacity/load visibility.
The core use case is helping users understand what a firewall is actually doing with minimal setup. Prioritize CPU, RAM, sessions, CPS, disk where useful, interface status, and interface throughput over deep feature-specific monitoring.
Throughput must be calculated from interface octet counters (ifHCInOctets / ifHCOutOctets) for both Palo Alto and Fortinet. Dataplane, NPU, or feature counters can be incomplete when traffic is offloaded or bypasses the counter path.
For CPU views, dashboards should show both the global CPU and every per-processor/dataplane CPU exposed by the vendor MIB (pan_hr_processors for Palo Alto and fortinet_processors for Fortinet). The global line is useful for quick reading; per-CPU lines reveal imbalance and saturated dataplanes.
The expected user journey is:
- Edit
firewalls.ymlwith one or more firewall definitions. - Run
generate.pyon a Linux host with Docker, usually through the optionalgenerate.shbootstrap wrapper. - Start or refresh the stack with Docker Compose.
- Open Grafana and use the provisioned dashboards for firewall monitoring.
Keep changes aligned with that goal: simple install, clear configuration, reliable SNMP polling, and dashboards that work out of the box.
docker-compose.yaml: InfluxDB, custom Telegraf image, and Grafana services.firewalls.yml: user-facing inventory for Palo Alto and Fortinet devices..firewalls.generated.yml: generated inventory enriched fromfirewalls.yml; ignored by Git and safe to recreate.generate.py: main Python generator. It checks Docker, prepares MIBs, enriches inventory, renderstelegraf/telegraf.conf, builds Telegraf, and starts the stack.generate.sh: optional convenience wrapper that creates a local.venv, installsrequirements.txt, and executesgenerate.py.telegraf/header.tmpl: common Telegraf agent and InfluxDB output config.telegraf/inputs_paloalto.tmpl: SNMP input template for Palo Alto devices.telegraf/inputs_fortinet.tmpl: SNMP input template for Fortinet devices.telegraf/Dockerfile: custom Telegraf image with Net-SNMP and vendor MIB support.telegraf/mibs/: bundled vendor MIBs.grafana/provisioning/: Grafana datasources and dashboards.
firewalls.ymlis the main operator-facing config file.- Supported vendors are currently
paloaltoandfortinet. - Palo Alto entries may omit
vendor; templates and generation logic default missing vendor values topaloalto. - Palo Alto system metrics use the shared measurement
pan_system;hostnameis a tag. Do not reintroduce per-host measurement names, because dashboards must work with multiple firewalls declared infirewalls.yml. - Palo Alto VSYS metrics are important for multi-tenant or multi-context firewalls; keep the
vsysmeasurement and prefer dashboards that can show global load plus per-VSYS sessions and CPS. - MIB comparison notes:
panIfTableexists in PAN-OS 10.2+,panhrStorageUsageand PA cluster summary objects appear in 11.2+, andpanVsysTotalCpspluspanInterfaceUtilizationTableappear in 12.1+.generate.pyperforms best-effort Palo Alto SNMP discovery, then infers these flags from discovered or declaredpanos_versioninto.firewalls.generated.yml; keep the user-facingfirewalls.ymlsimple unless an override is genuinely needed. generate.pyalso performs best-effort Fortinet SNMP discovery and should prefer discoveredfortios_version, serial, model, and VDOM presence over user-declared values.- Keep
firewalls.ymlminimal. Chassis mode is normally inferred bygenerate.py; only document or usechassis: trueas an advanced override when SNMP discovery cannot identify the platform. - Palo Alto HOST-RESOURCES tables are collected for all Palo Alto devices so multi-DP appliances such as PA-5200 Series can expose per-processor load. Chassis mode additionally enables ENTITY, ENTITY-SENSOR, and ENTITY-STATE polling in
telegraf/inputs_paloalto.tmpl. Keep this table-based where possible because sensor and slot indexes vary by platform. - SNMP v2c and SNMP v3 are both represented in
firewalls.yml; preserve both paths when changing templates. - Generated Telegraf config is written to
telegraf/telegraf.conf. - Grafana uses InfluxDB Flux with the datasource UID currently set to
P951FEA4DE68E13C5; avoid changing it casually because dashboards may depend on it. - Fortinet system metrics use the shared measurement
fortinet_system;hostnameis a tag. Do not reintroduce per-host measurement names, because dashboards must work with multiple firewalls declared infirewalls.yml. - Fortinet entries can set optional
modelandclustervalues; the Fortinet template collects system, interface, VDOM, processor, hardware sensor, and HA member metrics while preservingcpu_pct,mem_pct,sessions_active, and the sharedinterfacesmeasurement expected by dashboards.
Typical install or refresh on the target Linux host:
./generate.shDirect run after .venv exists:
.venv/bin/python generate.pyUseful manual commands:
docker compose build telegraf
docker compose up -d
docker compose ps
docker compose logs -f telegrafThis workspace may be edited from Windows, but the generator is intended for Linux hosts. Be careful with line endings in shell scripts; keep generate.sh LF.
- The current project version is stored in
VERSION. - Use semantic versioning. Dashboard-only fixes and small operator-facing improvements are usually patch releases.
- When preparing a release, update both
VERSIONandCHANGELOG.mdin the same commit. - Tags use the
vX.Y.Zformat and should matchVERSION. - After tagging and pushing, create a GitHub Release for the tag when previous releases exist.
- Do not bump versions, create tags, or publish releases unless the user explicitly asks for a new version or release.
- Prefer small, practical changes that improve installability and reduce operator friction.
- Keep the stack Compose-based and avoid adding heavyweight dependencies unless they clearly simplify installation.
- Keep shell scripts POSIX/Bash-friendly and readable.
- Preserve UTF-8 encoding. Project files, comments, logs, and documentation should stay in English.
- Keep
firewalls.ymlexamples clear and safe. Use placeholder IPs, usernames, passwords, tokens, and communities. - Do not commit real firewall IPs, SNMP communities, SNMPv3 credentials, InfluxDB tokens, or Grafana passwords.
- If adding config values, document them in
firewalls.ymlcomments or a README if one exists. - Prefer vendor-specific templates over large conditional blocks when adding firewall-specific SNMP metrics.
- Keep MIB paths consistent with
telegraf/Dockerfileanddocker-compose.yaml.
Runtime stack secrets belong in .env, created from .env.example. Keep .env ignored by Git and do not reintroduce real or sample service passwords directly in docker-compose.yaml.
Do not print secrets in logs, generated files beyond what Telegraf requires, or examples intended for sharing.
After changing generation logic or templates, validate at least:
python3 -m py_compile generate.py
bash -n generate.sh
python3 -m pip install -r requirements.txtWhen Docker is available, also validate:
./generate.sh
docker compose ps
docker compose logs --tail=100 telegrafFor dashboard or datasource changes, confirm Grafana starts and the datasource still targets:
- URL:
http://influxdb:8086 - organization:
netops - bucket:
firewalls
- Read the existing files before making structural changes.
- Do not delete generated or local artifact files unless the user explicitly asks.
- Do not rewrite dashboards wholesale unless the user asks for dashboard redesign.
- If adding support for another vendor, add a dedicated template, update
generate.py, ensure MIB availability, and keep existing Palo Alto/Fortinet behavior unchanged. - If a command needs network access, Docker image pulls, package installation, or writes outside this workspace, ask for approval first.