Synchronizes Zabbix problems with Argus incidents
Project description
zabbix-argus-glue
A glue service that synchronizes Zabbix 7.2+ problems with Argus incidents. It translates Zabbix problem events into Argus incident state changes, keeping both systems in sync.
Status: Early development. The reconciliation poller and webhook receiver are functional; ack sync is planned but not yet implemented.
Architecture
Hybrid push + poll design:
┌─────────────┐ webhook POST ┌──────────────────────┐ REST API ┌───────────┐
│ Zabbix │ ───────────────> │ zabbix-argus-glue │ ───────────> │ Argus │
│ Server │ <─────────────── │ │ <─────────── │ Server │
│ │ API polling │ - HTTP receiver │ │ │
└─────────────┘ │ - Reconciliation │ └───────────┘
│ - Ack sync * │
└──────────────────────┘
* planned
- Webhook receiver — receives Zabbix webhook POSTs, creates/closes Argus incidents in near-real-time. (implemented)
- Reconciliation poller — periodically fetches open problems from Zabbix, compares against Argus state, fixes drift. Full sync on startup. (implemented)
- Ack sync — detect acknowledgements and closures made in Argus, write them back to Zabbix. (planned)
Installation
uv tool install zabbix-argus-glue
Or install the latest unreleased version directly from the repository:
uv tool install git+https://github.com/Uninett/zabbix-argus-glue.git
Configuration
Copy the example configuration and edit it:
cp zabbixargus.example.toml zabbixargus.toml
See zabbixargus.example.toml for all available options with comments.
The program searches for zabbixargus.toml in the following locations
(first match wins):
- Current working directory
$XDG_CONFIG_HOME/zabbixargus/(typically~/.config/zabbixargus/)- System config directory (typically
/etc/xdg/zabbixargus/)
You can override this with --config PATH.
API tokens can also be provided via the ARGUS_TOKEN and ZABBIX_TOKEN
environment variables instead of storing them in the config file. The
webhook shared secret can likewise be set via WEBHOOK_SECRET instead of
[webhook] secret, so it can be sourced from a Kubernetes Secret or vault
rather than a plaintext config file.
Incident detail links point back to the Zabbix problem page using
relative URLs (e.g. tr_events.php?triggerid=...&eventid=...). The
Argus source system's base_url must include the full path prefix to
the Zabbix frontend — for Apache-based installs this is typically
https://zabbix.example.com/zabbix/, while Nginx-based installs
usually use https://zabbix.example.com/.
Usage
# Run the service (config auto-discovered)
zabbix-argus-glue
# Verify API connectivity before running
zabbix-argus-glue --verify
# Use an explicit config file
zabbix-argus-glue --config /etc/zabbixargus/zabbixargus.toml
# Enable debug logging
zabbix-argus-glue -v
Webhook setup
The webhook receiver listens for HTTP POSTs from Zabbix. To use it, you need to configure a webhook media type and a trigger action in Zabbix.
By default the receiver binds 0.0.0.0:8080; change the bind address
and port with [webhook] listen and port, or turn the receiver off
entirely with [webhook] enabled = false.
Requires Zabbix 7.2 or later (the setup uses the {EVENT.TIMESTAMP}
macro, introduced after the 7.0 LTS).
1. Create a webhook media type
In Zabbix, go to Alerts → Media types → Create media type and configure:
-
Name:
Argus -
Type: Webhook
-
Parameters:
Name Value glue_urlhttp://glue-host:8080/webhooksecret(same value as [webhook] secretin your config)eventid{EVENT.ID}value{EVENT.VALUE}severity{EVENT.NSEVERITY}hostname{HOST.NAME}name{EVENT.NAME}timestamp{EVENT.TIMESTAMP}triggerid{TRIGGER.ID}tags{EVENT.TAGSJSON}update_status{EVENT.UPDATE.STATUS}update_action{EVENT.UPDATE.ACTIONJSON}update_user{USER.FULLNAME} -
Script:
var params = JSON.parse(value), req = new HttpRequest(), payload = {}; req.addHeader('Content-Type: application/json'); req.addHeader('X-Webhook-Secret: ' + params.secret); payload.eventid = params.eventid; payload.value = params.value; payload.severity = params.severity; payload.hostname = params.hostname; payload.name = params.name; payload.timestamp = params.timestamp; payload.triggerid = params.triggerid; payload.tags = params.tags; payload.update_status = params.update_status; payload.update_action = params.update_action; payload.update_user = params.update_user; var resp = req.post(params.glue_url, JSON.stringify(payload)); if (req.getStatus() < 200 || req.getStatus() >= 300) { throw 'Request failed with status ' + req.getStatus() + ': ' + resp; } return 'OK';
2. Assign the media type to a user
Zabbix sends alerts through users. Create a dedicated service account or use an existing user.
Go to Users → Users and create or edit a user:
- Username: e.g.
argus-glue - Role: a User-type role (with the problem-update actions enabled) is enough — the account only fires webhooks and, once acknowledgement sync lands, acts on problems. Avoid Super admin: a credential-bearing service account should not hold full configuration rights.
- Groups: a user group with read access to the hosts you want to sync. (Acknowledgement sync back to Zabbix additionally needs read-write access to those host groups.)
- Media tab → Add:
- Type:
Argus - Send to:
argus(required by Zabbix but ignored by webhooks) - Enabled: checked
- Type:
Resolving "Inaccessible user" in update notifications
Update notifications carry {USER.FULLNAME} — the person who
acknowledged or commented on a problem. Zabbix only reveals a user's
name to accounts that share at least one user group with them;
otherwise the macro resolves to the literal string Inaccessible user
(a privacy safeguard introduced by
ZBX-12441). To make names
resolve without widening the service account's access, create a user
group with no permissions (e.g. argus-visibility) and add both the
argus-glue account and every operator who acknowledges problems to it.
Membership alone establishes visibility; the empty permission set keeps
it least-privilege. Granting Super admin also works but
over-privileges the account — don't.
3. Create a trigger action
Go to Alerts → Actions → Trigger actions → Create action:
- Name:
Send to Argus - Conditions: (adjust to match the problems you want to sync)
- Operations → Add:
- Send to users: select the user from step 2
- Send only to:
Argus - Check Custom message and set any non-empty subject and
body (e.g.
{EVENT.NAME}/{EVENT.ID}). Zabbix requires a message to be defined even though webhooks ignore it.
- Recovery operations → Add:
- Same settings as above, including a custom message
- Update operations → Add:
- Same settings as above (forwards acks, comments, and severity changes)
4. Test with curl
curl -X POST http://localhost:8080/webhook \
-H 'Content-Type: application/json' \
-H 'X-Webhook-Secret: your-secret' \
-d '{
"eventid": "12345",
"value": "1",
"severity": "4",
"hostname": "web01.example.com",
"name": "High CPU usage on web01",
"timestamp": "1745326800",
"triggerid": "678",
"tags": "[{\"tag\": \"application\", \"value\": \"nginx\"}]"
}'
Development
Requires Python 3.11+.
# Clone and install in editable mode
git clone https://github.com/Uninett/zabbix-argus-glue.git
cd zabbix-argus-glue
uv venv --python 3.13
uv sync --all-groups
# Set up pre-commit hooks
pre-commit install
# Run tests
pytest
# Lint and format
ruff check --fix src/
ruff format src/
Changelog
See CHANGELOG.md. We use
towncrier to manage changelog
fragments. Add a fragment to changelog.d/ with each PR.
License
Apache-2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zabbix_argus_glue-0.1.0.tar.gz.
File metadata
- Download URL: zabbix_argus_glue-0.1.0.tar.gz
- Upload date:
- Size: 145.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d4bc1a8fa6b744b1a9cd41da18b6faa3a724cdb966100dcce721bdcc0ea834a
|
|
| MD5 |
e5ad94feed12f1ef44c586272378031b
|
|
| BLAKE2b-256 |
0feee4b8ba0104273c152b5d19322735fd08a663ba9d5d30312ea7bfdcaec085
|
File details
Details for the file zabbix_argus_glue-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zabbix_argus_glue-0.1.0-py3-none-any.whl
- Upload date:
- Size: 26.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.05","id":"yarara","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c57f889241ae8cd67da77a036db627119e3f4390c7efe3ecd8430f188fee909
|
|
| MD5 |
34b86c3bbe43c0bce507249099226e62
|
|
| BLAKE2b-256 |
b7406d413eaf116c6070f51bdd6b6d77db66638dfc1b4d54559e7a149e45c00b
|