Veeam v13: Monitoring Integration with External Tools

Veeam v13 Grafana Splunk Zabbix Teams Slack PowerShell Monitoring

Veeam v13 Series | Component: VBR v13, Veeam ONE v13 | Audience: Enterprise Architects, MSP Engineers, Security and Compliance Teams

Veeam ONE is a solid monitoring layer for people who live in the Veeam console. But most operations teams do not. NOC engineers work in Grafana dashboards. Security teams work in Splunk. Infrastructure teams have Zabbix or a similar platform watching everything. And when a backup job fails at 3am, the fastest path to an engineer is usually a Teams or Slack message, not a Veeam ONE email that sits unread until morning.

This article covers how to push Veeam data outward into the tools your team already uses. Grafana dashboards via Prometheus, Splunk ingestion via HTTP Event Collector, Zabbix external check integration, and Teams/Slack webhook alerts from Veeam ONE alarm actions.


1. Integration Architecture Overview

There are three ways to get data out of Veeam and into external tools. The right choice depends on what you need and what your external tool supports.

MethodBest ForData TypeLatency
Veeam ONE alarm script actionReal time alert delivery to chat tools, ticketing systemsAlarm events onlyNear real time (seconds after alarm fires)
SNMP traps from Veeam ONENetwork management platforms (Zabbix, PRTG, SolarWinds)Alarm events onlyNear real time
PowerShell polling via VBR APIGrafana, Splunk, custom dashboards needing metricsJob status, repository capacity, session data, any VBR metricPolling interval (typically 1 to 5 minutes)

For real time alerting, use the alarm script action or SNMP. For metrics and dashboards, use PowerShell polling. For security event ingestion, use PowerShell polling into Splunk or a syslog forwarder. Most mature environments use all three.


2. Teams and Slack Webhook Integration

This is the fastest win and the one most teams implement first. Veeam ONE fires an alarm, a PowerShell script runs, and a formatted message lands in your Teams or Slack channel within seconds.

Setup: Create an Incoming Webhook

In Teams: go to the channel you want alerts delivered to, click the three dot menu, select Connectors, search for Incoming Webhook, configure it, and copy the webhook URL.

In Slack: go to api.slack.com/apps, create a new app, enable Incoming Webhooks, add a webhook to your workspace, select the target channel, and copy the webhook URL.

Veeam ONE Alarm Script: Teams

Send-TeamsAlert.ps1 (called by Veeam ONE alarm script action)
# Parameters passed by Veeam ONE:
# %1 = Alarm name
# %2 = Affected object (node) name
# %3 = Alarm summary
# %4 = Date/time triggered
# %5 = Current status
# %6 = Previous status

param(
    [string]$AlarmName,
    [string]$NodeName,
    [string]$Summary,
    [string]$TriggeredAt,
    [string]$Status,
    [string]$PrevStatus
)

$webhookUrl = "https://your-org.webhook.office.com/webhookb2/YOUR-WEBHOOK-URL"

$color = switch ($Status) {
    "Error"   { "FF0000" }
    "Warning" { "FFA500" }
    "Resolved"{ "00AA00" }
    default   { "808080" }
}

$body = @{
    "@type"      = "MessageCard"
    "@context"   = "https://schema.org/extensions"
    "themeColor" = $color
    "summary"    = "Veeam Alert: $AlarmName"
    "sections"   = @(
        @{
            "activityTitle"    = "Veeam ONE Alert: $Status"
            "activitySubtitle" = $AlarmName
            "facts"            = @(
                @{ "name" = "Object";    "value" = $NodeName }
                @{ "name" = "Summary";   "value" = $Summary }
                @{ "name" = "Status";    "value" = "$PrevStatus to $Status" }
                @{ "name" = "Triggered"; "value" = $TriggeredAt }
            )
        }
    )
} | ConvertTo-Json -Depth 10

Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $body -ContentType "application/json"

The MessageCard format used above is the legacy Teams connector format. It works across all current Microsoft 365 tenants and does not require an app registration. Microsoft has announced future deprecation of the Incoming Webhook connector in Teams in favor of the Power Automate based workflow connector, but as of early 2026 MessageCard webhooks remain functional. If your tenant has already disabled legacy connectors, use a Power Automate flow with an HTTP trigger as the webhook endpoint instead.

