Files
linux-scripts/install-windows-exporter.ps1
T
chiefgeek a1a17e81a1 Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
2026-05-25 03:31:08 +02:00

582 lines
21 KiB
PowerShell

#############################################################
#### Prometheus Windows Exporter Installer ####
#### For Windows Server 2016+ and Windows 10/11 ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### License: MIT ####
#### Version: 1.0 ####
#### ####
#### Usage: .\install-windows-exporter.ps1 [OPTIONS] ####
#############################################################
param(
[string]$ServerType = "standard", # standard, iis, sql, ad, rdp, all
[string]$ExtraCollectors = "", # additional collectors (comma-separated)
[string]$RemoveCollectors = "", # collectors to remove from the profile
[int]$Port = 9182,
[string]$InstallDir = "C:\Program Files\windows_exporter",
[string]$PrometheusIP = "", # restrict firewall to this IP
[switch]$NoFirewall,
[switch]$NoDefenderExclusion,
[switch]$Update,
[switch]$Uninstall,
[switch]$DryRun,
[switch]$Help
)
$ErrorActionPreference = "Stop"
# ============================================================================
# CONFIGURATION
# ============================================================================
$ServiceName = "windows_exporter"
$ServiceDisplayName = "Prometheus Windows Exporter"
$FirewallRuleName = "Prometheus Windows Exporter (TCP-In)"
$GitHubApiUrl = "https://api.github.com/repos/prometheus-community/windows_exporter/releases/latest"
$TextFileDir = Join-Path $InstallDir "textfile_inputs"
$TargetExe = Join-Path $InstallDir "windows_exporter.exe"
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
function Write-ColorOutput {
param([string]$Message, [string]$Color = "Green")
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "[$timestamp] $Message" -ForegroundColor $Color
}
function Show-Help {
Write-Host @"
Prometheus Windows Exporter Installer v1.0
https://mylinux.work
USAGE:
.\install-windows-exporter.ps1 [OPTIONS]
OPTIONS:
-ServerType <type> Server profile: standard, iis, sql, ad, rdp, all (default: standard)
-ExtraCollectors <list> Additional collectors, comma-separated (e.g. "service,hyperv")
-RemoveCollectors <list> Remove collectors from the profile (e.g. "tcp,time")
-Port <port> Metrics listen port (default: 9182)
-InstallDir <path> Installation directory (default: C:\Program Files\windows_exporter)
-PrometheusIP <ip> Restrict firewall rule to this source IP
-NoFirewall Skip firewall rule creation
-NoDefenderExclusion Skip Windows Defender exclusion
-Update Update existing installation to latest version
-Uninstall Remove windows_exporter completely
-DryRun Show what would be done without making changes
-Help Show this help
SERVER PROFILES:
standard [defaults],process,tcp,time
iis [defaults],process,tcp,time,iis
sql [defaults],process,tcp,time,mssql
ad [defaults],process,tcp,time,ad,dns
rdp [defaults],process,tcp,time,remote_fx
all [defaults],process,tcp,time,iis,mssql,ad,dns,remote_fx
[defaults] = cpu,cs,logical_disk,os,system,net,cache,logon,memory
EXAMPLES:
# Standard install
.\install-windows-exporter.ps1
# IIS server with restricted firewall
.\install-windows-exporter.ps1 -ServerType iis -PrometheusIP "10.0.0.5"
# SQL server with extra service collector
.\install-windows-exporter.ps1 -ServerType sql -ExtraCollectors "service"
# Update to latest version
.\install-windows-exporter.ps1 -Update
# Uninstall
.\install-windows-exporter.ps1 -Uninstall
"@
}
# ============================================================================
# ADMINISTRATOR CHECK
# ============================================================================
function Test-Administrator {
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
# ============================================================================
# SERVER PROFILE BUILDER
# ============================================================================
function Get-CollectorString {
$defaultCollectors = @("cpu", "cs", "logical_disk", "os", "system", "net", "cache", "logon", "memory")
$profileCollectors = @("process", "tcp", "time")
switch ($ServerType.ToLower()) {
"iis" { $profileCollectors += @("iis") }
"sql" { $profileCollectors += @("mssql") }
"ad" { $profileCollectors += @("ad", "dns") }
"rdp" { $profileCollectors += @("remote_fx") }
"all" { $profileCollectors += @("iis", "mssql", "ad", "dns", "remote_fx") }
"standard" { }
default {
Write-ColorOutput "WARNING: Unknown server type '$ServerType', using 'standard'" "Yellow"
}
}
$allCollectors = $defaultCollectors + $profileCollectors
# Add extra collectors
if ($ExtraCollectors) {
$extras = $ExtraCollectors -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
foreach ($col in $extras) {
if ($allCollectors -notcontains $col) {
$allCollectors += $col
}
}
}
# Remove unwanted collectors
if ($RemoveCollectors) {
$removals = $RemoveCollectors -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" }
$allCollectors = $allCollectors | Where-Object { $removals -notcontains $_ }
}
return ($allCollectors | Select-Object -Unique) -join ","
}
# ============================================================================
# GITHUB RELEASE FUNCTIONS
# ============================================================================
function Get-LatestRelease {
Write-ColorOutput "Querying GitHub for latest release..."
try {
$release = Invoke-RestMethod -Uri $GitHubApiUrl -UseBasicParsing
$asset = $release.assets | Where-Object { $_.name -match "amd64" -and $_.name -match "\.exe$" } | Select-Object -First 1
if (-not $asset) {
Write-ColorOutput "ERROR: Could not find amd64 .exe asset in latest release" "Red"
exit 1
}
return @{
Version = $release.tag_name
DownloadUrl = $asset.browser_download_url
AssetName = $asset.name
}
} catch {
Write-ColorOutput "ERROR: Failed to query GitHub API: $($_.Exception.Message)" "Red"
exit 1
}
}
# ============================================================================
# SERVICE MANAGEMENT
# ============================================================================
function Stop-ExistingService {
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($service) {
Write-ColorOutput "Stopping existing service..."
Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
}
}
function Remove-ExistingService {
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($service) {
Stop-ExistingService
Write-ColorOutput "Deleting existing service..."
sc.exe delete $ServiceName | Out-Null
Start-Sleep -Seconds 2
}
}
function New-ExporterService {
param([string]$CollectorString)
$serviceArgs = @(
"--log.file=eventlog",
"--web.listen-address=0.0.0.0:$Port",
"--collector.textfile.directories=`"$TextFileDir`"",
"--collectors.enabled=$CollectorString"
)
$binaryPath = "`"$TargetExe`" " + ($serviceArgs -join " ")
Write-ColorOutput "Creating service with collectors: $CollectorString" "Cyan"
if ($DryRun) {
Write-ColorOutput "[DRY RUN] Would create service: $binaryPath" "Yellow"
return
}
New-Service -Name $ServiceName `
-BinaryPathName $binaryPath `
-DisplayName $ServiceDisplayName `
-StartupType Automatic `
-Description "Prometheus metrics exporter for Windows (managed by install-windows-exporter.ps1)" | Out-Null
Write-ColorOutput "Service created successfully"
}
# ============================================================================
# FIREWALL MANAGEMENT
# ============================================================================
function Add-FirewallRule {
if ($NoFirewall) {
Write-ColorOutput "Skipping firewall rule (-NoFirewall specified)" "Yellow"
return
}
# Remove existing rule if present
$existing = Get-NetFirewallRule -DisplayName $FirewallRuleName -ErrorAction SilentlyContinue
if ($existing) {
Remove-NetFirewallRule -DisplayName $FirewallRuleName -ErrorAction SilentlyContinue
Write-ColorOutput "Removed existing firewall rule"
}
if ($DryRun) {
$scope = if ($PrometheusIP) { $PrometheusIP } else { "Any" }
Write-ColorOutput "[DRY RUN] Would create firewall rule: port $Port, source: $scope" "Yellow"
return
}
$params = @{
DisplayName = $FirewallRuleName
Direction = "Inbound"
Protocol = "TCP"
LocalPort = $Port
Action = "Allow"
Profile = "Any"
Description = "Allow Prometheus to scrape windows_exporter metrics on port $Port"
}
if ($PrometheusIP) {
$params.RemoteAddress = $PrometheusIP
Write-ColorOutput "Creating firewall rule: port $Port restricted to $PrometheusIP"
} else {
Write-ColorOutput "Creating firewall rule: port $Port open to all sources"
}
New-NetFirewallRule @params | Out-Null
Write-ColorOutput "Firewall rule created"
}
function Remove-FirewallRule {
$existing = Get-NetFirewallRule -DisplayName $FirewallRuleName -ErrorAction SilentlyContinue
if ($existing) {
Remove-NetFirewallRule -DisplayName $FirewallRuleName
Write-ColorOutput "Firewall rule removed"
} else {
Write-ColorOutput "No firewall rule found to remove" "Yellow"
}
}
# ============================================================================
# DEFENDER EXCLUSION
# ============================================================================
function Add-DefenderExclusion {
if ($NoDefenderExclusion) {
Write-ColorOutput "Skipping Defender exclusion (-NoDefenderExclusion specified)" "Yellow"
return
}
if ($DryRun) {
Write-ColorOutput "[DRY RUN] Would add Defender exclusion for: $InstallDir" "Yellow"
return
}
try {
Add-MpPreference -ExclusionPath $InstallDir -ErrorAction Stop
Write-ColorOutput "Windows Defender exclusion added for: $InstallDir"
} catch {
Write-ColorOutput "WARNING: Could not add Defender exclusion: $($_.Exception.Message)" "Yellow"
}
}
function Remove-DefenderExclusion {
try {
Remove-MpPreference -ExclusionPath $InstallDir -ErrorAction Stop
Write-ColorOutput "Windows Defender exclusion removed for: $InstallDir"
} catch {
Write-ColorOutput "WARNING: Could not remove Defender exclusion: $($_.Exception.Message)" "Yellow"
}
}
# ============================================================================
# VERIFICATION
# ============================================================================
function Test-MetricsEndpoint {
Write-ColorOutput "Waiting for service to start..."
Start-Sleep -Seconds 5
$metricsUrl = "http://localhost:$Port/metrics"
try {
$response = Invoke-WebRequest -Uri $metricsUrl -UseBasicParsing -TimeoutSec 10
if ($response.StatusCode -eq 200) {
Write-ColorOutput "Metrics endpoint responding at $metricsUrl" "Green"
return $true
}
} catch {
Write-ColorOutput "WARNING: Metrics endpoint not responding at $metricsUrl" "Yellow"
Write-ColorOutput "The service may still be starting. Check: Get-Service $ServiceName" "Yellow"
return $false
}
return $false
}
# ============================================================================
# UNINSTALL MODE
# ============================================================================
function Invoke-Uninstall {
Write-ColorOutput "=== Uninstalling Windows Exporter ===" "Cyan"
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $service -and -not (Test-Path $InstallDir)) {
Write-ColorOutput "Windows Exporter does not appear to be installed" "Yellow"
exit 0
}
Write-Host ""
Write-Host "This will remove:" -ForegroundColor Yellow
Write-Host " - Service: $ServiceName"
Write-Host " - Directory: $InstallDir"
Write-Host " - Firewall rule: $FirewallRuleName"
Write-Host " - Defender exclusion: $InstallDir"
Write-Host ""
if (-not $DryRun) {
$confirm = Read-Host "Are you sure? (y/N)"
if ($confirm -ne "y" -and $confirm -ne "Y") {
Write-ColorOutput "Uninstall cancelled" "Yellow"
exit 0
}
}
if ($DryRun) {
Write-ColorOutput "[DRY RUN] Would uninstall windows_exporter" "Yellow"
return
}
# Stop and remove service
Remove-ExistingService
# Remove firewall rule
Remove-FirewallRule
# Remove Defender exclusion
Remove-DefenderExclusion
# Remove install directory
if (Test-Path $InstallDir) {
Remove-Item -Path $InstallDir -Recurse -Force
Write-ColorOutput "Install directory removed: $InstallDir"
}
Write-Host ""
Write-ColorOutput "=== Windows Exporter uninstalled successfully ===" "Green"
}
# ============================================================================
# UPDATE MODE
# ============================================================================
function Invoke-Update {
Write-ColorOutput "=== Updating Windows Exporter ===" "Cyan"
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $service) {
Write-ColorOutput "ERROR: Service '$ServiceName' not found. Use install mode instead." "Red"
exit 1
}
$release = Get-LatestRelease
Write-ColorOutput "Latest version: $($release.Version)"
# Check installed version if binary exists
if (Test-Path $TargetExe) {
try {
$installedVersion = (Get-Item $TargetExe).VersionInfo.ProductVersion
if ($installedVersion) {
Write-ColorOutput "Installed version: $installedVersion"
$latestClean = $release.Version -replace '^v', ''
if ($installedVersion -eq $latestClean) {
Write-ColorOutput "Already running the latest version. No update needed." "Green"
exit 0
}
}
} catch {
Write-ColorOutput "Could not determine installed version, proceeding with update" "Yellow"
}
}
if ($DryRun) {
Write-ColorOutput "[DRY RUN] Would update to $($release.Version)" "Yellow"
return
}
# Download new binary
$tempExe = Join-Path $env:TEMP "windows_exporter_update.exe"
Write-ColorOutput "Downloading $($release.AssetName)..."
Invoke-WebRequest -Uri $release.DownloadUrl -OutFile $tempExe -UseBasicParsing
# Stop service, replace binary, start service
Stop-ExistingService
Copy-Item -Path $tempExe -Destination $TargetExe -Force
Remove-Item $tempExe -Force -ErrorAction SilentlyContinue
Write-ColorOutput "Binary updated"
Start-Service -Name $ServiceName
$verified = Test-MetricsEndpoint
Write-Host ""
Write-ColorOutput "=== Update Summary ===" "Cyan"
Write-ColorOutput "Version: $($release.Version)"
Write-ColorOutput "Status: $(if ($verified) { 'Verified' } else { 'Started (verification pending)' })"
Write-ColorOutput "Metrics URL: http://localhost:$Port/metrics"
}
# ============================================================================
# INSTALL MODE
# ============================================================================
function Invoke-Install {
Write-ColorOutput "=== Installing Windows Exporter ===" "Cyan"
Write-ColorOutput "Server type: $ServerType"
Write-ColorOutput "Port: $Port"
Write-ColorOutput "Install dir: $InstallDir"
# --- Create directories ---
if (-not $DryRun) {
if (-not (Test-Path $InstallDir)) {
New-Item -Path $InstallDir -ItemType Directory -Force | Out-Null
Write-ColorOutput "Created directory: $InstallDir"
}
if (-not (Test-Path $TextFileDir)) {
New-Item -Path $TextFileDir -ItemType Directory -Force | Out-Null
Write-ColorOutput "Created directory: $TextFileDir"
}
} else {
Write-ColorOutput "[DRY RUN] Would create: $InstallDir" "Yellow"
Write-ColorOutput "[DRY RUN] Would create: $TextFileDir" "Yellow"
}
# --- Defender exclusion ---
Add-DefenderExclusion
# --- Get latest release ---
$release = Get-LatestRelease
Write-ColorOutput "Latest version: $($release.Version)"
# --- Check if already installed with same version ---
if (Test-Path $TargetExe) {
try {
$installedVersion = (Get-Item $TargetExe).VersionInfo.ProductVersion
$latestClean = $release.Version -replace '^v', ''
if ($installedVersion -and $installedVersion -eq $latestClean) {
Write-ColorOutput "Version $installedVersion already installed, skipping download" "Yellow"
$skipDownload = $true
}
} catch { }
}
# --- Download binary ---
$tempExe = Join-Path $env:TEMP "windows_exporter_install.exe"
if (-not $skipDownload) {
Write-ColorOutput "Downloading $($release.AssetName)..."
if (-not $DryRun) {
Invoke-WebRequest -Uri $release.DownloadUrl -OutFile $tempExe -UseBasicParsing
Write-ColorOutput "Download complete"
} else {
Write-ColorOutput "[DRY RUN] Would download: $($release.DownloadUrl)" "Yellow"
}
}
# --- Stop and remove existing service ---
Remove-ExistingService
# --- Copy binary ---
if (-not $skipDownload -and -not $DryRun) {
Copy-Item -Path $tempExe -Destination $TargetExe -Force
Remove-Item $tempExe -Force -ErrorAction SilentlyContinue
Write-ColorOutput "Binary installed to: $TargetExe"
}
# --- Build collector string ---
$collectorString = Get-CollectorString
# --- Create service ---
New-ExporterService -CollectorString $collectorString
# --- Firewall rule ---
Add-FirewallRule
# --- Start service ---
if (-not $DryRun) {
Write-ColorOutput "Starting service..."
Start-Service -Name $ServiceName
$verified = Test-MetricsEndpoint
}
# --- Summary ---
Write-Host ""
Write-ColorOutput "=== Installation Summary ===" "Cyan"
Write-ColorOutput "Version: $($release.Version)"
Write-ColorOutput "Binary: $TargetExe"
Write-ColorOutput "Port: $Port"
Write-ColorOutput "Collectors: $collectorString"
Write-ColorOutput "Textfile dir: $TextFileDir"
Write-ColorOutput "Firewall: $(if ($NoFirewall) { 'Skipped' } elseif ($PrometheusIP) { "Restricted to $PrometheusIP" } else { 'Open' })"
Write-ColorOutput "Defender: $(if ($NoDefenderExclusion) { 'Skipped' } else { 'Exclusion added' })"
if (-not $DryRun) {
Write-ColorOutput "Status: $(if ($verified) { 'Verified - metrics endpoint responding' } else { 'Started (verification pending)' })"
Write-ColorOutput "Verify URL: http://localhost:$Port/metrics" "Cyan"
}
Write-Host ""
Write-ColorOutput "=== Installation complete ===" "Green"
}
# ============================================================================
# MAIN EXECUTION
# ============================================================================
# Show help
if ($Help) {
Show-Help
exit 0
}
# Check administrator privileges
if (-not (Test-Administrator)) {
Write-ColorOutput "ERROR: This script must be run as Administrator" "Red"
Write-Host "Right-click PowerShell and select 'Run as administrator'" -ForegroundColor Yellow
exit 1
}
if ($DryRun) {
Write-ColorOutput "=== DRY RUN MODE - No changes will be made ===" "Yellow"
Write-Host ""
}
# Route to the appropriate mode
if ($Uninstall) {
Invoke-Uninstall
} elseif ($Update) {
Invoke-Update
} else {
Invoke-Install
}