Manage Zabbix templates, items, triggers and discovery rules through YAML files and Git — the same mental model as Terraform, Ansible or ArgoCD.
pip install zbxctlzbx plan configs/ See what would change
zbx plan configs/ --output plan.json Save plan to file
zbx apply configs/ Apply changes to Zabbix
zbx apply --from-plan plan.json Apply a saved plan (CI/CD gating)
zbx diff configs/ Compare local config against Zabbix
zbx validate configs/ Validate YAML schema (no Zabbix connection)
zbx export linux Export an existing template to YAML
zbx export --all Export every template to configs/templates/
zbx schema Print YAML field reference (Markdown or JSON Schema)
zbx scaffold my-check Bootstrap a new monitoring check folder
zbx status Show connection status and server summary
zbx host list List all hosts in Zabbix
zbx host create <host> --ip ... Create a host from the CLI
zbx host delete <host> Delete a host
zbx hostgroup list List all host groups
zbx hostgroup create <name> Create a host group
zbx hostgroup delete <name> Delete an empty host group
zbx macro list List all global macros
zbx macro set {$NAME} value Create or update a global macro
zbx macro delete {$NAME} Delete a global macro
zbx inventory list List all hosts in Zabbix
zbx inventory apply inventory.yaml Create or update hosts in Zabbix
zbx check list List all bundled monitoring checks
zbx check info <name> Show items, triggers and agent details for a check
zbx check install <name> <host> Apply template + deploy agent in one step
zbx agent diff <host> Preview agent-side changes
zbx agent deploy <host> Deploy scripts and UserParameters via SSH
zbx agent test <host> Verify keys with zabbix_agentd -t
zbx agent deploy <host> --from-check configs/checks/my-check/
zbx agent test <host> --from-check configs/checks/my-check/
zbx --profile staging plan configs/ Use a named environment profile
zbx --install-completion bash Enable shell completion (bash/zsh/fish)
| Pain | Solution |
|---|---|
| Zabbix templates live only in the web UI | Store everything as YAML in Git |
| No audit trail for monitoring changes | Every change is a commit |
| Hard to review or approve changes | PR-based workflow, same as application code |
| Drift between environments | zbx diff catches it |
| Manual script deployment to monitored hosts | zbx agent deploy handles it |
| No way to automate template rollout | CI/CD friendly CLI |
Requirements: Python 3.11+
From PyPI (recommended):
pip install zbxctl
zbx --versionFrom source (for development):
git clone https://github.com/psantana5/zbx
cd zbx
pip install -e .
zbx --versionCopy .env.example to .env and fill in the connection details:
cp .env.example .envZBX_URL=http://zabbix.example.com/zabbix
ZBX_USER=Admin
ZBX_PASSWORD=secret
ZBX_VERIFY_SSL=true
ZBX_TIMEOUT=30 # API request timeout in seconds (default: 30)
Additional optional env vars:
| Variable | Default | Description |
|---|---|---|
ZBX_TIMEOUT |
30 |
Zabbix API request timeout (seconds) |
ZBX_SSH_TIMEOUT |
30 |
SSH connect timeout for agent deployment (seconds) |
ZBX_INIT_TIMEOUT |
10 |
zbx init connection test timeout (seconds) |
ZBX_PROFILE |
— | Active named profile (see Multi-environment profiles) |
Or export the variables directly (useful in CI/CD):
export ZBX_URL=http://zabbix.example.com/zabbix
export ZBX_USER=Admin
export ZBX_PASSWORD=secretFor teams with multiple environments (staging, production, dev), create a
zbx.profiles.yaml (gitignored — contains credentials):
# zbx.profiles.yaml
staging:
ZBX_URL: http://zabbix-staging.example.com/zabbix
ZBX_USER: Admin
ZBX_PASSWORD: staging-secret
production:
ZBX_URL: https://zabbix.example.com/zabbix
ZBX_USER: Admin
ZBX_PASSWORD: prod-secret
ZBX_VERIFY_SSL: "true"Then switch environments with:
zbx --profile staging plan configs/
zbx --profile production apply configs/ --auto-approve
# Or set via environment variable
export ZBX_PROFILE=staging
zbx plan configs/Copy zbx.profiles.yaml.example from the repo as a starting point.
zbx manages both sides of Zabbix monitoring:
Layer 1 — Zabbix server config (templates, items, triggers, discovery rules)
configs/templates/ YAML templates
configs/hosts/ Host playbooks (which templates to link, which macros to set)
zbx plan / apply / diff / validate / export
Layer 2 — Monitored host agent config (scripts + UserParameters)
scripts/ Agent scripts versioned in Git
inventory.yaml Host inventory with agent deployment config
zbx inventory apply Create/update hosts in Zabbix
zbx agent deploy SSH into host, deploy scripts, write UserParameters
zbx agent test Run zabbix_agentd -t to verify keys
Run the interactive setup wizard once to connect to your Zabbix server and scaffold the directory structure:
zbx initzbxctl — first-time setup
Zabbix URL [http://localhost/zabbix]: http://zabbix.example.com/zabbix
Username [Admin]:
Password: ••••••••
Verify SSL certificates? [Y/n]: y
✔ Connected to Zabbix 7.4.7
✔ Authentication successful
✔ Written .env
✔ Created configs/templates/ configs/hosts/ configs/checks/
✔ Updated .gitignore (excluded .env)
All set! Next steps:
zbx plan configs/ # preview changes
zbx apply configs/ # apply to Zabbix
zbx check list # browse bundled checks
For non-interactive environments (CI/CD), use --yes to accept all defaults:
ZBX_URL=http://zabbix.example.com/zabbix ZBX_USER=Admin ZBX_PASSWORD=secret zbx init --yes# configs/templates/linux-observability.yaml
template: linux-observability
name: "Linux Observability"
description: "Core performance metrics for Linux servers"
groups:
- Templates
- Templates/Linux
macros:
- macro: "{$CPU.UTIL.CRIT}"
value: "90"
description: CPU utilization critical threshold (%)
- macro: "{$MEM.AVAIL.MIN}"
value: "512"
description: Minimum available memory in MB
items:
- name: CPU utilization
key: system.cpu.util
interval: 30s
value_type: float
units: "%"
- name: Available memory
key: vm.memory.size[available]
interval: 60s
value_type: unsigned
units: B
triggers:
- name: High CPU utilization (>90% for 5 min)
expression: avg(/linux-observability/system.cpu.util,5m) > 90
severity: high
discovery_rules:
- name: Mounted filesystem discovery
key: vfs.fs.discovery
interval: 1h
item_prototypes:
- name: "Filesystem {#FSNAME}: used space (%)"
key: "vfs.fs.size[{#FSNAME},pused]"
interval: 5m
value_type: float
units: "%"zbx plan configs/templates/linux-observability.yaml
zbx apply configs/templates/linux-observability.yaml# configs/hosts/webserver01.yaml
host: webserver01
templates:
- linux-observability
macros:
- macro: "{$CUSTOM_THRESHOLD}"
value: "90"zbx apply configs/hosts/webserver01.yamlInteractive first-time setup wizard. Connects to your Zabbix server, writes .env,
and creates the standard configs/ directory structure.
zbx init # interactive prompts
zbx init --yes # non-interactive, reads from env varsWhat it does:
- Prompts for Zabbix URL, username and password
- Tests the connection (
apiinfo.version) and authenticates - Writes
.envwith your connection details - Creates
configs/templates/,configs/hosts/,configs/checks/ - Adds
.envto.gitignoreso credentials are never committed
Environment variables read by zbx init --yes:
| Variable | Description |
|---|---|
ZBX_URL |
Zabbix server URL |
ZBX_USER |
Username (default: Admin) |
ZBX_PASSWORD |
Password |
ZBX_VERIFY_SSL |
Verify TLS certificates (true/false, default: true) |
ZBX_INIT_TIMEOUT |
Connection test timeout in seconds (default: 10) |
Shows what would be created, modified or removed. No changes are made.
+ template: linux-observability
+ item: CPU utilization (system.cpu.util)
+ item: Available memory (vm.memory.size[available])
+ trigger: High CPU utilization (>90% for 5 min)
+ discovery_rule: Mounted filesystem discovery
Plan: 4 to add, 0 to modify, 0 to remove
Save the plan to a file for later use (Terraform-style):
zbx plan configs/ --output plan.json
# Plan saved to plan.json. Run zbx apply --from-plan plan.json to apply it.Applies the configuration. Shows the plan first, then prompts for confirmation.
zbx apply configs/ # interactive confirmation
zbx apply configs/ --auto-approve # skip confirmation (CI/CD)
zbx apply configs/ --dry-run # same as plan
zbx apply --from-plan plan.json # apply a previously saved planCI/CD gating pattern (Terraform-style):
# In your review/plan stage:
zbx plan configs/ --output zbx.plan
# After approval, in your apply stage:
zbx apply --from-plan zbx.plan --auto-approveCompares local YAML state against the current Zabbix configuration.
zbx diff configs/
zbx diff configs/templates/nginx.yamlValidates YAML files against the schema without connecting to Zabbix.
zbx validate configs/
zbx validate configs/ --verboseExports an existing Zabbix template to YAML. Use this to migrate existing templates to Git.
zbx export "Linux by Zabbix agent"
zbx export "Linux by Zabbix agent" --output configs/templates/linux-zabbix-agent.yaml
zbx export linux # partial name search
# Export every template at once
zbx export --all # writes to configs/templates/
zbx export --all --out-dir my-backup/Prints the full YAML field reference. Useful when writing templates by hand.
zbx schema # Markdown table (default)
zbx schema --format json # JSON Schema (for editor integration)
zbx schema --output docs/schema.md # write to fileBootstraps a new self-contained monitoring check folder under configs/checks/.
The generated skeleton includes a check.yaml, a placeholder script and a README.md.
zbx scaffold my-check-name
# creates configs/checks/my-check-name/{check.yaml, my_check_name.py, README.md}After scaffolding, edit the generated files and follow the contributor workflow described in CONTRIBUTING.md.
Shows connection info and a summary of the Zabbix server state.
zbx status # one-shot snapshot
zbx status --watch # live-refreshing dashboard (Ctrl+C to stop)
zbx status --watch --interval 10 # refresh every 10 secondszbx version 0.6.0
Zabbix server http://zabbix.example.com/zabbix
API version 7.4.7
Authenticated as Admin
Templates 210
Hosts 42 total (40 enabled)
Active problems 3
Recent problems
• high High CPU on web-01
• average Disk full on db-02
• warning Service nginx down on proxy-01
Browse and deploy bundled monitoring checks.
zbx check list # table of all checks with item/trigger counts
zbx check info postgresql # full details: items, triggers, agent deploy info
zbx check install postgresql # copy check to configs/checks/ then apply to Zabbix
zbx check update postgresql # refresh an installed check from latest package version
zbx check update # update all installed checks at once
zbx check update --dry-run # preview what would change without writing fileszbx check install is a shortcut for:
zbx apply configs/checks/postgresql/
zbx agent deploy myhost --from-check configs/checks/postgresql/Manage Zabbix hosts directly from the CLI without an inventory.yaml.
zbx host list # table of all hosts
zbx host list --group "Linux servers" # filter by group
zbx host list --templates # show linked templates column
zbx host create myserver \
--ip 192.168.1.10 \
--group "Linux servers" \
--template "Linux by Zabbix agent" \
--template postgresql # link multiple templates
zbx host delete myserver # with confirmation prompt
zbx host delete myserver --force # skip confirmationManage host groups.
zbx hostgroup list # all groups
zbx hostgroup list --hosts # show host count per group
zbx hostgroup list --search prod # filter by name
zbx hostgroup create "Production Linux"
zbx hostgroup delete "Old Group" # refuses if group has hostsManage global macros (applies to all hosts/templates in Zabbix).
zbx macro list # all global macros
zbx macro list --search SLACK # filter by name
zbx macro set '{$SLACK_WEBHOOK}' 'https://hooks.slack.com/...'
zbx macro set '{$SNMP_COMMUNITY}' public --description "Default SNMP v2"
zbx macro delete '{$OLD_MACRO}'The inventory defines all hosts that should exist in Zabbix and how to connect to them. It also defines agent-side deployment config (scripts and UserParameters).
# inventory.yaml
hosts:
- host: webserver01
name: "Web Server 01"
ip: 192.168.1.101
port: 10050
groups:
- Linux servers
- Web servers
status: enabled
agent:
ssh_user: deploy
sudo: true
scripts:
- source: scripts/check_nginx.sh
dest: /usr/local/scripts/zabbix/check_nginx.sh
owner: zabbix # OS user owning the script (default: zabbix)
group: zabbix # OS group owning the script (default: zabbix)
mode: "0755"
userparameters:
- name: nginx
path: /etc/zabbix/zabbix_agentd.d/userparameters_nginx.conf
parameters:
- key: nginx.active_connections
command: /usr/local/scripts/zabbix/check_nginx.sh connections
- key: nginx.requests_per_sec
command: /usr/local/scripts/zabbix/check_nginx.sh rps
restart_agent: false
test_keys:
- nginx.active_connectionsLocalhost shortcut: If ip is 127.0.0.1, localhost, or ::1, zbx
skips SSH entirely and runs all commands locally via subprocess. No SSH key
setup required. zbx agent deploy will prompt for your sudo password once
at startup (hidden input) and use it for all writes to /etc/zabbix/.
zbx inventory list # table of all hosts in Zabbix
zbx inventory apply inventory.yaml # create or update hosts + macros
zbx inventory apply inventory.yaml --dry-runMacro diff output example:
~ host: webserver01 (macros (+{$CPU_THRESHOLD}, ~{$MEM_THRESHOLD}))
Inventory Summary
1 to update
+ macro {$CPU_THRESHOLD} on 'webserver01'
~ macro {$MEM_THRESHOLD} on 'webserver01'
ok Inventory applied: 0 created, 1 updated.
The agent commands deploy scripts and UserParameters to monitored hosts.
Scripts are stored in scripts/ (or inside a check folder) in the repo and
versioned in Git. zbx computes a SHA-256 checksum before every deploy —
only changed files are transferred.
zbx agent diff webserver01 # show what would change on the host
zbx agent deploy webserver01 # copy scripts, write userparameters
zbx agent deploy webserver01 --dry-run
zbx agent deploy webserver01 --auto-approve # skip confirmation (CI/CD)
zbx agent test webserver01 # run zabbix_agentd -t for each test_key
zbx agent test webserver01 --key nginx.active_connections # ad-hoc testIf a check lives under configs/checks/, you can deploy its scripts and
UserParameters without touching inventory.yaml. zbx merges the check's
agent: block into the host's existing config automatically:
zbx agent diff webserver01 --from-check configs/checks/nginx/
zbx agent deploy webserver01 --from-check configs/checks/nginx/
zbx agent test webserver01 --from-check configs/checks/nginx/For remote hosts, zbx connects over SSH (Paramiko). The user running zbx
must have SSH key access to the host. Password auth is not supported — use
ssh-copy-id to set up key-based auth first.
For localhost, zbx uses subprocess. If sudo: true is set in the agent
config, zbx agent deploy prompts for your sudo password once before making
any writes.
# 1. Add monitoring scripts to the repo
cp /path/to/script.py scripts/
git add scripts/script.py
# 2. Define the template (server side)
vim configs/templates/my-template.yaml
# 3. Define the inventory entry with agent config (host side)
vim inventory.yaml
# 4. Define the host playbook (template linking + macros)
vim configs/hosts/myhost.yaml
# 5. Deploy — server side
zbx validate configs/
zbx plan configs/
zbx apply configs/
# 6. Deploy — host agent side
zbx inventory apply inventory.yaml # ensure host exists in Zabbix
zbx agent diff myhost # preview
zbx agent deploy myhost # copy scripts + write userparameters
zbx agent test myhost # verify keys
# 7. Commit everything
git add configs/ scripts/ inventory.yaml
git commit -m "feat: add monitoring for myhost"# 1. Bootstrap the check folder
zbx scaffold my-check
# 2. Write the script and fill in check.yaml
vim configs/checks/my-check/my_check.py
vim configs/checks/my-check/check.yaml
# 3. Validate and preview
zbx validate configs/checks/my-check/
zbx plan configs/checks/my-check/
# 4. Apply the template to Zabbix
zbx apply configs/checks/my-check/
# 5. Deploy script to host (no inventory.yaml changes needed)
zbx agent deploy myhost --from-check configs/checks/my-check/
zbx agent test myhost --from-check configs/checks/my-check/
# 6. Commit
git add configs/checks/my-check/
git commit -m "feat(check): add my-check monitoring"| Field | Type | Required | Description |
|---|---|---|---|
template |
string | yes | Technical name (used as Zabbix host name) |
name |
string | no | Display name (defaults to template) |
description |
string | no | Human-readable description |
groups |
list[string] | no | Template groups (default: ["Templates"]) |
items |
list[Item] | no | Monitored items |
triggers |
list[Trigger] | no | Alert triggers |
discovery_rules |
list[DiscoveryRule] | no | LLD rules |
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Display name |
key |
string | required | Zabbix item key |
interval |
string | 60s |
Collection interval (30s, 5m, 1h) |
type |
enum | zabbix_agent |
Item type |
value_type |
enum | float |
Data type |
units |
string | "" |
Unit label (%, B, bps) |
history |
string | 90d |
History retention |
trends |
string | 365d |
Trends retention |
enabled |
bool | true |
Whether the item is active |
params |
string | "" |
Formula for calculated items; JSONPath/regex for http_agent |
Item types: zabbix_agent, zabbix_agent_active, zabbix_trapper,
simple_check, calculated, http_agent, snmp_v2c, dependent
calculateditems requireparams— set it to the formula string, e.g.params: "avg(/mytemplate/my.key,5m)". Omitting it causesInvalid parameter "/1": the parameter "params" is missingfrom the API.
Value types: float, unsigned, char, text, log
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Display name |
key |
string | required | Item key (may contain LLD macros) |
type |
enum | zabbix_agent |
Item type |
value_type |
enum | float |
Data type |
master_item_key |
string | no | Key of master item (for dependent type) |
preprocessing |
list[Preprocessing] | [] |
Preprocessing steps |
Preprocessing types: jsonpath, regex, multiplier, trim,
not_match_regex, check_not_supported, discard_unchanged
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Trigger name |
expression |
string | required | Zabbix trigger expression |
severity |
enum | average |
Alert severity |
description |
string | "" |
Description or runbook notes |
enabled |
bool | true |
Whether the trigger is active |
Severities: not_classified, information, warning, average, high, disaster
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Rule name |
key |
string | required | LLD key |
interval |
string | 1h |
Discovery interval |
type |
enum | zabbix_agent |
Same values as Item type |
item_prototypes |
list[ItemPrototype] | [] |
Item prototypes |
trigger_prototypes |
list[TriggerPrototype] | [] |
Trigger prototypes |
Templates can define user macros that are created, updated and removed idempotently alongside the template itself. Template macros let hosts override thresholds per-host while keeping sane defaults in the template.
template: linux-observability
macros:
- macro: "{$CPU.UTIL.CRIT}"
value: "80"
description: CPU utilization critical threshold (%)
- macro: "{$MEM.AVAIL.MIN}"
value: "20"
description: Minimum available memory (%)
- macro: "{$DISK.UTIL.WARN}"
value: "85"| Field | Type | Default | Description |
|---|---|---|---|
macro |
string | required | Macro name — must be {$NAME} format |
value |
string | "" |
Default value |
description |
string | "" |
Human-readable description |
zbx plan and zbx diff detect macro value and description changes. zbx export exports macros back to YAML for full round-trip migration.
host: myhost # must match the technical hostname in Zabbix
templates:
- linux-observability # templates to link
- custom-template
macros:
- macro: "{$THRESHOLD}"
value: "90"
description: "Alert threshold percentage"host: myhost
name: "My Host Display Name"
ip: 192.168.1.100
port: 10050
groups:
- Linux servers
description: "Optional description"
status: enabled # enabled or disabled
templates:
- linux-observability # pre-link templates at host creation time
macros:
- macro: "{$CPU_THRESHOLD}"
value: "90"
description: "CPU alert threshold (%)"
- macro: "{$MEM_THRESHOLD}"
value: "80"
description: "Memory alert threshold (%)"Macros are applied idempotently: zbx inventory apply creates missing macros,
updates changed values, and skips unchanged ones. Running it twice produces
the same result.
zbx ships with 14 ready-to-use monitoring checks under configs/checks/.
Each includes a Zabbix template and an agent: block so the script and
UserParameter can be deployed with a single command.
| Check | Folder | Keys |
|---|---|---|
| PostgreSQL | configs/checks/postgresql/ |
postgresql.stat[ping], postgresql.stat[connections.active], … |
| Redis | configs/checks/redis/ |
redis.stat[ping], redis.stat[connected_clients], … |
| Nginx | configs/checks/nginx/ |
nginx.stat[ping], nginx.stat[active], … |
| Docker | configs/checks/docker/ |
docker.stat[ping], docker.stat[containers.running], … |
| SSL cert | configs/checks/ssl-cert/ |
ssl.cert[days_remaining,host:443], ssl.cert[valid,host:443] |
| MySQL | configs/checks/mysql/ |
mysql.stat[ping], mysql.stat[threads_connected], … |
| RabbitMQ | configs/checks/rabbitmq/ |
rabbitmq.stat[ping], rabbitmq.stat[messages_ready], … |
| HAProxy | configs/checks/haproxy/ |
haproxy.stat[ping], haproxy.stat[active_backends], … |
| Elasticsearch | configs/checks/elasticsearch/ |
elasticsearch.stat[ping], elasticsearch.stat[status], … |
| Kubernetes node | configs/checks/kubernetes-node/ |
k8s.node[ping], k8s.node[pods_running], … |
| Windows agent | configs/checks/windows-agent/ |
system.cpu.util, vm.memory.size[available], system.uptime, … |
| Apache httpd | configs/checks/apache-httpd/ |
apache.stat[ping], apache.stat[busy_workers], … |
| MongoDB | configs/checks/mongodb/ |
mongodb.stat[ping], mongodb.stat[connections.active], … |
| JVM (Jolokia) | configs/checks/jvm-jolokia/ |
jvm.jolokia[heap.usage_pct], jvm.jolokia[threads.count], … |
Browse and install checks interactively:
zbx check list # see all checks
zbx check info mysql # items, triggers, agent details
zbx check install mysql db-server-01 # apply + deploy in one commandCustomising check macros
Each check ships with sensible macro defaults. Override them in your
inventory.yaml host block to adapt without editing the check YAML:
# inventory.yaml
hosts:
- name: app-server-01
ip: 10.0.1.10
templates:
- jvm-jolokia
- ssl-cert
macros:
- macro: "{$JOLOKIA_PORT}"
value: "9778" # non-default JMX port
- macro: "{$SSL_TEST_HOST}"
value: "app-server-01:8443" # HTTPS on a non-standard portDeploy a check manually (step-by-step):
# 1. Apply the template to Zabbix
zbx apply configs/checks/postgresql/
# 2. Preview what the agent deploy would do
zbx agent diff myhost --from-check configs/checks/postgresql/
# 3. Deploy script + UserParameter to the monitored host
zbx agent deploy myhost --from-check configs/checks/postgresql/
# 4. Verify the keys are working
zbx agent test myhost --from-check configs/checks/postgresql/Scripts are installed to /usr/local/zbx/scripts/ and UserParameters are
written to /etc/zabbix/zabbix_agentd.d/zbx-<check>.conf.
Script monitoring scripts also support environment variable overrides for non-default service endpoints (useful on hosts with multiple instances):
| Script | Env var | Default |
|---|---|---|
check_apache.py |
APACHE_STATUS_URL |
http://localhost/server-status?auto |
check_apache.py |
APACHE_TIMEOUT |
5 |
check_mysql.py |
MYSQL_HOST / MYSQL_PORT |
127.0.0.1 / 3306 |
check_rabbitmq.py |
RABBITMQ_HOST / RABBITMQ_PORT |
127.0.0.1 / 15672 |
check_elasticsearch.py |
ES_HOST / ES_PORT |
127.0.0.1 / 9200 |
check_nginx.py |
NGINX_STATUS_URL |
http://localhost/nginx_status |
check_haproxy.py |
HAPROXY_STATS_URL |
http://127.0.0.1:8404/stats;csv |
check_jvm_jolokia.py |
JOLOKIA_HOST / JOLOKIA_PORT |
localhost / 8778 |
zbx/
├── zbx/
│ ├── cli.py Typer app + command registration
│ ├── models.py Pydantic models (Template, Item, Trigger, DiscoveryRule,
│ │ Host, InventoryHost, AgentConfig, ScriptDeploy, ...)
│ ├── config_loader.py YAML loading, schema validation, profile support
│ ├── zabbix_client.py Zabbix JSON-RPC HTTP client (version-aware auth)
│ ├── diff_engine.py Desired vs current state comparison
│ ├── deployer.py Apply logic for templates and hosts
│ ├── agent_deployer.py SSH/local agent deployment (scripts + UserParameters)
│ ├── plan_serializer.py Serialize/deserialize plan diffs to/from JSON
│ ├── formatter.py Rich CLI output
│ └── commands/
│ ├── apply.py zbx apply (--from-plan support)
│ ├── plan.py zbx plan (--output support)
│ ├── diff.py zbx diff
│ ├── validate.py zbx validate
│ ├── export.py zbx export / zbx export --all
│ ├── scaffold.py zbx scaffold
│ ├── schema.py zbx schema (field reference / JSON Schema)
│ ├── inventory.py zbx inventory list / apply (with macro support)
│ ├── agent.py zbx agent diff / deploy / test
│ ├── status.py zbx status (connection + server summary)
│ ├── check.py zbx check list / info / install
│ ├── host.py zbx host list / create / delete
│ ├── hostgroup.py zbx hostgroup list / create / delete
│ └── macro.py zbx macro list / set / delete
├── configs/
│ ├── templates/ Standalone template YAML files
│ │ ├── linux-observability.yaml
│ │ └── nginx.yaml
│ ├── checks/ Self-contained monitoring checks (14 bundled)
│ │ ├── CONTRIBUTING.md How to add a new check
│ │ ├── postgresql/ PostgreSQL monitoring
│ │ ├── redis/ Redis monitoring
│ │ ├── nginx/ Nginx stub_status monitoring
│ │ ├── docker/ Docker daemon monitoring
│ │ ├── ssl-cert/ SSL certificate expiry
│ │ ├── mysql/ MySQL / MariaDB monitoring
│ │ ├── rabbitmq/ RabbitMQ management API monitoring
│ │ ├── haproxy/ HAProxy stats monitoring
│ │ ├── elasticsearch/ Elasticsearch REST API monitoring
│ │ ├── kubernetes-node/ Kubernetes node Kubelet monitoring
│ │ ├── windows-agent/ Windows built-in agent keys (no script)
│ │ ├── apache-httpd/ Apache mod_status monitoring
│ │ ├── mongodb/ MongoDB monitoring
│ │ ├── jvm-jolokia/ JVM monitoring via Jolokia REST API
│ │ ├── system-health/ CPU / memory / disk (built-in keys, no script)
│ │ └── s3-monitoring/ Reference example with custom script
│ └── hosts/ Host playbook YAML files
│ └── zabbixtest3100.yaml
├── scripts/ Agent scripts (legacy; prefer configs/checks/ for new work)
│ └── README.md
├── tests/
│ ├── test_models.py Unit tests — Pydantic model validation (51 tests)
│ ├── test_diff_engine.py Unit tests — diff engine logic (15 tests)
│ └── test_e2e.py End-to-end integration tests vs live Zabbix (22 tests)
├── inventory.yaml Host inventory (groups, IPs, agent config)
├── zbx.profiles.yaml.example Multi-environment profile template
├── .github/
│ ├── workflows/
│ │ ├── publish.yml PyPI publish on vX.Y.Z tag (OIDC trusted publishing)
│ │ ├── tests.yml Run test suite on push/PR
│ │ └── ai-maintainer.yml Automated issue processing via Claude
│ └── scripts/
│ └── ai_maintainer.py Agentic implementation
├── CONTRIBUTING.md
├── CHANGELOG.md
├── pyproject.toml
├── .env.example
└── README.md
| Zabbix version | Notes |
|---|---|
| < 5.4 | user field in login |
| >= 5.4 | username field in login |
| >= 6.2 | Templates require templategroup, not hostgroup |
| >= 6.4 | Auth token sent as Authorization: Bearer header (not in payload) |
zbx detects the API version on first connect via apiinfo.version and
adjusts automatically.
git checkout -b monitoring/add-redis-template
vim configs/templates/redis.yaml
zbx validate configs/templates/redis.yaml
ZBX_URL=http://zabbix-staging zbx plan configs/templates/redis.yaml
git add configs/templates/redis.yaml
git commit -m "feat: add Redis monitoring template"
git push origin monitoring/add-redis-template
# After PR approval
zbx apply configs/templates/redis.yaml --auto-approveThe repository ships with .github/workflows/zbx-gitops.yml, a Terraform-style
GitOps pipeline:
| Event | Action |
|---|---|
Pull request touches configs/ |
zbx validate + zbx plan — result posted as PR comment |
Merge to main |
zbx apply --auto-approve — changes deployed to Zabbix |
Required secrets (Settings → Secrets and variables → Actions):
ZBX_URL https://zabbix.example.com
ZBX_USER Admin
ZBX_PASSWORD secret
Manual trigger: Go to Actions → zbx GitOps → Run workflow → choose plan or apply.
GitHub's cloud runners cannot reach a Zabbix server on a private network. Use a self-hosted runner on a machine that has network access to your Zabbix:
# In .github/workflows/zbx-gitops.yml, change:
runs-on: ubuntu-latest
# to:
runs-on: self-hostedTag a release to publish zbxctl to PyPI automatically via .github/workflows/publish.yml:
git tag v1.0.0
git push origin v1.0.0The workflow uses OIDC trusted publishing — no API token needed once configured at pypi.org/manage/project/zbxctl/settings/publishing/.
- zbx never deletes items, triggers or discovery rules that exist in Zabbix but are absent from config. It logs a warning instead. Removal must be done manually — this is an intentional safety net.
zbx applyalways shows the plan and asks for confirmation unless--auto-approveis passed.- All write operations are idempotent — running
zbx applytwice produces the same result. zbx agent deployuses SHA-256 checksums to skip files that have not changed.
| What to add | Where |
|---|---|
| New resource type (host groups, macros) | Model in models.py, CRUD in zabbix_client.py, diff in diff_engine.py, apply in deployer.py |
| New CLI command | zbx/commands/<cmd>.py, registered in cli.py |
| Custom output format | formatter.py |
| New agent check step | agent_deployer.py |
| New monitoring check | zbx scaffold <name> → fill in configs/checks/<name>/ |
See CONTRIBUTING.md for the full contributor guide.
The repository includes a GitHub Actions workflow that automatically processes
issues labeled ai-task using Claude (via GitHub Models API).
- Open an issue describing the change, bug fix or new check needed.
- Add the
ai-tasklabel. - The workflow triggers, runs an agentic loop:
- reads the issue and explores the codebase,
- writes the necessary files,
- validates any YAML,
- commits and pushes to a new branch,
- opens a pull request.
- A comment is posted on the issue with a link to the PR.
Be specific. Good example:
Add a PostgreSQL monitoring check
Add
configs/checks/postgres/that monitors:
- Active connections (
pg_stat_activitycount) — trigger: warning > 200, high > 400- Replication lag in seconds
- Database size in bytes
Script should output plain numbers. Use
psqlto query.
Actions → AI Maintainer → Run workflow → enter the issue number.
MIT