Veeam ONE Alarm Script: Slack

Send-SlackAlert.ps1 (called by Veeam ONE alarm script action)
param(
    [string]$AlarmName,
    [string]$NodeName,
    [string]$Summary,
    [string]$TriggeredAt,
    [string]$Status,
    [string]$PrevStatus
)

$webhookUrl = "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"

$emoji = switch ($Status) {
    "Error"    { ":red_circle:" }
    "Warning"  { ":warning:" }
    "Resolved" { ":white_check_mark:" }
    default    { ":grey_question:" }
}

$body = @{
    text = "$emoji *Veeam ONE Alert: $Status*"
    blocks = @(
        @{
            type = "section"
            text = @{
                type = "mrkdwn"
                text = "$emoji *$AlarmName*`n*Object:* $NodeName`n*Status:* $PrevStatus to $Status`n*Summary:* $Summary`n*Triggered:* $TriggeredAt"
            }
        }
    )
} | ConvertTo-Json -Depth 10

Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $body -ContentType "application/json"

Registering the Script in Veeam ONE

Scripts must be wrapped in a .cmd launcher because Veeam ONE requires a direct executable path. Create a wrapper:

veeam-teams-alert.cmd (wrapper executable)
@echo off
pwsh.exe -NonInteractive -ExecutionPolicy Bypass ^
  -File "C:\VeeamONE\Scripts\Send-TeamsAlert.ps1" ^
  -AlarmName "%1" ^
  -NodeName "%2" ^
  -Summary "%3" ^
  -TriggeredAt "%4" ^
  -Status "%5" ^
  -PrevStatus "%6"

In Veeam ONE, edit the target alarm, go to the Notifications tab, add a Run Script action, and set the executable path to the .cmd file. Set the condition to Errors and Warnings or Errors Only depending on your noise tolerance.


3. Grafana Integration via Prometheus

Grafana does not have a native Veeam data source. The integration path is: PowerShell exporter script collects VBR metrics and exposes them as a Prometheus endpoint, Prometheus scrapes the endpoint, Grafana queries Prometheus. This gives you full time series dashboards for backup job success rates, repository capacity trends, proxy throughput, and more.

Setting Up the Veeam Prometheus Exporter

The community maintained veeam-exporter project (available on GitHub) is the most widely used approach. It connects to the VBR REST API (port 9419 by default in v12 and v13), collects job, session, and repository metrics, and exposes them as a Prometheus metrics endpoint on a configurable local port. Run it on the VBR server itself or on any host with network access to the VBR REST API.

Install veeam-exporter (run on VBR server or monitoring host)
# Install the Veeam PowerShell snap-in if not already present
# (included with VBR console installation)

# Download and extract veeam-exporter
# https://github.com/veeamhub/veeam-exporter

# Configure veeam-exporter.yaml
veeamserver: localhost
veeamport: 9419
veeamuser: svc-veeam-exporter
veeampassword: "your-service-account-password"
port: 9100
# veeamport 9419 is the VBR REST API default port in v12 and v13
# port 9100 is the metrics endpoint veeam-exporter exposes for Prometheus to scrape

Key Metrics Exposed

MetricDescriptionDashboard Use
veeam_jobs_statusLast job run result per job (0=success, 1=warning, 2=error)Job health overview panel
veeam_repositories_capacity_gbTotal capacity per repository in GBRepository capacity gauge
veeam_repositories_free_gbFree space per repository in GBRepository free space trend
veeam_jobs_duration_secondsLast job duration in secondsBackup window compliance chart
veeam_protected_vmsCount of protected VMsCoverage summary panel
veeam_failed_jobs_last24hCount of failed jobs in the last 24 hoursDaily failure count alert panel

Prometheus Scrape Configuration

prometheus.yml scrape config for Veeam
scrape_configs:
  - job_name: 'veeam'
    scrape_interval: 60s
    scrape_timeout: 30s
    static_configs:
      - targets:
          - 'vbr-server.domain.local:9100'
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+).*'
        replacement: '${1}'

