Automated Host creation and deployment
Zabbix is a powerful open-source monitoring solution that can monitor various services, servers, and network devices. In this blog, I will show how I setup WMI sensor discovery with auto-deployment of the Zabbix Agent using GPO, and having the desktops auto-register with the Zabbix server.


‣ Prerequisites
• Zabbix Server
• Windows Server
Host Creation
SENSOR DISCOVERY
This part sets up how I will get sensor information from LibreHardwareMonitor and send it to Zabbix. The purpose is to install the Zabbix Agent on select Windows machines that need more monitoring than most.
First, I opened up Visual Studio Code and made the following YAML file to extract WMI information from LibreHardwareMonitor.
zabbix_export:
version: '6.4'
template_groups:
- uuid: 57b7ae836ca64446ba2c296389c00933
name: Templates/Modules
- uuid: 846977d1dfed4968bc5f8bdb36328533
name: 'Templates/Operating systems'
templates:
- uuid: f4c4ad00160d4848bb6e8d4f4aa83033
template: WINDOWS_LHM_AUTO
name: 'Windows LibreHardwareMonitor Discovery'
groups:
- name: Templates/Modules
- name: 'Templates/Operating systems'
discovery_rules:
- uuid: 82ce8718123a4613866b5ce90c38f933
name: 'Sensors discovery'
key: lhm_discovery
filter:
conditions:
- macro: '{#ID_WMI}'
formulaid: A
type: ZABBIX_ACTIVE
item_prototypes:
- uuid: 0ad541b0a61a476a867e5d1ae03fc333
name: 'LHM: {#NAME_WMI}'
key: 'Lhm_capteur[{#ID_WMI}]'
value_type: FLOAT
type: ZABBIX_ACTIVE
template_groups
– This will add it to the ‘Templates/Modules’ and ‘Templates/Operating systems’ groups.templates
– This will give it the name ‘Windows LibreHardwareMonitor Discovery’.discovery_rules
lhm_discovery
– The item key used by Zabbix to execute this discovery.{#ID_WMI}
Contains conditions that refine which discovered entities are considered valid.ZABBIX_ACTIVE
– Specifies that this is an active check, meaning the agent sends data to the server.
I then went to Data Collection > Templates
.

Then selected the file and clicked ‘Import’.

AUTO-REGISTRATION
This part shows how I setup auto-registration, that way any Active Agents will be automatically added to the host list, and be given the desired templates.
First, I went to Alerts > Actions > Autoregistration Actions.

I gave the action a name and clicked ‘Add’ under ‘Conditions’.

Each desktop ends with ‘PC’ so I set it up to add any host name that contact ‘PC’.

I then created an operation to add the host to the ‘Corporate Desktops’ group.

I also set it to add the templates ‘Windows by Zabbix agent active’ and the one I just created ‘Windows LibreHardwareMonitor Discovery’.

I then clicked ‘Add’.

WINDOWS SERVER
FILE PREPARATION
Here I go over downloading the necessary files, as well as creating a configuration file, and 2 PowerShell scripts, which will be used to get sensor information from LibreHardwareMonitor.
First, from my Windows Server I downloaded the Zabbix Agent 2 MSI installer.
https://www.zabbix.com/download_agents
I made sure to get the ‘agent 2’ MSI.

I then downloaded LibreHardwareMonitor.
https://github.com/LibreHardwareMonitor/LibreHardwareMonitor/releases
I then extracted the contents and created the following file and named it LibreHardwareMonitor.config
startMinMenuItem
– Makes the program start minimized upon boot.minCloseMenuItem
– If you close the program it’ll minimize it to the system tray.minTrayMenuItem
– If you minimize the program it’ll minimize it to the system tray.
I then created a PowerShell script to collect hardware sensor information from LibreHardwareMonitor via WMI, process it to create human-readable names, and then output the data in a JSON format suitable for Zabbix.
I named the file ‘lhm_discovery.ps1’.
#Create the data array
$sensorData = @()
Get-WmiObject -Namespace "Root\LibreHardwareMonitor" -Query "SELECT * FROM Sensor" | ForEach-Object {
#Make a human readable name for Zabbix
$blah = $_.Identifier -match '(\w+)/(\d+)$'
$itemPropertyName = (Get-Culture).TextInfo.ToTitleCase($Matches[1])
$itemPropertyIndex = $Matches[2]
#Create the object and populate its properites
$properties = @{'{#ID_WMI}'=$_.Identifier;'{#NAME_WMI}'=$_.Name + " " + $itemPropertyName + " " + $itemPropertyIndex}
$object = New-Object -TypeName PSObject -Prop $properties
#Add the object to the array
$sensorData += ($object)
}
#Wrap the resulting array into another object as property 'data'
$properties = @{'data'=$sensorData}
$object = New-Object -TypeName PSObject -Prop $properties
#Output to the console to be picked up by Zabbix
write-host($object | convertto-json)
\$sensorData = @()
– Creates an empty array to store sensor data objects.Get-WmiObject
– Queries WMI for all sensor objects in the LibreHardwareMonitor namespace.ForEach-Object
– Processes each sensor.\$_.Identifier -match '(\w+)/(\d+)$'
– Uses a regular express to extract two parts from the sensor’s Identifier property.(\w+)
– Represents a type or category.(\d+)
– Represents an index or identifier number.
I then created a PowerShell script to retrieve a specific sensor’s value from LibreHardwareMonitor using WMI, based on an identifier passed in by the Zabbix agent.
I named the file ‘lhm_get.ps1’.
#grab the ident parameter that was passed in (by the Zabbix agent)
param([string]$ident)
$request = "SELECT * FROM Sensor WHERE Identifier='$ident'"
#Request the data (only need the first result) and write it out to the console for the zabbix agent
$sensorValues = Get-WmiObject -Namespace "Root\LibreHardwareMonitor" -Query $request
write-host($sensorValues.value)
#Sample to test if it works
#powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent\lhm_discovery.ps1"
#Copy any #ID_WMI value in the and for example
#powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent\lhm_get.ps1" "/amdcpu/0/load/0"
NETWORK SHARE
I next needed to create a network share so that the computers can access these newly downloaded and created files.
First, I went to File and Storage Services > Volumes > Tasks > New Share
.

Chose SMB Share - Quick
.

I chose the server, and entered the custom path.

I gave the share the name ‘Zabbix’.

I checked both Enable access-based enumeration
and Allow caching of share
.

I added ‘Domain Users’ to have ‘Read & execute’ permissions.

Then clicked ‘Create’.

I created a folder within the share called ‘Zabbix’.

I then pasted the LHM folder (with the config file), the 2 PowerShell scripts I created and the Zabbix Agent 2 msi.

GROUP POLICY
I made seperate GPO’s, as well as different PowerShell scripts to install Zabbix, as well as Install LibreHardwareMonitor.
It’s possible that this all could have been accomplished with 1 script, but I could not figure it out myself. I kept running into errors and issues where it would start 3 instances of LibreHardwareMonitor.
The first GPO will be to install Zabbix.
I opened Group Policy Management, right-clicked on my domain and selected ‘Create a GPO in this domain, and Link it here…’.

I gave it an easy identifiable name.

Then right-clicked on the GPO and selected ‘Edit’.

I then drilled down to Computer Configuration > Policies > Windows Settings > Scripts
.

I right-clicked ‘Startup’ and clicked ‘Properties’.

I clicked on the PowerShell Scripts tab, and then clicked on ‘Show Files’.

I’m going to create 4 ps1 files. So I right-clicked and went to New > Text Document
.

First one will install Zabbix.
# Construct the FQDN of the local computer
$FQDN=(Get-WmiObject win32_computersystem).DNSHostName+"."+(Get-WmiObject win32_computersystem).Domain
$ZabbixInstallationMSI = "\\WIN-SVR1\Zabbix\Zabbix\zabbixagent2.msi"
$ZabbixAgentVersion = "7.2"
$ZabbixServerIP = "10.33.99.30"
$ZabbixInstallationFolder = "\\$FQDN\c$\Program Files\Zabbix Agent 2\"
$ZabbixSoftwareName = "Zabbix Agent 2 (64-bit)"
$InstalledZabbixVersion = (Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -eq $ZabbixSoftwareName }).Version
# Extract the major version from the installed version
$InstalledVersion = $InstalledZabbixVersion -replace "(\d+\.\d+\.\d+).*", '$1'
$Arguments = "SERVER=$ZabbixServerIP SERVERACTIVE=$ZabbixServerIP HOSTMETADATA=Windows HOSTNAME=$FQDN /qn"
if ($InstalledVersion -lt $ZabbixAgentVersion) {
# The installed version if different from the desired version, so perform the installation or update
if (Test-Path $ZabbixInstallationMSI) {
# The instalation file is available, so start the installation process
Start-Process -FilePath "$ZabbixInstallationMSI" -ArgumentList "$Arguments" -Wait
# Copy-Item -Path @($ZabbixPluginFolder, $ZabbixScriptsFolder) -Destination $ZabbixInstallationFolder -Force -Recurse
} else {
# The installation file is not available, exit the script
exit
}
}
Next one is to move the 2 PowerShell scripts I created earlier, lhm_discovery & lhm_get, into the Zabbix folder.
$sourcePath = "\\WIN-SVR1\Zabbix\Zabbix\"
$destinationPath = "C:\Program Files\Zabbix Agent 2"
$files = @("lhm_discovery.ps1", "lhm_get.ps1")
foreach ($file in $files) {
$src = Join-Path -Path $sourcePath -ChildPath $file
$dest = Join-Path -Path $destinationPath -ChildPath $file
if (Test-Path $src) {
Copy-Item -Path $src -Destination $dest -Force
} else {
Write-Output "File not found: $src"
}
}
This next one will add 2 lines to the Zabbix configuration file. These 2 lines will work with the PowerShell scripts, lhm_discovery & lhm_get.
Set-ExecutionPolicy Unrestricted -Scope Process
$confFilePath = "C:\Program Files\Zabbix Agent 2\zabbix_agent2.conf"
$line1 = 'UserParameter=ohm_discovery,powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent 2\lhm_discovery.ps1"
$line2 = 'UserParameter=ohm_capteur[*],powershell.exe -Noprofile -ExecutionPolicy Bypass -file "C:\Program Files\Zabbix Agent 2\lhm_get.ps1" $1'
if (Test-Path $confFilePath) {
$configContent = Get-Content $confFilePath
if ($configContent -notcontains $line1) {
$configContent += $line1
}
if ($configContent -notcontains $line2) {
$configContent += $line2
}
$configContent | Set-Content -Path $confFilePath -Encoding Ascii -Force
}
Last one is to restart Zabbix, that way the Zabbix agent will start sending the LibreHardwareMonitor sensor information pulled with the PowerShell scripts.
Restart-Service -Name "Zabbix Agent 2"
I then created another GPO, and created the following PowerShell script to install LibreHardwareMonitor.
Get-Process -Name "LibreHardwareMonitor" -ErrorAction SilentlyContinue | Stop-Process -Force
New-Item -Path "C:\Program Files\" -Name "LHM" -ItemType Directory -Force
$sourceFolder = "\\WIN-SVR1\Zabbix\Zabbix\LHM\*"
$destinationFolder = "C:\Program Files\LHM"
$exePath = "C:\Program Files\LHM\LibreHardwareMonitor.exe"
Start-Sleep -Seconds 60
if (Test-Path "\\WIN-SVR1\Zabbix\Zabbix\LHM\") {
Copy-Item -Path $sourceFolder -Destination $destinationFolder -Recurse -Force
} else {
Write-Output "Error1"
exit
}
if (-Not (Test-Path $exePath)) {
Write-Output "Error2"
exit
}
$ohmRunning = Get-Process | Where-Object {
$_.Path -eq $exePath
}
if (-not $lhmRunning) {
Start-Process -FilePath $exePath
Write-Output "Error3"
} else {
Write-Output "Error4"
}