Ansible works when you run it. Ad-hoc runs drift. Schedule the patch playbook weekly and forget about it.
“Automation that doesn’t run is just documentation.”
“Same time tomorrow?” - Groundhog Day. Your cron should run the same playbook, same time, every week. Repetition is the point.
Why schedule?#
I used to run apt update && apt upgrade when something broke. Or when I remembered. Proxmox hosts drifted - one had a kernel from three months ago. The NIC bug fix? Never applied.
Scheduled runs: Same time every week. No human in the loop. Drift gets caught before it becomes a problem.
“Manual operations don’t scale. The only way to go fast is to automate the boring stuff.” - DevOps Handbook
The cron job#
# /etc/cron.d/ansible-proxmox-patch
# Run patch playbook weekly (Saturdays at 3 AM)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
0 3 * * 6 ansible-runner run /opt/ansible-proxmox-patch 2>&1 | logger -t ansible-patchOr with a wrapper script (recommended):
#!/bin/bash
# /usr/local/bin/proxmox-patch-cron.sh
set -e
cd /opt/proxmox-ops # or wherever the repo lives
/usr/bin/ansible-playbook playbooks/patch.yml -e manual_patch=true \
>> /var/log/ansible-patch.log 2>&1Cron:
# Run Saturdays at 3 AM
0 3 * * 6 /usr/local/bin/proxmox-patch-cron.shKey flags#
| Flag | Purpose |
|---|---|
-e manual_patch=true | Applies updates (otherwise patch playbook only reports) |
--limit opti-7080 | Patch one host at a time (safer for clusters) |
-e patching_reboot_policy=auto | Reboot if kernel update (use with caution) |
Default patching_reboot_policy: manual means the playbook applies packages but doesn’t reboot. You reboot during a maintenance window.
Where to run#
Options:
- Dedicated workstation - Always-on machine with SSH keys to Proxmox. Cron runs locally.
- Proxmox host - One node runs cron and patches the others (and itself last). Requires SSH keys between nodes.
- GitHub Actions - Scheduled workflow. Needs self-hosted runner or network access to hosts; otherwise use a different trigger.
For homelab, a NAS or always-on Linux box works. The cron user needs:
- Ansible installed
- SSH key to
ansible_useron each Proxmox host - Repo checked out (or use
ansible-pull)
Vault password#
If you use Ansible Vault, the cron job needs the password:
export ANSIBLE_VAULT_PASSWORD_FILE=/etc/ansible/.vault-pass
/usr/bin/ansible-playbook playbooks/patch.yml -e manual_patch=trueStore /etc/ansible/.vault-pass with restricted permissions (chmod 600). Or use --ask-vault-pass and an expect script - messier.
Logging and alerting#
Append to a log file:
/usr/bin/ansible-playbook playbooks/patch.yml -e manual_patch=true \
>> /var/log/ansible-patch.log 2>&1Pipe to logger for syslog:
... 2>&1 | logger -t ansible-patchFor alerts on failure, add exit-code handling:
/usr/bin/ansible-playbook playbooks/patch.yml -e manual_patch=true
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "Ansible patch failed with $STATUS" | mail -s "Proxmox patch failed" admin@example.com
fi
exit $STATUSOr integrate with monitoring (heartbeat on success, alert on missed heartbeat).
site.yml vs patch.yml#
| Playbook | Schedule | Purpose |
|---|---|---|
patch.yml | Weekly | Updates only. Fast. Low risk. |
site.yml | Monthly or on change | Full config. Patching + security + backup. Catches drift. |
Run patch.yml weekly. Run site.yml when you change playbooks or add hosts. Or schedule site.yml monthly as a full reconciliation.
What I learned#
“Automation without monitoring is blind. Add a heartbeat so you know when it stops beating.” - See monitoring
Start with patch, not site. I scheduled site.yml weekly. Full config every time. Overkill. Patching is the high-frequency need - packages drift constantly. Security and backup config change maybe once a quarter. Run patch weekly. Run site monthly. Or when you change things. Your cron will thank you.
Don’t auto-reboot in cron. I made this mistake once. patching_reboot_policy: auto. Saturday 3am. Cron ran. Kernel update on pve-node-2. Host rebooted. While I had a VM live-migrating off it - I’d started the migration before bed. The migration failed mid-transfer. The VM (Plex, naturally) went down. I woke up to Uptime Kuma alerts and an angry household. Learn from my terrible life choices. Reboot during a maintenance window. When you’re awake. With coffee.
Log somewhere. Cron ran. Something failed. I had no idea what. Or when. Or why. The only evidence was “Ansible patch didn’t run this week” from the monitoring alert. Log to /var/log/ansible-patch.log or syslog. When something breaks at 3am, you need to know what actually ran. Trust me on this.
References#
- Managing Proxmox with Ansible
- Patching role -
patching_reboot_policy,manual_patch