Recommended Grafana Dashboard Panels

  • Job Success Rate (24h). Stat panel showing percentage of jobs that completed successfully in the last 24 hours. Alert threshold at 95%.
  • Repository Capacity by Repo. Bar gauge showing used vs free per repository. Alert at 80% used.
  • Failed Jobs (7 days). Time series showing daily failure count. Spike detection for ransomware correlation.
  • Backup Window Compliance. Table showing job duration vs expected window per job. Highlights overrunning jobs.
  • Protected VM Count Trend. Time series showing total protected VM count over time. Drops indicate coverage loss.

4. Splunk Integration

Splunk ingestion gives your security team visibility into Veeam events alongside the rest of your infrastructure. Backup job failures, repository access, configuration changes, and Veeam ONE alarms all become searchable events in Splunk. For SOC teams, unusual backup patterns (jobs suddenly failing after running cleanly for months, large unexpected data changes) are early ransomware indicators.

HTTP Event Collector Setup

In Splunk: Settings, Data Inputs, HTTP Event Collector, New Token. Set a source type of json and note the token. The HEC endpoint is https://splunk-server:8088/services/collector/event.

PowerShell: Push Veeam Job Sessions to Splunk HEC

Send-VeeamToSplunk.ps1 (schedule as a Windows Task every 15 minutes)
Connect-VBRServer -Server "vbr-server.domain.local"

$splunkHEC   = "https://splunk-server.domain.local:8088/services/collector/event"
$splunkToken = "YOUR-HEC-TOKEN"
$cutoff      = (Get-Date).AddMinutes(-20)

# Get recent job sessions
$sessions = Get-VBRBackupSession | Where-Object { $_.EndTime -gt $cutoff -or $_.State -eq "Working" }

foreach ($session in $sessions) {
    $event = @{
        time       = [DateTimeOffset]::new($session.EndTime).ToUnixTimeSeconds()
        sourcetype = "veeam:backup:session"
        source     = "vbr-powershell"
        host       = $env:COMPUTERNAME
        event      = @{
            job_name    = $session.JobName
            job_type    = $session.JobType.ToString()
            state       = $session.State.ToString()
            result      = $session.Result.ToString()
            start_time  = $session.CreationTime.ToString("o")
            end_time    = $session.EndTime.ToString("o")
            duration_s  = [int]($session.EndTime - $session.CreationTime).TotalSeconds
            total_size_gb = [math]::Round($session.BackupStats.TotalSize / 1GB, 2)
            transferred_gb = [math]::Round($session.BackupStats.BackupSize / 1GB, 2)
        }
    } | ConvertTo-Json -Depth 5

    $headers = @{ Authorization = "Splunk $splunkToken" }
    Invoke-RestMethod -Uri $splunkHEC -Method Post -Body $event `
                      -Headers $headers -ContentType "application/json" `
                      -SkipCertificateCheck
}

Disconnect-VBRServer

Two notes on the script above: the -SkipCertificateCheck parameter on Invoke-RestMethod requires PowerShell 6 or later (pwsh.exe). If you are running Windows PowerShell 5.1, remove that parameter and configure certificate trust through your certificate store instead. The Unix timestamp conversion uses [DateTimeOffset]::new() which works reliably on all PowerShell versions on Windows, avoiding the -UFormat %s pattern which is inconsistently supported outside Linux environments.

Useful Splunk Searches for Veeam Data

Splunk SPL: Failed jobs in the last 24 hours
sourcetype="veeam:backup:session" result="Failed" earliest=-24h
| table job_name, start_time, end_time, duration_s, result
| sort start_time desc
Splunk SPL: Jobs with unusually large data change (potential ransomware indicator)
sourcetype="veeam:backup:session" earliest=-7d
| eval change_ratio = transferred_gb / total_size_gb
| where change_ratio > 0.5
| table job_name, start_time, total_size_gb, transferred_gb, change_ratio
| sort change_ratio desc

5. Zabbix Integration

Zabbix integration works via two approaches: SNMP traps from Veeam ONE for real time alarm events, and external check scripts that Zabbix runs periodically to collect VBR metrics.

SNMP Trap Integration

Configure Veeam ONE to send SNMP traps to your Zabbix server (Settings, Server Settings, SNMP Settings, enter Zabbix server IP on port 162). In Zabbix, configure an SNMP trap receiver item on the host representing your Veeam ONE server. Import the Veeam ONE MIB file to decode trap content into readable alarm data.

