Set up comprehensive Grafana alerting using both Prometheus metrics and InfluxDB time-series data to monitor your infrastructure from multiple data sources. This tutorial covers configuring data sources, creating alert rules, and setting up notification channels for production monitoring.
Prerequisites
- Grafana server with admin access
- Prometheus server running on port 9090
- InfluxDB server with monitoring database
- SMTP server access for email notifications
- Basic understanding of time-series monitoring
What this solves
Grafana alerting with multiple data sources provides comprehensive monitoring coverage for your infrastructure. By combining Prometheus metrics with InfluxDB time-series data, you can monitor both application performance and system metrics from a single dashboard with unified alerting rules.
Step-by-step configuration
Install Grafana server
First install Grafana on your system if not already present.
sudo apt update
sudo apt install -y software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo dnf install -y wget
sudo tee /etc/yum.repos.d/grafana.repo <
Configure Grafana service
Enable and start the Grafana service with proper permissions.
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
Configure Prometheus data source
Access Grafana at http://your-server:3000 with admin/admin credentials and configure the Prometheus data source.
curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:9090",
"access": "proxy",
"isDefault": true
}'
Configure InfluxDB data source
Add InfluxDB as a secondary data source for time-series monitoring data.
curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "InfluxDB",
"type": "influxdb",
"url": "http://localhost:8086",
"access": "proxy",
"database": "monitoring",
"user": "grafana",
"password": "secure_password"
}'
Create InfluxDB authentication
Set up proper authentication for the InfluxDB connection with restricted permissions.
influx -execute "CREATE USER grafana WITH PASSWORD 'secure_password'"
influx -execute "GRANT READ ON monitoring TO grafana"
influx -execute "SHOW USERS"
Configure notification channels
Set up email notifications for alert delivery using SMTP configuration.
[smtp]
enabled = true
host = smtp.example.com:587
user = alerts@example.com
password = smtp_password
skip_verify = false
from_address = alerts@example.com
from_name = Grafana Alerts
[alerting]
enabled = true
execute_alerts = true
Restart Grafana with new configuration
Apply the SMTP configuration changes by restarting the service.
sudo systemctl restart grafana-server
sudo systemctl status grafana-server
Create Slack notification channel
Add Slack integration for real-time alert notifications to your team channels.
curl -X POST http://admin:admin@localhost:3000/api/alert-notifications \
-H "Content-Type: application/json" \
-d '{
"name": "slack-alerts",
"type": "slack",
"settings": {
"url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
"channel": "#alerts",
"title": "Grafana Alert",
"text": "{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}"
}
}'
Create email notification channel
Configure email notifications as a backup delivery method for critical alerts.
curl -X POST http://admin:admin@localhost:3000/api/alert-notifications \
-H "Content-Type: application/json" \
-d '{
"name": "email-alerts",
"type": "email",
"settings": {
"addresses": "ops-team@example.com;sre-team@example.com",
"subject": "[ALERT] {{ .GroupLabels.alertname }}"
}
}'
Create Prometheus CPU alert rule
Set up a CPU usage alert using Prometheus metrics with proper thresholds.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "cpu-alerts",
"folder": "alerts",
"rules": [
{
"uid": "cpu-high",
"title": "High CPU Usage",
"condition": "A",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "prometheus-uid",
"model": {
"expr": "100 - (avg(irate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"interval": "",
"refId": "A"
}
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "5m",
"annotations": {
"summary": "CPU usage is above 80% for 5 minutes"
},
"labels": {
"severity": "warning"
}
}
]
}
]
}'
Create InfluxDB memory alert rule
Configure a memory usage alert using InfluxDB data for system monitoring.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "memory-alerts",
"folder": "alerts",
"rules": [
{
"uid": "memory-high",
"title": "High Memory Usage",
"condition": "A",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "influxdb-uid",
"model": {
"query": "SELECT mean(\"used_percent\") FROM \"mem\" WHERE time >= now() - 5m GROUP BY time(1m)",
"refId": "A"
}
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "3m",
"annotations": {
"summary": "Memory usage is above 90% for 3 minutes"
},
"labels": {
"severity": "critical"
}
}
]
}
]
}'
Create disk space alert with multi-source data
Combine Prometheus and InfluxDB data for comprehensive disk monitoring alerts.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "disk-alerts",
"folder": "alerts",
"rules": [
{
"uid": "disk-space-low",
"title": "Low Disk Space",
"condition": "C",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "prometheus-uid",
"model": {
"expr": "100 - ((node_filesystem_avail_bytes{mountpoint=\"/\"} * 100) / node_filesystem_size_bytes{mountpoint=\"/\"})",
"refId": "A"
}
},
{
"refId": "B",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "influxdb-uid",
"model": {
"query": "SELECT mean(\"used_percent\") FROM \"disk\" WHERE \"path\" = '/' AND time >= now() - 5m",
"refId": "B"
}
},
{
"refId": "C",
"queryType": "",
"expression": "$A > 85 OR $B > 85",
"conditions": [
{
"evaluator": {
"params": [85],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": ["A"]
},
"reducer": {
"type": "last"
},
"type": "query"
}
]
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "2m",
"annotations": {
"summary": "Disk space usage is above 85% on root filesystem"
},
"labels": {
"severity": "warning"
}
}
]
}
]
}'
Configure alert routing and policies
Set up alert routing based on severity levels and notification preferences.
apiVersion: 1
policies:
- orgId: 1
receiver: default-receiver
group_by:
- alertname
- severity
routes:
- receiver: slack-critical
matchers:
- severity = critical
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
- receiver: email-warning
matchers:
- severity = warning
group_wait: 1m
group_interval: 10m
repeat_interval: 4h
- receiver: slack-info
matchers:
- severity = info
group_wait: 5m
group_interval: 30m
repeat_interval: 12h
Set correct permissions for alerting configuration
Ensure Grafana can read the alerting configuration files with proper ownership.
sudo mkdir -p /etc/grafana/provisioning/alerting
sudo chown -R grafana:grafana /etc/grafana/provisioning
sudo chmod 755 /etc/grafana/provisioning/alerting
sudo chmod 644 /etc/grafana/provisioning/alerting/policies.yaml
Never use chmod 777. It gives every user on the system full access to your files. Instead, use appropriate ownership with chown and minimal permissions like 644 for files and 755 for directories.
Test alert configuration
Validate your alerting setup by testing notification delivery and rule evaluation.
sudo systemctl restart grafana-server
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/test \
-H "Content-Type: application/json" \
-d '{
"expr": "up == 0",
"datasourceUid": "prometheus-uid"
}'
Configure advanced alert features
Set up alert silencing
Configure maintenance windows and alert silencing for planned downtime.
curl -X POST http://admin:admin@localhost:3000/api/alertmanager/grafana/api/v2/silences \
-H "Content-Type: application/json" \
-d '{
"matchers": [
{
"name": "instance",
"value": "203.0.113.10:9100",
"isRegex": false
}
],
"startsAt": "2024-01-01T02:00:00.000Z",
"endsAt": "2024-01-01T06:00:00.000Z",
"createdBy": "admin",
"comment": "Maintenance window for server updates"
}'
Configure alert annotations
Add detailed annotations to alerts for better troubleshooting context.
apiVersion: 1
groups:
- name: detailed-alerts
folder: monitoring
rules:
- uid: service-down
title: Service Down Alert
condition: A
data:
- refId: A
queryType: ''
relativeTimeRange:
from: 300
to: 0
datasourceUid: prometheus-uid
model:
expr: up{job="node-exporter"} == 0
annotations:
summary: "Service {{ $labels.instance }} is down"
description: "The service on {{ $labels.instance }} has been down for more than 5 minutes. Check the service status and logs."
runbook_url: "https://wiki.example.com/runbooks/service-down"
dashboard_url: "https://grafana.example.com/d/node-exporter/node-exporter-full"
labels:
team: infrastructure
service: node-exporter
Verify your setup
sudo systemctl status grafana-server
curl -s http://localhost:3000/api/health | jq
curl -s http://admin:admin@localhost:3000/api/datasources | jq '.[].name'
curl -s http://admin:admin@localhost:3000/api/alert-notifications | jq '.[].name'
curl -s http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules | jq '.groups[].name'
Check Prometheus metrics collection:
curl -s "http://localhost:9090/api/v1/query?query=up" | jq '.data.result[] | .metric.instance'
curl -s "http://localhost:9090/api/v1/targets" | jq '.data.activeTargets[] | select(.health=="up") | .labels.instance'
Verify InfluxDB connectivity and data:
influx -execute "SHOW DATABASES"
influx -database monitoring -execute "SHOW MEASUREMENTS LIMIT 5"
influx -database monitoring -execute "SELECT * FROM cpu WHERE time > now() - 1h LIMIT 3"
Common issues
Symptom
Cause
Fix
Data source connection failed
Incorrect URL or authentication
Verify service URLs and credentials: curl http://localhost:9090/metrics
Alert rules not evaluating
Invalid query syntax or missing data
Test queries in Explore tab: curl -X POST /api/ruler/grafana/api/v1/rules/test
Notifications not delivered
SMTP misconfiguration or wrong webhook URL
Check logs: sudo journalctl -u grafana-server -f and test SMTP settings
Permission denied on config files
Wrong ownership or permissions
Fix ownership: sudo chown -R grafana:grafana /etc/grafana/
High memory usage in Grafana
Too many concurrent queries
Limit concurrent queries in /etc/grafana/grafana.ini: max_concurrent_queries = 20
Next steps
- Configure advanced Grafana dashboards with Prometheus integration
- Set up OpenTelemetry custom instrumentation with Prometheus
- Integrate MinIO with Prometheus monitoring for storage metrics
- Set up Grafana dashboard provisioning and automation
- Configure Prometheus Alertmanager with custom webhook integrations
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'
BLUE='\033[0;34m'
NC='\033[0m'
# Global variables
PKG_MGR=""
PKG_INSTALL=""
DISTRO=""
GRAFANA_CONFIG=""
PROMETHEUS_CONFIG=""
INFLUXDB_CONFIG=""
# Cleanup function
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop grafana-server prometheus influxdb 2>/dev/null || true
systemctl disable grafana-server prometheus influxdb 2>/dev/null || true
fi
exit $exit_code
}
trap cleanup ERR
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -h, --help Show this help message"
echo " --influxdb-password Password for InfluxDB admin user (default: randomly generated)"
echo " --grafana-port Grafana port (default: 3000)"
echo " --prometheus-port Prometheus port (default: 9090)"
echo " --influxdb-port InfluxDB port (default: 8086)"
exit 1
}
# Parse arguments
INFLUXDB_PASSWORD=""
GRAFANA_PORT="3000"
PROMETHEUS_PORT="9090"
INFLUXDB_PORT="8086"
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
;;
--influxdb-password)
INFLUXDB_PASSWORD="$2"
shift 2
;;
--grafana-port)
GRAFANA_PORT="$2"
shift 2
;;
--prometheus-port)
PROMETHEUS_PORT="$2"
shift 2
;;
--influxdb-port)
INFLUXDB_PORT="$2"
shift 2
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
usage
;;
esac
done
# Generate random password if not provided
if [ -z "$INFLUXDB_PASSWORD" ]; then
INFLUXDB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-16)
fi
# Check prerequisites
check_prerequisites() {
echo -e "${BLUE}[1/8] Checking prerequisites...${NC}"
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
if ! command -v wget &> /dev/null; then
echo -e "${YELLOW}wget not found, will install it${NC}"
fi
if ! command -v openssl &> /dev/null; then
echo -e "${RED}openssl is required but not installed${NC}"
exit 1
fi
}
# Detect distribution
detect_distro() {
echo -e "${BLUE}[2/8] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO="$ID"
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
}
# Install Grafana
install_grafana() {
echo -e "${BLUE}[3/8] Installing Grafana...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
apt update
$PKG_INSTALL software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" > /etc/apt/sources.list.d/grafana.list
apt update
$PKG_INSTALL grafana
else
$PKG_INSTALL wget
cat > /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
$PKG_INSTALL grafana
fi
# Configure Grafana
sed -i "s/;http_port = 3000/http_port = $GRAFANA_PORT/" "$GRAFANA_CONFIG"
systemctl enable grafana-server
systemctl start grafana-server
}
# Install Prometheus
install_prometheus() {
echo -e "${BLUE}[4/8] Installing Prometheus...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL prometheus
else
$PKG_INSTALL prometheus2
PROMETHEUS_CONFIG="/etc/prometheus2"
fi
# Configure Prometheus
mkdir -p "$PROMETHEUS_CONFIG"
cat > "$PROMETHEUS_CONFIG/prometheus.yml" << EOF
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:$PROMETHEUS_PORT']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
EOF
chown -R prometheus:prometheus "$PROMETHEUS_CONFIG" 2>/dev/null || true
chmod 644 "$PROMETHEUS_CONFIG/prometheus.yml"
systemctl enable prometheus
systemctl start prometheus
}
# Install InfluxDB
install_influxdb() {
echo -e "${BLUE}[5/8] Installing InfluxDB...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
wget -qO- https://repos.influxdata.com/influxdb.key | apt-key add -
echo "deb https://repos.influxdata.com/debian stable main" > /etc/apt/sources.list.d/influxdb.list
apt update
$PKG_INSTALL influxdb
else
cat > /etc/yum.repos.d/influxdb.repo << EOF
[influxdb]
name = InfluxDB Repository - RHEL
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF
$PKG_INSTALL influxdb
fi
# Configure InfluxDB
mkdir -p "$INFLUXDB_CONFIG"
cat > "$INFLUXDB_CONFIG/influxdb.conf" << EOF
[meta]
dir = "/var/lib/influxdb/meta"
[data]
dir = "/var/lib/influxdb/data"
engine = "tsm1"
wal-dir = "/var/lib/influxdb/wal"
[http]
enabled = true
bind-address = ":$INFLUXDB_PORT"
EOF
chown -R influxdb:influxdb "$INFLUXDB_CONFIG" 2>/dev/null || true
chown -R influxdb:influxdb /var/lib/influxdb 2>/dev/null || true
chmod 644 "$INFLUXDB_CONFIG/influxdb.conf"
systemctl enable influxdb
systemctl start influxdb
}
# Configure data sources
configure_datasources() {
echo -e "${BLUE}[6/8] Configuring Grafana data sources...${NC}"
# Wait for services to be ready
sleep 5
# Configure Prometheus data source
curl -s -X POST \
http://admin:admin@localhost:$GRAFANA_PORT/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:'$PROMETHEUS_PORT'",
"access": "proxy",
"isDefault": true
}' || echo -e "${YELLOW}Prometheus datasource may already exist${NC}"
# Configure InfluxDB data source
curl -s -X POST \
http://admin:admin@localhost:$GRAFANA_PORT/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "InfluxDB",
"type": "influxdb",
"url": "http://localhost:'$INFLUXDB_PORT'",
"access": "proxy",
"database": "monitoring"
}' || echo -e "${YELLOW}InfluxDB datasource may already exist${NC}"
}
# Configure firewall
configure_firewall() {
echo -e "${BLUE}[7/8] Configuring firewall...${NC}"
if command -v ufw &> /dev/null; then
ufw allow $GRAFANA_PORT/tcp
ufw allow $PROMETHEUS_PORT/tcp
ufw allow $INFLUXDB_PORT/tcp
elif command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=$GRAFANA_PORT/tcp
firewall-cmd --permanent --add-port=$PROMETHEUS_PORT/tcp
firewall-cmd --permanent --add-port=$INFLUXDB_PORT/tcp
firewall-cmd --reload
fi
}
# Verify installation
verify_installation() {
echo -e "${BLUE}[8/8] Verifying installation...${NC}"
# Check services
for service in grafana-server prometheus influxdb; do
if systemctl is-active --quiet $service; then
echo -e "${GREEN}✓ $service is running${NC}"
else
echo -e "${RED}✗ $service is not running${NC}"
exit 1
fi
done
# Check ports
for port in $GRAFANA_PORT $PROMETHEUS_PORT $INFLUXDB_PORT; do
if ss -tlnp | grep -q ":$port "; then
echo -e "${GREEN}✓ Port $port is open${NC}"
else
echo -e "${RED}✗ Port $port is not accessible${NC}"
exit 1
fi
done
}
# Main execution
main() {
check_prerequisites
detect_distro
install_grafana
install_prometheus
install_influxdb
configure_datasources
configure_firewall
verify_installation
echo -e "${GREEN}Installation completed successfully!${NC}"
echo -e "${BLUE}Access Grafana at: http://localhost:$GRAFANA_PORT${NC}"
echo -e "${BLUE}Default login: admin/admin${NC}"
echo -e "${BLUE}Prometheus: http://localhost:$PROMETHEUS_PORT${NC}"
echo -e "${BLUE}InfluxDB: http://localhost:$INFLUXDB_PORT${NC}"
echo -e "${YELLOW}InfluxDB admin password: $INFLUXDB_PASSWORD${NC}"
}
main "$@"
Review the script before running. Execute with: bash install.sh