Files
MajorWiki/02-selfhosting/security/ansible-unattended-upgrades-fleet.md
MajorLinux 6592eb4fea wiki: audit fixes — broken links, wikilinks, frontmatter, stale content (66 files)
- Fixed 4 broken markdown links (bad relative paths in See Also sections)
- Corrected n8n port binding to 127.0.0.1:5678 (matches actual deployment)
- Updated SnapRAID article with actual majorhome paths (/majorRAID, disk1-3)
- Converted 67 Obsidian wikilinks to relative markdown links or plain text
- Added YAML frontmatter to 35 articles missing it entirely
- Completed frontmatter on 8 articles with missing fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:16:29 -04:00

95 lines
3.2 KiB
Markdown

---
title: Standardizing unattended-upgrades Across Ubuntu Fleet with Ansible
domain: selfhosting
category: security
tags:
- ansible
- ubuntu
- apt
- unattended-upgrades
- fleet-management
status: published
created: '2026-03-16'
updated: '2026-03-16'
---
# Standardizing unattended-upgrades Across Ubuntu Fleet with Ansible
When some Ubuntu hosts in a fleet self-update via `unattended-upgrades` and others don't, they drift apart over time — different kernel versions, different reboot states, inconsistent behavior. This article covers how to diagnose the drift and enforce uniform auto-update config across all Ubuntu hosts using Ansible.
## Diagnosing the Problem
If only some Ubuntu hosts are flagging for reboot, check:
```bash
# What triggered the reboot flag?
cat /var/run/reboot-required.pkgs
# Is unattended-upgrades installed and active?
systemctl status unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades
# When did apt last run?
ls -lt /var/log/apt/history.log*
```
The reboot flag is written to `/var/run/reboot-required` by `update-notifier-common` when packages like the kernel, glibc, or systemd are updated. If some hosts have `unattended-upgrades` running and others don't, the ones that self-updated will flag for reboot while the others lag behind.
## The Fix — Ansible Playbook
Add these tasks to your update playbook **before** the apt cache update step:
```yaml
- name: Ensure unattended-upgrades is installed on Ubuntu servers
ansible.builtin.apt:
name:
- unattended-upgrades
- update-notifier-common
state: present
update_cache: true
when: ansible_facts['os_family'] == "Debian"
- name: Enforce uniform auto-update config on Ubuntu servers
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
owner: root
group: root
mode: '0644'
when: ansible_facts['os_family'] == "Debian"
- name: Ensure unattended-upgrades service is enabled and running
ansible.builtin.systemd:
name: unattended-upgrades
enabled: true
state: started
when: ansible_facts['os_family'] == "Debian"
```
Running this across the `ubuntu` group ensures every host has the same config on every Ansible run — idempotent and safe.
## Rebooting Flagged Hosts
Once identified, reboot specific hosts without touching the rest:
```bash
# Reboot just the flagging hosts
ansible-playbook reboot.yml -l teelia,tttpod
# Run full update on remaining hosts to bring them up to the same kernel
ansible-playbook update.yml -l dca,majorlinux,majortoot
```
## Notes
- `unattended-upgrades` runs daily on its own schedule — hosts that haven't checked yet will lag behind but catch up within 24 hours
- The other hosts showing `ok` (not `changed`) on the config tasks means they were already correctly configured
- After a kernel update is pulled, only an actual reboot clears the `/var/run/reboot-required` flag — Ansible reporting the flag is informational only
## See Also
- [Ansible Getting Started](../../01-linux/shell-scripting/ansible-getting-started.md)
- [Linux Server Hardening Checklist](linux-server-hardening-checklist.md)