Story / scenario opener
You installed Fedora six months ago. You run sudo dnf upgrade every few weeks when you remember. Last Tuesday a critical CVE dropped for a library you depend on. You didn't patch until Friday. The system is safe, but the anxiety is real. You want the system to handle the boring part. You want security updates to land without you thinking about it. dnf-automatic does exactly that. It runs in the background, downloads updates, and applies them on a schedule you control.
What's actually happening
dnf-automatic is a systemd timer that triggers a service. The service calls dnf with specific flags to download and install updates. It doesn't replace your manual updates. It supplements them. The configuration lives in /etc/dnf/automatic.conf. This file controls behavior. By default, it downloads updates but does not install them. You have to change the config to enable automatic installation. This default exists for a reason. Automatic installation can break things if a repository has a conflict or if a kernel update requires a reboot that interrupts a workflow. The tool gives you the mechanism. You set the policy.
Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. Fedora's package manager respects this hierarchy. If you edit the wrong file, your changes vanish on the next package update.
Edit the config before you enable the timer. The default behavior is safe but passive.
Install and enable the timer
Here's how to install the tool and activate the daily timer.
sudo dnf install -y dnf-automatic # Install the automatic update tool
sudo systemctl enable --now dnf-automatic.timer # Start the daily timer immediately
The timer runs once a day by default. You can change the schedule by editing the timer unit, but the daily cadence works for most users. dnf upgrade --refresh is the normal weekly maintenance command for manual updates. dnf-automatic handles the daily routine. They are different workflows. Don't conflate them.
Verify the timer is active. Look for active (waiting) in the output.
systemctl status dnf-automatic.timer # Verify the timer is active and scheduled
Run journalctl first. Read the actual error before guessing.
Configure automatic installation
Here's how to enable automatic installation in the configuration file.
# /etc/dnf/automatic.conf
# ...
# Download updates automatically
download_updates = yes
# Install updates automatically
apply_updates = yes # Change from no to yes to enable automatic installation
The apply_updates setting controls whether dnf installs the downloaded packages. The default is no. Change it to yes to allow automatic installation. The download_updates setting controls whether packages are fetched. Keep this yes. If you set download_updates = no, the timer does nothing useful.
You can limit updates to security fixes. This reduces the risk of breaking changes while keeping the system secure. Set upgrade_type = security.
Here's how to restrict automatic updates to security fixes only.
# /etc/dnf/automatic.conf
# Only install security updates
upgrade_type = security # Filter updates to security fixes only
# Apply updates automatically
apply_updates = yes
The security type checks the update metadata for security advisories. Only packages with a security flag get installed. This is a common pattern for servers where stability matters more than new features. Desktop users often prefer default to get all updates.
Configure the delay if you manage a fleet. Mirrors appreciate the load distribution.
Add a random delay
Here's how to add a random delay to distribute load across mirrors.
# /etc/dnf/automatic.conf
# Add a random delay to avoid hammering mirrors
random_delay = 3600 # Delay up to 1 hour before running
The random_delay setting adds a random wait time before the update runs. The value is in seconds. 3600 means up to one hour. If you run ten machines with this setting, they won't all hit the mirrors at the exact same second. This prevents thundering herd problems. Fedora mirrors handle load well, but the courtesy helps the community.
Check the logs after a failure. The timer retries daily, but the conflict won't resolve itself.
Configure reboot behavior
Here's how to configure reboot behavior to avoid unexpected restarts.
# /etc/dnf/automatic.conf
# Reboot only if kernel or systemd updates are installed
reboot = when-needed # Prevents reboot on every update cycle
Kernel updates require a reboot. dnf-automatic can reboot the system automatically. This is dangerous for a desktop. Set reboot = when-needed or reboot = no. The when-needed option reboots only if a kernel or systemd update is installed. The no option never reboots. You must reboot manually. For a headless server, reboot = always might be acceptable if you have no active sessions. For a workstation, when-needed is the safest choice.
SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. If dnf-automatic fails with a permission error, check the SELinux logs. The tool runs with the correct context by default. Manual edits to the service file can break the context.
Snapshot the system before the upgrade. Future-you will thank you.
Verify it worked
Here's how to verify the timer is active and review recent update activity.
systemctl status dnf-automatic.timer # Verify the timer is active and scheduled
journalctl -u dnf-automatic.service --since today # Review today's update activity
The systemctl status command shows the timer state. Look for active (waiting) and the next trigger time. The journalctl command shows the logs from the service. Look for Installed: lines to confirm updates applied. Look for Error: lines to find failures.
journalctl -xeu dnf-automatic.service reads better than journalctl alone. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style. Use that pattern here.
If you see Error: Transaction test error: package python3-3.12.x conflicts with python3-3.3.y in the logs, the update failed. The conflict is real. dnf aborted the transaction. The timer will try again tomorrow. You need to investigate the conflict. Manual intervention is required.
Trust the package manager. Manual file edits drift, snapshots stay.
Common pitfalls
Automatic updates can fail silently if the transaction test fails. If a package conflicts, dnf aborts. The timer runs again tomorrow. You won't get a notification unless you check logs. The dnf upgrade command will refuse to proceed and print Error: Transaction test error: package kernel-6.x conflicts with kernel-6.y. The conflict is intentional. Read the next paragraph before forcing.
Third-party repositories can cause conflicts. If you use RPM Fusion or custom repos, dnf-automatic includes them. Conflicts here are common. Check the logs. If a third-party repo is broken, dnf-automatic will fail. You might need to disable the repo temporarily.
sudo dnf config-manager --set-disabled <repo-name> # Disable a problematic repo temporarily
Reboot policies can surprise you. If you set reboot = when-needed and a kernel update installs, the system reboots. If you have unsaved work, you lose it. Plan your workflow. Run heavy tasks outside the update window. The timer runs at a fixed time. Check the timer unit to see when it triggers.
systemctl status <unit> shows recent log lines AND state in one view. Always check status before restart. If you need to force a run, use systemctl start dnf-automatic.service. This bypasses the timer. Use this for testing, not for production.
Reboot before you debug. Half the time the symptom is gone.
When to use this vs alternatives
Use dnf-automatic with apply_updates = yes when you run a server or a workstation that can tolerate automatic reboots during maintenance windows.
Use dnf-automatic with apply_updates = no when you want updates downloaded and ready but you prefer to apply them manually to control the reboot timing.
Use manual sudo dnf upgrade when you need immediate control over every transaction and want to inspect changelogs before installing.
Use dnf-automatic on a headless server when you cannot log in daily but need security patches applied without intervention.
Stay on manual updates if you run development environments where package conflicts are common and automatic resolution might break your toolchain.