Proxmox Update Checker
Proxmox Update Checker
This Node-RED flow automatically checks for available package updates on a Proxmox node at scheduled times and generates a notification message if updates are found.
The flow uses the Proxmox API (nodes/pve/apt/versions) to retrieve the list of packages and compares installed versions with available ones. If updates exist, the flow formats them into a message and outputs it for debugging or further integration (e.g., sending notifications via Home Assistant, Telegram, or email).
Flow Overview
Components
cronplus
Triggers the flow at 06:00 and 18:00 every day.
Proxmox API (check update)
Queries Proxmox API endpoint: nodes//apt/versions to fetch available package versions for the selected node.
Find New Version (function)
Filters the API response to only include packages where OldVersion != Version.
Check list is not empty (function)
Ensures that only non-empty results are passed forward. If no updates are found, processing stops (no notification).
Make list (function)
Formats updates into a simple list of packages with their new versions.
Make message (function)
Builds a structured notification object with:
Title: "Proxmox updates available"
Message: "Packages to update:\n"
Debug nodes (debug 9 and debug 4)
Allow inspection of both the formatted list and the final notification object in the Node-RED debug sidebar.
Execution Flow
cronplus triggers the flow at the scheduled times.
Proxmox API node calls nodes/pve//versions.
Find New Version filters out only the packages that require an update.
Check list is not empty discards the message if no updates are available.
Make list produces a readable string with all upgradable packages.
Make message creates a structured notification object.
Debug nodes show the result for validation.
Example Output
If there are updates available, the notification object will look like:
json
{
"title": "Proxmox updates available",
"message": "Packages to update:\nproxmox-ve: 8.1-2\npve-manager: 8.1-3\nqemu-server: 8.1-1"
}
If no updates are available, the flow produces no output beyond the filtering stage.
Customization
Schedule:
Adjust the cron expression in the cronplus node for different times.
Notifications:
Replace/debug nodes with notification nodes (e.g., Home Assistant, Telegram, Email, Pushover).
Target node:
Modify the Proxmox API node to query a different Proxmox hostname or cluster node.
[{"id":"cd03ab3266d868a8","type":"tab","label":"check update proxmox","disabled":false,"info":"","env":[]},{"id":"d69566a73fad90a7","type":"proxmox-api","z":"cd03ab3266d868a8","name":"check update","path":"nodes/<NODE>/apt/versions","method":"GET","payload":"","server":"ad2b30f4130d3ff1","x":350,"y":80,"wires":[["eb6ea80485f5e272"]]},{"id":"8c48ada043fc5f3e","type":"debug","z":"cd03ab3266d868a8","name":"debug 4","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"data","targetType":"msg","statusVal":"","statusType":"auto","x":860,"y":360,"wires":[]},{"id":"eb6ea80485f5e272","type":"function","z":"cd03ab3266d868a8","name":"Find New Version","func":"msg.payload = msg.payload.filter(\n p => p.OldVersion && p.Version && p.OldVersion !== p.Version\n);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":80,"wires":[["5b102652432a6224"]]},{"id":"da8e339f1438c180","type":"function","z":"cd03ab3266d868a8","name":"make list","func":"let lines = msg.payload.map(p => `${p.Package}: ${p.Version}`);\nmsg.payload = lines.join('\\n');\n\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":580,"y":180,"wires":[["99780754f0ae4923","7db03965519e3fad"]]},{"id":"7db03965519e3fad","type":"function","z":"cd03ab3266d868a8","name":"make messge","func":"msg.data = {\n title: 'Proxmox updates available',\n message: `Packages to update:\\n${msg.payload}`\n};\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":280,"wires":[["8c48ada043fc5f3e"]]},{"id":"99780754f0ae4923","type":"debug","z":"cd03ab3266d868a8","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":780,"y":160,"wires":[]},{"id":"5b102652432a6224","type":"function","z":"cd03ab3266d868a8","name":"check list is not empty","func":"if (!Array.isArray(msg.payload) || msg.payload.length === 0) {\n return null;\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":180,"wires":[["da8e339f1438c180"]]},{"id":"2242d4504192893c","type":"cronplus","z":"cd03ab3266d868a8","name":"","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 6,18 * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":100,"y":80,"wires":[["d69566a73fad90a7"]]},{"id":"ad2b30f4130d3ff1","type":"proxmox-server","host":"10.10.10.10","port":8006},{"id":"7126e5ccd30f5607","type":"global-config","env":[],"modules":{"node-red-contrib-proxmox":"0.0.2","node-red-contrib-home-assistant-websocket":"0.77.2","node-red-contrib-cron-plus":"2.2.1"}}]