How to Set dnf-automatic Security Updates for Rocky/Alma
Set up dnf-automatic for Rocky Linux and AlmaLinux 9: security-only updates, systemd timer, email alerts, and reboot rules. DNF5 on version 10 differs.
Wetin dnf-automatic dey do for Rocky Linux and AlmaLinux
dnf-automatic na how you dey get unattended security updates for Rocky Linux and AlmaLinux. Na one small program wey systemd timer dey start, e dey read /etc/dnf/automatic.conf and apply wetin that file allow. Installation na one command. The rest of this guide dey explain settings wey decide whether e go protect the box or quietly do nothing.
If you come from Debian or Ubuntu, na the same work unattended-upgrades dey do for Ubuntu VPS. One difference important pass all the others: wetin the word "security" mean to the package manager. For Ubuntu, na separate archive pocket. For the RHEL family, na metadata wey dey attached to published advisories, and that metadata fit dey missing or out of date. If you point dnf-automatic to repository wey no get advisory data, e no install anything even as e report success.
This guide dey based on Rocky Linux 9 and AlmaLinux 9, wey use DNF 4 (DNF na the package manager for the RHEL family), as of August 2026. The 10 releases don move to DNF5 and the names change there, so dem get their own section near the end. Every command below na one wey you go run for your own box, with the output wey you suppose expect beside am.
Install dnf-automatic and read the config wey e ship
You suppose add automatic updates to the rest setup for the first ten minutes for new VPS, immediately after you don get non-root user and firewall.
sudo dnf install -y dnf-automatic
rpm -q dnf dnf-automatic
systemctl is-enabled dnf-automatic.timersystemctl is-enabled dey print disabled for fresh install, because installing the package no start anything. Na this be the most common reason why server wey get "dnf-automatic" never apply any update.
DNF version matter for one option. The reboot setting enter upstream for DNF 4.15, and Red Hat backport am into dnf-4.14.0-6.el9 for November 2023 through advisory RHBA-2023:6645. Rocky 9 and AlmaLinux 9 rebuild that package, so current box get am, but box wey nobody touch since 2023 no get am.
Config file na /etc/dnf/automatic.conf. The shipped copy list every option wey this build understand, with the default value commented out. Read am once before you edit am, because that file na the correct source for your version.
Switch wey decide wetin go happen
download_updates and apply_updates for [commands] section na dem dey decide the behaviour. By default, both dey no for EL9 (enterprise Linux 9, the shared base of Rocky 9 and AlmaLinux 9). So, if you enable dnf-automatic without editing am, e go only tell you wetin dey available.
- Both
no: dnf-automatic go report available updates, and e no go change anything for the box. download_updates = yeswithapply_updates = no: packages go download enter DNF cache. Installation go quick and e no need network, but nothing don change tonight.- Both
yeswithupgrade_type = default: every available update go install, whether security update or not. - Both
yeswithupgrade_type = security: na only packages wey security advisory name go install.
A reasonable starting point for a public-facing VPS:
[commands]
upgrade_type = security
download_updates = yes
apply_updates = yes
random_sleep = 0
network_online_timeout = 60
reboot = nevernetwork_online_timeout na how many seconds the run go wait for working network before e give up. This matter for box wey just boot. random_sleep na older way to spread load across many machines, but timer dey do that work now. Run systemctl cat dnf-automatic.service to see the exact flags wey the shipped service dey pass.
Prove say the file dey do wetin you expect, without waiting until 06:00:
sudo systemctl start dnf-automatic.service
sudo journalctl -u dnf-automatic.service -n 50 --no-pagerJournal go show wetin the run check and wetin e do. You fit also force one behaviour from command line. This one go override the file for only that run:
sudo dnf-automatic --downloadupdates --no-installupdatesWetin upgrade_type = security really mean for Rocky and Alma
DNF no dey know say update na security update by comparing version numbers. E dey read errata metadata: file wey dem call updateinfo.xml wey dem publish inside repository, where each advisory list the packages wey fix am. AlmaLinux dey publish dem as ALSA advisories, while Rocky dey publish dem as RLSA. upgrade_type = security dey build filter from that metadata, then e upgrade only packages wey match am.
Two things follow from this, and both fit surprise people.
First, if metadata no dey, no update go happen. If repository no carry updateinfo.xml, the filter no go match anything, and the run go end with this line for journal:
No security updates needed, but 3 updates availableThe box no dey patched, and nothing report failure. Check am yourself:
dnf updateinfo list --security
dnf check-updateIf dnf check-update list packages while dnf updateinfo list --security no print anything at all, either no pending update carry advisory, or repository no get advisory data wey e fit read. Rocky and AlmaLinux both dey publish am, so for those two, empty list usually mean say nothing dey pending. CentOS Stream no dey publish am at all.
Second, security mode no be minimal change. dnf-automatic dey add security filter, then e run the normal upgrade path. So package wey advisory name go move to the newest version for repository, and e go carry its dependencies along. The smaller step, wey move only to the earliest version wey fix the advisory, na dnf upgrade-minimal --security wey you go run by hand. dnf-automatic no get setting for am.
One more warning apply to Rocky. Rocky dey generate its errata from Red Hat data through its own pipeline, and that pipeline don fall behind. For September 2025, users report say Rocky 9 BaseOS updateinfo.xml never move since December 2024. Because of that, --security no get recent advisories, and Rocky staff confirm say na known issue. If you depend on upgrade_type = security, compare the advisory list with recent RLSA announcements from time to time. For box where coverage matter pass change control, upgrade_type = default on schedule wey you choose na the safer setting.
systemd timer wey actually dey run am
sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timerlist-timers suppose print one row wey get NEXT time wey dey about one day from now. Empty table mean say timer no dey enabled, so nothing go ever run.
The timer wey package provide dey run for *-*-* 6:00 with RandomizedDelaySec=60m and Persistent=true. The random delay dey spread the servers across one hour, so every server no go hit the mirror for the same second. Persistent=true mean say machine wey dey powered off for 06:00 go run the missed job shortly after e boot, instead of skipping that day.
Change the schedule with drop-in. No edit the unit wey package provide, because package upgrade go replace files under /usr/lib/systemd/system.
sudo systemctl edit dnf-automatic.timer[Timer]
OnCalendar=
OnCalendar=*-*-* 03:30
RandomizedDelaySec=30mThe empty OnCalendar= line dey required. OnCalendar dey accumulate, so if you no add that reset, you go keep the 06:00 entry and add another one, then the job go run twice every day. Confirm the result with systemctl list-timers dnf-automatic.timer and read the NEXT column. The same drop-in rules apply to anything else wey you schedule. writing systemd service and timer units cover that topic.
Now make we look the trap. The package ship three more timers: dnf-automatic-notifyonly.timer, dnf-automatic-download.timer and dnf-automatic-install.timer. Each one start the same program with command-line flags, and those flags override download_updates and apply_updates from your config file. If you enable one of dem beside dnf-automatic.timer, the job go run twice with two different behaviours. E go look exactly like say your config file dey ignored. Enable one timer and check:
systemctl list-unit-files 'dnf-automatic*'How I fit know when dem install something?
emit_via for [emitters] section dey control reporting. Under systemd, stdio emitter dey write go the journal. Na the dependable option because e no need anything else wey dem install:
sudo journalctl -u dnf-automatic.service --since -7d --no-pagermotd emitter dey write the report inside /etc/motd and replace wetin dey inside that file. If you keep login banner for there, no include this emitter.
email emitter dey open SMTP (simple mail transfer protocol) connection go email_host for email_port. Dem default to localhost and 25. Fresh VPS no get anything wey dey listen there, so connection go dey refused and no mail go send. Run ss -lnt | grep ':25' before you depend on am, and set up relay-only Postfix if output empty. When mail dey work, subject go read Updates applied on 'web01'., and e dey take the name from system_name.
For anything else, command emitter dey hand the report give your program through standard input:
[emitters]
emit_via = stdio, command
system_name = web01.example.com
send_error_messages = yes
[command]
command_format = /usr/local/bin/notify-ops
stdin_format = {body}send_error_messages default to no, meaning say failed run no go report anything. Turn am on. Patching system wey only announce successful runs worse pass no system, because the silence go look like everything dey healthy.
dnf-automatic no dey restart your services
Installing package dey replace files for disk. Process wey already dey run keep the old code for memory, so patched library no dey help daemon wey start last month. This difference between installed and active na why unattended patching need restart policy, no be install policy only.
sudo dnf install -y dnf-plugins-core
dnf needs-restarting -s
dnf needs-restarting -r-s dey list systemd services wey their files change after dem start. -r dey answer one question, and e dey print one of two blocks:
Core libraries or services have been updated since boot-up:
* kernel
Reboot is required to fully utilize these updates.No core libraries or services have been updated since boot-up.
Reboot should not be necessary.-r no be deep analysis. E dey check fixed list of packages: kernel, kernel-core, kernel-rt, glibc, linux-firmware, systemd, dbus, dbus-broker, dbus-daemon and microcode_ctl. If dem install any one of dem after the last boot, you go get the first answer. Add your own package names for file wey end with .conf under /etc/dnf/plugins/needs-restarting.d/ when another thing for the box also need reboot before e go take effect.
One thing to note for scripts: dnf needs-restarting -r dey exit non-zero both when reboot dey required and when the command itself fail, so exit status alone no fit tell the two cases apart. Read the output text.
Restarting service na the smaller action and most times na the correct one. Restart SSH daemon from second SSH session wey already dey open, so bad config no go lock you out. New kernel na the case wey only reboot fit solve, because running kernel no fit replace itself in place.
Box suppose e reboot by itself?
[commands]
reboot = when-needed
reboot_command = shutdown -r +5 'Rebooting after applying package updates'reboot = never na the default. when-changed dey reboot after any update wey apply. when-needed dey reboot only when the check behind needs-restarting -r talk say dem replace core package, and na wetin most people wey dey manage one server want, together with timer window wey dem choose by themselves. The default reboot_command dey give users wey don log in five minutes warning through shutdown, and you fit make the time longer.
Settle two things before you enable this. Every service wey you depend on must start by itself during boot. This na the common problem with a Docker Compose stack wey person start by hand. You also need console or rescue access from your provider, because kernel wey no boot no fit repair through SSH. If any of these two things no dey, leave reboot = never enabled and reboot by yourself after you read the journal.
Rocky, AlmaLinux and CentOS Stream: dem differ for where
For Rocky 9 and AlmaLinux 9, everything we talk before na the same, including config path and unit names. Both dey publish errata, so upgrade_type = security get data wey e fit filter.
CentOS Stream na the exception, and the difference serious. Stream repositories no carry updateinfo.xml, so the security filter no fit match and every run dey report No security updates needed. For Stream, use upgrade_type = default and accept say you dey take every update. Stream also dey ahead of RHEL, so that setting go move more for Stream machine pass the same setting for Rocky or AlmaLinux.
Rocky 10 and AlmaLinux 10 don move to DNF5, and DNF5 rename some things. The upstream DNF5 documentation give the timer as dnf5-automatic.timer, put the defaults wey package ship with for /usr/share/dnf5/dnf5-plugins/automatic.conf while your overrides still dey for /etc/dnf/automatic.conf, set download_updates to yes instead of no by default, and add distro-sync as an upgrade_type. The advisory query na dnf advisory list, while updateinfo remain as alias. Confirm wetin your release really install before you copy package or unit names from guide wey dem write for 9:
dnf list --available '*automatic*'
systemctl list-unit-files '*automatic*'Many guides wey people publish for this topic still cover Rocky 8 only. The options don increase since dem write those guides, so check the commented file for your own machine instead of trusting old article.
Failure modes and the strings you will see
Nothing ever runs. systemctl list-timers dnf-automatic.timer go print empty table, while systemctl is-enabled dnf-automatic.timer go print disabled. Dem install the package, but dem never create the timer.
The job runs and installs nothing. Journal get No security updates needed, but 3 updates available. Security filter no match anything, either because nothing wey dey pending get advisory, or because repository no publish advisory data.
A setting looks ignored. DNF dey log unknown option for automatic.conf at debug level, then e use the default. So misspelled key no change anything and no warn anybody. Write apply_update = yes, and apply_updates go remain at no. This one make the box download forever but never install anything. After any edit, run sudo systemctl start dnf-automatic.service and read the journal instead of trusting the file.
The job runs twice a day. Two timers dey enabled. systemctl list-unit-files 'dnf-automatic*' go show which ones, and the extra ones dey pass flags wey override your config file.
No mail arrives. Either nothing dey listen on port 25 for the email emitter, or send_error_messages still dey no and the only thing worth reporting na error.
A patched service still reports the old version. File for disk don new, but process for memory still old. dnf needs-restarting -s go name the services wey need restart.
FAQ
Dnf-automatic dey install only security updates for Rocky Linux?
Na only if you set upgrade_type = security for /etc/dnf/automatic.conf, and only if your repositories publish errata metadata. Rocky Linux and AlmaLinux both dey publish am, so the filter get advisories wey e fit match. The default wey come with am na upgrade_type = default, wey dey install every available update once apply_updates = yes.
Why dnf-automatic dey report "No security updates needed, but 3 updates available"?
DNF dey decide wetin count as security update by reading updateinfo.xml from the repository, where every advisory list the packages wey fix am. If this metadata miss or don old, the security filter no match anything while ordinary updates still dey wait. Na this one dey produce exactly that line. This one dey expected for CentOS Stream, because e no publish errata at all. For Rocky or AlmaLinux, compare dnf updateinfo list --security with dnf check-update and check say your metadata current.
Dnf-automatic go reboot my server after kernel update?
No, unless you tell am make e do so. The reboot option default na never. Set reboot = when-needed, and one run go reboot only when the check behind dnf needs-restarting -r find say core package like kernel or glibc don change since boot. reboot = when-changed dey reboot after any update wey e apply. Both dey use reboot_command, wey default na shutdown -r +5 with warning message for users wey dey logged in.
How I fit change the time wey dnf-automatic dey run?
Run sudo systemctl edit dnf-automatic.timer and add [Timer] section with empty OnCalendar= line, then put your schedule after am, for example OnCalendar=*-*-* 03:30. The empty line dey required because OnCalendar dey accumulate. If you leave am out, e go keep the shipped 06:00 run and add another one. Verify with systemctl list-timers dnf-automatic.timer and read the NEXT column.
I still need check server wey dey patch itself?
Yes. dnf-automatic dey install packages and stop there. E no restart daemons, and e no report anything wey you go see unless emit_via name an emitter wey you actually dey read. Set emit_via to stdio at minimum, turn on send_error_messages so dem fit report failures too, and run dnf needs-restarting -s after patch window to find services wey still dey run old code.