Step 0: Lock packages too sensitive to auto-update

Some packages are version-pinned for a reason — usually because a major-version bump breaks runtime compatibility. Common ones are java*, gcc, your database engine, and anything you've pinned through Terraform or AMI building.

The versionlock plugin makes those exclusions persistent.

# Amazon Linux 1 / 2 (yum)
sudo yum install yum-plugin-versionlock
sudo yum versionlock 'java-*' 'mariadb*'

# Amazon Linux 2023 (dnf)
sudo dnf install python3-dnf-plugin-versionlock
sudo dnf versionlock add 'java-*' 'mariadb*'

Inspect or clear:

sudo yum versionlock list
sudo yum versionlock clear

Amazon Linux 2: yum-cron

sudo yum install yum-cron
sudo nano /etc/yum/yum-cron.conf

Set:

update_cmd = security
apply_updates = yes
emit_via = email                    # or 'stdio' if you read journal logs
email_to = ops@yourdomain.com
download_updates = yes

Enable and start:

sudo systemctl enable --now yum-cron

Verify:

sudo systemctl status yum-cron
sudo journalctl -u yum-cron -n 50

Amazon Linux 1: same but older init

AL1 reached end-of-life on December 31, 2023 — you should not be running it any more. If you have to:

sudo yum install yum-cron
sudo service yum-cron start
sudo chkconfig yum-cron on

Configuration file is the same /etc/yum/yum-cron.conf.

Amazon Linux 2023: dnf-automatic

AL2023 replaced yum-cron with the upstream dnf-automatic system. The semantics are nearly identical, the file paths differ.

sudo dnf install dnf-automatic
sudo nano /etc/dnf/automatic.conf

Set:

[commands]
upgrade_type = security
download_updates = yes
apply_updates = yes
reboot = when-needed                # critical: applies kernel updates fully

[emitters]
emit_via = motd email

[email]
email_to = ops@yourdomain.com
email_from = root@$(hostname)

Enable the systemd timer (the daemon is stateless, the timer fires it once a day):

sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer

Verify it actually ran

The simplest sanity check is to wait for the next scheduled run, then look at the journal:

# AL2
sudo journalctl -u yum-cron --since "24 hours ago"

# AL2023
sudo journalctl -u dnf-automatic.service --since "24 hours ago"

You should see entries for "Downloading and applying updates" and a summary of what was installed (or "No packages marked for update").

Why kernel updates need a reboot

Auto-installing a kernel update without rebooting leaves your machine running the old kernel until something else triggers a reboot — often months later. The new kernel sits unused on disk, but more importantly the security fix you just installed isn't actually active.

dnf-automatic's reboot = when-needed setting handles this for you (it triggers a reboot only when an installed update actually requires one). On AL2, yum-cron doesn't have this; pair it with the needs-restarting command from yum-utils in a daily cron and reboot manually if it reports a kernel update.

Use AWS Systems Manager Patch Manager for fleets

If you have more than a handful of EC2 instances, configure patches centrally with SSM Patch Manager instead of doing this per host. You get patch baselines, maintenance windows, compliance reporting, and the ability to stagger reboots across an Auto Scaling group without losing capacity.