Here is a clean, comprehensive guide summarizing everything we just built. It is formatted so you can easily copy, paste, and share it with other homelabbers or keep it for your own documentation.
This guide walks through setting up zero-maintenance, native CPU power monitoring for non-enterprise Proxmox nodes (like Intel NUCs, Dell OptiPlex MFFs, or custom builds).
It uses turbostat to pull accurate CPU package wattage, wraps it in an MQTT Auto-Discovery payload so Home Assistant automatically recognizes it as a device, and includes self-logging for easy troubleshooting.
Out of the box, Proxmox looks for a paid Enterprise repository. We need to disable this to install our required packages.
enterprise.proxmox.com repositories and click Disable. (You can also add the No-Subscription repository here to keep getting free updates).Open your Proxmox node's shell and install the CPU tools and MQTT client:
apt update && apt install linux-cpupower mosquitto-clients -y
Never hardcode passwords into executable scripts. We will create a hidden file restricted only to the root user.
Create the secrets file:
nano /usr/local/bin/.mqtt_secrets
Paste in your network details:
MQTT_BROKER="192.168.X.X" # Replace with your MQTT IP
MQTT_USER="your_mqtt_user" # Replace with your MQTT username
MQTT_PASS="your_mqtt_pass" # Replace with your MQTT password
Ctrl+O, Enter, Ctrl+X).Lock down the file permissions:
chmod 600 /usr/local/bin/.mqtt_secrets
This script dynamically grabs the node's hostname, builds a Home Assistant Auto-Discovery JSON payload, extracts the wattage, pushes the data, and logs any errors.
nano /usr/local/bin/report_power.sh
Paste the following code:
#!/bin/bash
# Define our error log
LOG_FILE="/var/log/proxmox_power.log"
# Load variables from the secrets file
source /usr/local/bin/.mqtt_secrets
# Dynamically grab the hostname
NODE_NAME=$(hostname)
STATE_TOPIC="proxmox/${NODE_NAME}/cpu_power"
CONFIG_TOPIC="homeassistant/sensor/proxmox_${NODE_NAME}/cpu_power/config"
# Extract PkgWatt using the absolute path for turbostat
WATTAGE=$(/usr/sbin/turbostat --quiet --Summary --show PkgWatt -n 1 2>>"$LOG_FILE" | awk 'NR==2 {print $1}')
# Build the JSON Auto-Discovery Payload
CONFIG_PAYLOAD=$(cat <<EOF
{
"name": "CPU Power",
"object_id": "proxmox_${NODE_NAME}_cpu_power",
"unique_id": "proxmox_${NODE_NAME}_cpu_power",
"state_topic": "${STATE_TOPIC}",
"unit_of_measurement": "W",
"device_class": "power",
"state_class": "measurement",
"icon": "mdi:cpu-64-bit",
"device": {
"identifiers": ["proxmox_${NODE_NAME}"],
"name": "Proxmox Node (${NODE_NAME})",
"manufacturer": "Proxmox",
"model": "Compute Node"
}
}
EOF
)
# Push to MQTT only if the wattage is a valid number
if [[ $WATTAGE =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
# 1. Send Config (Retained)
mosquitto_pub -h "$MQTT_BROKER" -u "$MQTT_USER" -P "$MQTT_PASS" -t "$CONFIG_TOPIC" -m "$CONFIG_PAYLOAD" -r 2>>"$LOG_FILE"
# 2. Send State
mosquitto_pub -h "$MQTT_BROKER" -u "$MQTT_USER" -P "$MQTT_PASS" -t "$STATE_TOPIC" -m "$WATTAGE" 2>>"$LOG_FILE"
# Log network errors
if [ $? -ne 0 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Failed to connect to MQTT Broker at $MQTT_BROKER" >> "$LOG_FILE"
fi
else
# Log extraction errors
echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: Invalid wattage reading. Got: '$WATTAGE'" >> "$LOG_FILE"
fi
Ctrl+O, Enter, Ctrl+X).Crucial: Make the script executable:Bash
chmod +x /usr/local/bin/report_power.sh
Tell Proxmox to run this silently in the background every 60 seconds.
Open your cron editor:
crontab -e
* * * * * /usr/local/bin/report_power.sh
/var/log/proxmox_power.log. If that file doesn't exist, it means the script is running flawlessly.)nano /etc/logrotate.d/proxmox_power/var/log/proxmox_power.log {
size 5M
rotate 2
missingok
notifempty
compress
copytruncate
}Ctrl+O, Enter, Ctrl+X).Because we used an MQTT Auto-Discovery payload, there is no YAML to configure!
2, prefix to k, and time unit to h.