Set up advanced Zabbix alerting with custom webhooks for Slack and Microsoft Teams, create notification scripts and templates, and integrate with external systems through API automation.
Prerequisites
- Zabbix 7 server installed and running
- Web interface access with admin privileges
- Slack or Teams workspace for webhook testing
What this solves
Zabbix's default email alerts work for basic monitoring, but production environments need richer notifications and integrations. This tutorial shows you how to configure custom webhooks for Slack and Microsoft Teams, create notification scripts with templates, set up escalation rules, and integrate with external systems using API webhooks.
Step-by-step configuration
Create webhook media type for Slack
Configure Slack webhook integration to send formatted alerts to your team channels.
First, create a Slack webhook URL in your Slack workspace. Go to Your Apps > Incoming Webhooks and create a new webhook for your target channel.
In Zabbix web interface, navigate to Administration > Media types and click Create media type:
Name: Slack
Type: Webhook
Script name: slack
Parameters:
HTTPProxy: {ALERT.MESSAGE}
Message: {ALERT.MESSAGE}
Subject: {ALERT.SUBJECT}
To: {ALERT.SENDTO}
URL: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
Add this JavaScript code in the Script field:
try {
var params = JSON.parse(value),
req = new HttpRequest(),
payload = {},
resp;
req.addHeader('Content-Type: application/json');
payload = {
'channel': params.To,
'username': 'Zabbix',
'text': params.Subject,
'attachments': [{
'color': params.Subject.indexOf('PROBLEM') !== -1 ? 'danger' : 'good',
'text': params.Message
}]
};
resp = req.post(params.URL, JSON.stringify(payload));
if (req.getStatus() !== 200) {
throw 'Response code: ' + req.getStatus();
}
return 'OK';
} catch (error) {
Zabbix.log(4, 'Slack webhook failed: ' + error);
throw 'Slack webhook failed: ' + error;
}
Create webhook media type for Microsoft Teams
Set up Microsoft Teams integration for alerts in your Teams channels.
Create an incoming webhook in Microsoft Teams by going to your team channel > Connectors > Incoming Webhook.
In Zabbix, create another media type:
Name: Microsoft Teams
Type: Webhook
Script name: teams
Parameters:
Message: {ALERT.MESSAGE}
Subject: {ALERT.SUBJECT}
URL: https://outlook.office.com/webhook/YOUR/TEAMS/WEBHOOK
Add this JavaScript code for Teams formatting:
try {
var params = JSON.parse(value),
req = new HttpRequest(),
payload = {},
resp;
req.addHeader('Content-Type: application/json');
var color = params.Subject.indexOf('PROBLEM') !== -1 ? 'FF0000' : '00FF00';
payload = {
'@type': 'MessageCard',
'@context': 'https://schema.org/extensions',
'summary': params.Subject,
'themeColor': color,
'sections': [{
'activityTitle': params.Subject,
'activityText': params.Message,
'markdown': true
}]
};
resp = req.post(params.URL, JSON.stringify(payload));
if (req.getStatus() !== 200) {
throw 'Response code: ' + req.getStatus();
}
return 'OK';
} catch (error) {
Zabbix.log(4, 'Teams webhook failed: ' + error);
throw 'Teams webhook failed: ' + error;
}
Create custom notification script
Set up a custom shell script for advanced notification processing and external system integration.
Create the alertscripts directory and custom script:
sudo mkdir -p /usr/lib/zabbix/alertscripts
sudo chown zabbix:zabbix /usr/lib/zabbix/alertscripts
sudo chmod 755 /usr/lib/zabbix/alertscripts
Create a custom notification script:
#!/bin/bash
Custom Zabbix alert script
Parameters: $1=TO, $2=SUBJECT, $3=MESSAGE
TO="$1"
SUBJECT="$2"
MESSAGE="$3"
Log the alert
echo "$(date): Alert sent to $TO - $SUBJECT" >> /var/log/zabbix/custom-alerts.log
Parse alert severity from subject
if [[ "$SUBJECT" == "DISASTER" ]]; then
SEVERITY="critical"
COLOR="#FF0000"
elif [[ "$SUBJECT" == "HIGH" ]]; then
SEVERITY="high"
COLOR="#FF8C00"
elif [[ "$SUBJECT" == "AVERAGE" ]]; then
SEVERITY="medium"
COLOR="#FFA500"
else
SEVERITY="low"
COLOR="#00FF00"
fi
Send to external API
curl -X POST "https://api.example.com/alerts" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-API-TOKEN" \
-d "{
\"severity\": \"$SEVERITY\",
\"subject\": \"$SUBJECT\",
\"message\": \"$MESSAGE\",
\"timestamp\": \"$(date -Iseconds)\",
\"source\": \"zabbix\"
}"
Send SMS for critical alerts
if [[ "$SEVERITY" == "critical" ]]; then
curl -X POST "https://api.sms-provider.com/send" \
-d "to=$TO" \
-d "message=CRITICAL: $SUBJECT" \
-d "token=YOUR-SMS-TOKEN"
fi
exit 0
Make the script executable and set proper ownership:
sudo chmod +x /usr/lib/zabbix/alertscripts/custom-alert.sh
sudo chown zabbix:zabbix /usr/lib/zabbix/alertscripts/custom-alert.sh
Configure Zabbix server for custom scripts
Update Zabbix server configuration to enable custom alertscripts.
Edit the Zabbix server configuration:
# Uncomment and set the alertscripts path
AlertScriptsPath=/usr/lib/zabbix/alertscripts
Enable external scripts
ExternalScripts=/usr/lib/zabbix/externalscripts
Set timeout for scripts
Timeout=30
Create log directory for custom alerts:
sudo mkdir -p /var/log/zabbix
sudo chown zabbix:zabbix /var/log/zabbix
sudo chmod 755 /var/log/zabbix
Restart Zabbix server to apply changes:
sudo systemctl restart zabbix-server
sudo systemctl status zabbix-server
Create script media type
Add the custom script as a media type in Zabbix web interface.
Navigate to Administration > Media types and create a new media type:
Name: Custom Alert Script
Type: Script
Script name: custom-alert.sh
Script parameters:
{ALERT.SENDTO}
{ALERT.SUBJECT}
{ALERT.MESSAGE}
Enable the media type and test it with the Test button.
Configure user media for notifications
Assign notification methods to Zabbix users for different alert types.
Go to Administration > Users, select a user, and click on Media tab. Add media for each notification type:
For Slack:
Type: Slack
Send to: #alerts-channel
When active: 1-7,00:00-24:00
Use if severity: All selected
For Teams:
Type: Microsoft Teams
Send to: teams-webhook
When active: 1-7,08:00-18:00
Use if severity: High, Disaster
For Custom Script:
Type: Custom Alert Script
Send to: +1234567890
When active: 1-7,00:00-24:00
Use if severity: Disaster
Create alert actions with escalation
Set up automated alert actions with escalation rules for different scenarios.
Navigate to Configuration > Actions > Trigger actions and create a new action:
Name: Critical System Alerts
Conditions:
A: Trigger severity >= High
B: Host group = Production Servers
Operations:
Step 1 (0-0): Send message to Slack
Step 2 (1-3): Send message to Teams (escalation after 5 minutes, repeat 3 times)
Step 3 (4-0): Send message via Custom Script (escalation after 15 minutes)
Recovery operations:
Send recovery message to all media types
Update operations:
Send update message if problem persists > 1 hour
Configure API webhook integration
Create webhook integration with external monitoring systems and ticket systems.
Create an API integration script:
#!/bin/bash
API webhook integration script
TO="$1"
SUBJECT="$2"
MESSAGE="$3"
Extract host and item from message
HOST=$(echo "$MESSAGE" | grep -oP 'Host: \K[^\n]*' | head -1)
ITEM=$(echo "$MESSAGE" | grep -oP 'Item: \K[^\n]*' | head -1)
VALUE=$(echo "$MESSAGE" | grep -oP 'Value: \K[^\n]*' | head-1)
Create ticket in external system
if [[ "$SUBJECT" == "PROBLEM" ]]; then
TICKET_ID=$(curl -s -X POST "https://api.ticketsystem.com/tickets" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer API-TOKEN" \
-d "{
\"title\": \"$SUBJECT\",
\"description\": \"$MESSAGE\",
\"priority\": \"high\",
\"tags\": [\"monitoring\", \"zabbix\"]
}" | jq -r '.id')
echo "Created ticket: $TICKET_ID" >> /var/log/zabbix/api-webhooks.log
fi
Send to monitoring aggregation service
curl -X POST "https://api.monitoring-hub.com/events" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR-API-KEY" \
-d "{
\"source\": \"zabbix\",
\"host\": \"$HOST\",
\"item\": \"$ITEM\",
\"value\": \"$VALUE\",
\"subject\": \"$SUBJECT\",
\"message\": \"$MESSAGE\",
\"timestamp\": $(date +%s)
}"
exit 0
Make the API webhook script executable:
sudo chmod +x /usr/lib/zabbix/alertscripts/api-webhook.sh
sudo chown zabbix:zabbix /usr/lib/zabbix/alertscripts/api-webhook.sh
Create notification templates
Customize alert message templates for different media types and scenarios.
In each action, configure custom message templates. For Slack notifications:
Subject:
🚨 {TRIGGER.STATUS}: {TRIGGER.NAME}
Message:
Host: {HOST.NAME}
Item: {ITEM.NAME}
Value: {ITEM.LASTVALUE}
Severity: {TRIGGER.SEVERITY}
Time: {EVENT.DATE} {EVENT.TIME}
Age: {EVENT.AGE}
Description: {TRIGGER.DESCRIPTION}
Event ID: {EVENT.ID}
For Teams notifications:
Subject:
{TRIGGER.STATUS}: {HOST.NAME} - {TRIGGER.NAME}
Message:
Alert Details
Host: {HOST.NAME}
Trigger: {TRIGGER.NAME}
Severity: {TRIGGER.SEVERITY}
Status: {TRIGGER.STATUS}
Value: {ITEM.LASTVALUE}
Time: {EVENT.DATE} {EVENT.TIME}
Description: {TRIGGER.DESCRIPTION}
Event ID: {EVENT.ID}
Host IP: {HOST.IP}
Configure global notification settings
Set up global notification policies and maintenance handling.
Navigate to Administration > General > Other and configure:
Frontend messaging: Enabled
Message timeout: 90 seconds
Max count of elements to show in problems widget: 100
Maintenance settings:
Show suppressed problems: Disabled
Show timeline of events in maintenance: Enabled
Configure notification policies in each action for maintenance periods:
Conditions:
Maintenance status = Not in maintenance
Pause operations for suppressed problems: Enabled
Notify about cancelled escalations: Enabled
Verify your setup
Test your webhook and script integrations to ensure they work correctly.
# Test custom alert script manually
sudo -u zabbix /usr/lib/zabbix/alertscripts/custom-alert.sh "+1234567890" "TEST: Alert test" "This is a test message"
Check Zabbix server logs for webhook activity
sudo tail -f /var/log/zabbix/zabbix_server.log | grep -i webhook
Check custom alert logs
sudo tail -f /var/log/zabbix/custom-alerts.log
Test webhook media types from Zabbix interface
Go to Administration > Media types > Select media type > Test
Verify alert actions are active
sudo zabbix_server -R config_cache_reload
Advanced webhook configurations
Configure PagerDuty integration
Set up PagerDuty webhook for incident management integration.
Create a PagerDuty media type with this webhook script:
try {
var params = JSON.parse(value),
req = new HttpRequest(),
payload = {},
resp;
req.addHeader('Content-Type: application/json');
var event_action = params.Subject.indexOf('PROBLEM') !== -1 ? 'trigger' : 'resolve';
payload = {
'routing_key': params.IntegrationKey,
'event_action': event_action,
'dedup_key': 'zabbix-' + params.EventID,
'payload': {
'summary': params.Subject,
'source': params.Host,
'severity': params.Subject.indexOf('DISASTER') !== -1 ? 'critical' : 'warning',
'custom_details': {
'message': params.Message,
'event_id': params.EventID,
'host': params.Host
}
}
};
resp = req.post('https://events.pagerduty.com/v2/enqueue', JSON.stringify(payload));
if (req.getStatus() !== 202) {
throw 'Response code: ' + req.getStatus();
}
return 'OK';
} catch (error) {
Zabbix.log(4, 'PagerDuty webhook failed: ' + error);
throw 'PagerDuty webhook failed: ' + error;
}
Create Jira ticket integration
Automatically create Jira tickets for critical alerts using API webhooks.
Create a Jira integration script:
#!/bin/bash
TO="$1"
SUBJECT="$2"
MESSAGE="$3"
Jira API configuration
JIRA_URL="https://yourcompany.atlassian.net"
JIRA_USER="monitoring@example.com"
JIRA_TOKEN="your-api-token"
JIRA_PROJECT="MON"
Create ticket only for PROBLEM events
if [[ "$SUBJECT" == "PROBLEM" ]]; then
# Extract event details
HOST=$(echo "$MESSAGE" | grep -oP 'Host: \K[^\n]*')
SEVERITY=$(echo "$SUBJECT" | grep -oP '(DISASTER|HIGH|AVERAGE|WARNING|INFORMATION)')
# Set priority based on severity
case "$SEVERITY" in
"DISASTER") PRIORITY="Highest" ;;
"HIGH") PRIORITY="High" ;;
"AVERAGE") PRIORITY="Medium" ;;
*) PRIORITY="Low" ;;
esac
# Create Jira ticket
TICKET_RESPONSE=$(curl -s -X POST \
"$JIRA_URL/rest/api/3/issue" \
-H "Content-Type: application/json" \
-u "$JIRA_USER:$JIRA_TOKEN" \
-d "{
\"fields\": {
\"project\": {\"key\": \"$JIRA_PROJECT\"},
\"summary\": \"$SUBJECT\",
\"description\": \"$MESSAGE\",
\"issuetype\": {\"name\": \"Bug\"},
\"priority\": {\"name\": \"$PRIORITY\"},
\"labels\": [\"monitoring\", \"zabbix\", \"$HOST\"]
}
}")
TICKET_KEY=$(echo "$TICKET_RESPONSE" | jq -r '.key')
echo "$(date): Created Jira ticket $TICKET_KEY for $SUBJECT" >> /var/log/zabbix/jira-integration.log
fi
exit 0
Make the script executable and configure as a media type:
sudo chmod +x /usr/lib/zabbix/alertscripts/jira-integration.sh
sudo chown zabbix:zabbix /usr/lib/zabbix/alertscripts/jira-integration.sh
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Webhook returns HTTP 400 | Invalid JSON payload format | Validate JSON syntax and required fields in webhook script |
| Custom script not executing | Permission or path issues | Check script permissions (755) and AlertScriptsPath in zabbix_server.conf |
| Slack notifications not formatting | Incorrect Slack webhook URL | Verify webhook URL and test with curl manually |
| Escalations not triggering | Action conditions too restrictive | Review action conditions and trigger severity matching |
| API calls failing | Authentication or timeout issues | Check API tokens, increase Timeout in zabbix_server.conf |
| Teams cards not displaying | MessageCard format errors | Validate MessageCard schema and test payload |
Next steps
- Configure Zabbix 7 email and SMS alerting with escalation rules
- Configure Zabbix 7 API automation with Python scripts
- Set up Zabbix 7 distributed monitoring with proxy servers
- Configure custom Zabbix dashboards with Grafana integration
- Implement Zabbix high availability clustering for enterprise monitoring
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default values
SLACK_WEBHOOK_URL=""
TEAMS_WEBHOOK_URL=""
usage() {
echo "Usage: $0 [--slack-webhook URL] [--teams-webhook URL]"
echo " --slack-webhook URL Optional Slack webhook URL"
echo " --teams-webhook URL Optional Teams webhook URL"
exit 1
}
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
cleanup() {
log_error "Installation failed. Cleaning up..."
systemctl restart zabbix-server 2>/dev/null || true
}
trap cleanup ERR
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--slack-webhook)
SLACK_WEBHOOK_URL="$2"
shift 2
;;
--teams-webhook)
TEAMS_WEBHOOK_URL="$2"
shift 2
;;
-h|--help)
usage
;;
*)
log_error "Unknown option: $1"
usage
;;
esac
done
# Check if running as root
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
ZABBIX_CONF_DIR="/etc/zabbix"
;;
almalinux|rocky|centos|rhel|ol)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
ZABBIX_CONF_DIR="/etc/zabbix"
;;
fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
ZABBIX_CONF_DIR="/etc/zabbix"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
ZABBIX_CONF_DIR="/etc/zabbix"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
else
log_error "Cannot detect distribution"
exit 1
fi
log_info "Detected distribution: $ID"
echo "[1/7] Checking Zabbix installation..."
if ! systemctl is-active --quiet zabbix-server; then
log_error "Zabbix server is not running. Please install and configure Zabbix first."
exit 1
fi
echo "[2/7] Creating alertscripts directory..."
mkdir -p /usr/lib/zabbix/alertscripts
chown zabbix:zabbix /usr/lib/zabbix/alertscripts
chmod 755 /usr/lib/zabbix/alertscripts
mkdir -p /var/log/zabbix
chown zabbix:zabbix /var/log/zabbix
chmod 755 /var/log/zabbix
echo "[3/7] Creating custom notification script..."
cat > /usr/lib/zabbix/alertscripts/custom-alert.sh << 'EOF'
#!/bin/bash
# Custom Zabbix alert script
# Parameters: $1=TO, $2=SUBJECT, $3=MESSAGE
TO="$1"
SUBJECT="$2"
MESSAGE="$3"
# Log the alert
echo "$(date): Alert sent to $TO - $SUBJECT" >> /var/log/zabbix/custom-alerts.log
# Parse alert severity from subject
if [[ "$SUBJECT" == *"DISASTER"* ]]; then
SEVERITY="critical"
COLOR="#FF0000"
elif [[ "$SUBJECT" == *"HIGH"* ]]; then
SEVERITY="high"
COLOR="#FF8C00"
elif [[ "$SUBJECT" == *"AVERAGE"* ]]; then
SEVERITY="medium"
COLOR="#FFA500"
else
SEVERITY="low"
COLOR="#00FF00"
fi
# Send to external webhook (example)
if [[ "$TO" == "webhook:"* ]]; then
WEBHOOK_URL="${TO#webhook:}"
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"severity\":\"$SEVERITY\",\"subject\":\"$SUBJECT\",\"message\":\"$MESSAGE\"}" \
>> /var/log/zabbix/custom-alerts.log 2>&1
else
# Default email sending
echo "$MESSAGE" | mail -s "$SUBJECT" "$TO" 2>> /var/log/zabbix/custom-alerts.log
fi
exit 0
EOF
chown zabbix:zabbix /usr/lib/zabbix/alertscripts/custom-alert.sh
chmod 755 /usr/lib/zabbix/alertscripts/custom-alert.sh
echo "[4/7] Creating Slack webhook script..."
cat > /usr/lib/zabbix/alertscripts/slack-webhook.js << 'EOF'
try {
var params = JSON.parse(value),
req = new HttpRequest(),
payload = {},
resp;
req.addHeader('Content-Type: application/json');
payload = {
'channel': params.To,
'username': 'Zabbix',
'text': params.Subject,
'attachments': [{
'color': params.Subject.indexOf('PROBLEM') !== -1 ? 'danger' : 'good',
'text': params.Message
}]
};
resp = req.post(params.URL, JSON.stringify(payload));
if (req.getStatus() !== 200) {
throw 'Response code: ' + req.getStatus();
}
return 'OK';
} catch (error) {
Zabbix.log(4, 'Slack webhook failed: ' + error);
throw 'Slack webhook failed: ' + error;
}
EOF
chown zabbix:zabbix /usr/lib/zabbix/alertscripts/slack-webhook.js
chmod 644 /usr/lib/zabbix/alertscripts/slack-webhook.js
echo "[5/7] Creating Teams webhook script..."
cat > /usr/lib/zabbix/alertscripts/teams-webhook.js << 'EOF'
try {
var params = JSON.parse(value),
req = new HttpRequest(),
payload = {},
resp;
req.addHeader('Content-Type: application/json');
var color = params.Subject.indexOf('PROBLEM') !== -1 ? 'FF0000' : '00FF00';
payload = {
'@type': 'MessageCard',
'@context': 'https://schema.org/extensions',
'summary': params.Subject,
'themeColor': color,
'sections': [{
'activityTitle': params.Subject,
'activityText': params.Message,
'markdown': true
}]
};
resp = req.post(params.URL, JSON.stringify(payload));
if (req.getStatus() !== 200) {
throw 'Response code: ' + req.getStatus();
}
return 'OK';
} catch (error) {
Zabbix.log(4, 'Teams webhook failed: ' + error);
throw 'Teams webhook failed: ' + error;
}
EOF
chown zabbix:zabbix /usr/lib/zabbix/alertscripts/teams-webhook.js
chmod 644 /usr/lib/zabbix/alertscripts/teams-webhook.js
echo "[6/7] Configuring Zabbix server for custom alerts..."
# Update zabbix_server.conf to include AlertScriptsPath
if ! grep -q "AlertScriptsPath=/usr/lib/zabbix/alertscripts" "$ZABBIX_CONF_DIR/zabbix_server.conf"; then
echo "AlertScriptsPath=/usr/lib/zabbix/alertscripts" >> "$ZABBIX_CONF_DIR/zabbix_server.conf"
fi
# Set SELinux context if SELinux is enabled
if command -v semanage >/dev/null 2>&1 && getenforce 2>/dev/null | grep -q "Enforcing"; then
log_info "Setting SELinux contexts for alertscripts..."
semanage fcontext -a -t zabbix_exec_t "/usr/lib/zabbix/alertscripts(/.*)?" 2>/dev/null || true
restorecon -R /usr/lib/zabbix/alertscripts 2>/dev/null || true
fi
echo "[7/7] Restarting Zabbix server..."
systemctl restart zabbix-server
# Verification
echo "Verifying installation..."
sleep 5
if systemctl is-active --quiet zabbix-server; then
log_info "Zabbix server is running"
else
log_error "Zabbix server failed to start"
exit 1
fi
if [ -f /usr/lib/zabbix/alertscripts/custom-alert.sh ] && [ -x /usr/lib/zabbix/alertscripts/custom-alert.sh ]; then
log_info "Custom alert script installed successfully"
else
log_error "Custom alert script installation failed"
exit 1
fi
echo ""
log_info "Zabbix custom alerting configuration completed successfully!"
echo ""
echo "Next steps:"
echo "1. Log into Zabbix web interface"
echo "2. Go to Administration > Media types"
echo "3. Create media types using the installed webhook scripts"
if [ -n "$SLACK_WEBHOOK_URL" ]; then
echo " - Slack webhook URL: $SLACK_WEBHOOK_URL"
fi
if [ -n "$TEAMS_WEBHOOK_URL" ]; then
echo " - Teams webhook URL: $TEAMS_WEBHOOK_URL"
fi
echo "4. Configure user media and action triggers"
echo ""
echo "Scripts installed in: /usr/lib/zabbix/alertscripts/"
echo "Logs available in: /var/log/zabbix/custom-alerts.log"
Review the script before running. Execute with: bash install.sh