External Check Script for Zabbix

Zabbix external checks run a script on the Zabbix server and return a value. Create a PowerShell script that connects to VBR and returns the metric Zabbix is polling for.

veeam-check.ps1 (placed in Zabbix externalscripts directory)
# Called by Zabbix as: veeam-check.ps1 [metric_name]
# Returns a single value that Zabbix stores as an item

param([string]$Metric)

Connect-VBRServer -Server "vbr-server.domain.local" -Credential (
    New-Object PSCredential("svc-zabbix", (ConvertTo-SecureString "password" -AsPlainText -Force))
)

$result = switch ($Metric) {
    "failed_jobs_24h" {
        $cutoff = (Get-Date).AddHours(-24)
        (Get-VBRBackupSession | Where-Object {
            $_.EndTime -gt $cutoff -and $_.Result -eq "Failed"
        }).Count
    }
    "repo_free_pct" {
        $repos = Get-VBRBackupRepository
        $totalFree = ($repos | Measure-Object -Property FreeSpace -Sum).Sum
        $totalCap  = ($repos | Measure-Object -Property Capacity -Sum).Sum
        [math]::Round(($totalFree / $totalCap) * 100, 1)
    }
    "protected_vm_count" {
        (Get-VBRProtectedVM).Count
    }
    "last_job_result" {
        $lastSession = Get-VBRBackupSession | Sort-Object EndTime -Descending | Select-Object -First 1
        switch ($lastSession.Result) {
            "Success" { 0 }
            "Warning" { 1 }
            "Failed"  { 2 }
            default   { 3 }
        }
    }
}

Disconnect-VBRServer
Write-Output $result

Zabbix Item Configuration

Item KeyScript CallValue TypeTrigger Threshold
veeam.failed.jobsveeam-check.ps1[failed_jobs_24h]Numeric unsignedWarning at 1, High at 3
veeam.repo.free.pctveeam-check.ps1[repo_free_pct]Numeric floatWarning at 20%, High at 10%
veeam.protected.vmsveeam-check.ps1[protected_vm_count]Numeric unsignedChange detection trigger
veeam.last.job.resultveeam-check.ps1[last_job_result]Numeric unsignedHigh at 2 (Failed)

6. Service Account Best Practices

All of these integrations require a service account with access to VBR. Do not use a full administrator account for monitoring integrations. Create a dedicated read only account.

  • Create a dedicated service account: svc-veeam-monitoring or similar
  • Assign the Veeam Backup Viewer role in VBR. This grants read only access to job status, sessions, repository data, and infrastructure inventory without the ability to modify anything.
  • Store credentials in your secrets manager, not in plain text in scripts. Use Windows Credential Manager, HashiCorp Vault, or similar.
  • Restrict the account to log on only from the monitoring host. Group Policy or local policy can enforce this.
  • Rotate the password on your standard service account rotation schedule and update all integration scripts at the same time.
A monitoring integration that requires local admin or Veeam Administrator access to read job status is misconfigured. The Veeam Backup Viewer role exists precisely for this use case.

Key Takeaways

  • Use Veeam ONE alarm script actions for real time alert delivery to Teams and Slack. Scripts run under the Veeam ONE service account and receive 8 parameters including alarm name, object, status, and timestamp.
  • Teams and Slack webhooks accept JSON payloads. The MessageCard format works for Teams. Blocks format works for Slack. Color code by severity so engineers can triage at a glance.
  • Grafana integration requires a Prometheus exporter. The community veeam-exporter connects to the VBR REST API and exposes job status, repository capacity, and session metrics as Prometheus metrics. Prometheus scrapes the exporter endpoint; Grafana queries Prometheus.
  • Splunk HEC ingestion via PowerShell polling gives your security team Veeam job session data as searchable events. Unusual change ratios (transferred GB vs total size) are an early ransomware indicator worth alerting on.
  • Zabbix integration works via SNMP traps from Veeam ONE for events and external check scripts for metric polling. Both approaches are supported natively without additional plugins.
  • All monitoring integrations should use a dedicated service account with the Veeam Backup Viewer role, not an administrator account. Credentials should be stored in a secrets manager, not in plain text.

Read more