Get your free server today! View Plans →
Home Plans Blog About Contact Panel Join Discord
Security

How to set up automatic security updates on a Linux server

Learn how to make a Linux server patch its own security holes automatically, with real config for unattended-upgrades and dnf-automatic plus safe reboot windows.

How to set up automatic security updates on a Linux server

By the end of this guide you'll have a Linux server that installs its own security patches without you logging in to do it by hand. We'll cover Debian and Ubuntu with unattended-upgrades, the Red Hat family (Fedora, Rocky, AlmaLinux, RHEL) with dnf-automatic, automatic reboots for kernel patches, and how to confirm the whole thing is actually working. It's written for anyone who runs a server, whether that's a game server, a website, a Discord bot, or a small VPS, and you don't need to be a Linux expert to follow along.

Why this matters more than you'd think

Most servers that get compromised aren't hit by some clever zero day attack. They get hit because a known bug sat unpatched for weeks or months. Someone published the fix, the bad guys read the same changelog, and they went looking for machines that never applied it. A server that patches itself closes that window fast.

The catch is that updates can occasionally break things. So the goal here isn't to blindly install everything the moment it ships. It's to install security patches automatically and quickly, while being a bit more careful with the rest. That's the balance we run on our own boxes, and it's the setup we'll build below.

One thing before you start. Take a backup or a snapshot first. If your host gives you snapshots (most VPS providers do), grab one now. That way if a patch ever does cause trouble, you can roll back in minutes instead of debugging at 2am.

Debian and Ubuntu with unattended-upgrades

Debian and Ubuntu use the same tool, called unattended-upgrades. It hooks into apt and runs on a timer. Let's install it and turn it on.

Step 1: Install the packages

Update your package list and install the tool. The apt-listchanges package is optional but handy, since it can summarize what changed.

sudo apt update
sudo apt install unattended-upgrades apt-listchanges

On a fresh Ubuntu install, unattended-upgrades is often already present. Installing it again does no harm, so run the command anyway to be sure.

Step 2: Enable it

There's a built in helper that flips the right switches for you. Run it and choose Yes when the blue dialog asks whether to download and install stable updates automatically.

sudo dpkg-reconfigure --priority=low unattended-upgrades

This writes a small file at /etc/apt/apt.conf.d/20auto-upgrades. You can check it, and if you ever want to skip the dialog, you can create the file yourself with these two lines:

cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

The first line tells apt to refresh its package list once a day. The second tells it to run unattended-upgrades once a day. The value "1" means every day. If you set it to "7" it would run weekly, but daily is what you want for security fixes.

Step 3: Tune what gets installed

The main config lives in /etc/apt/apt.conf.d/50unattended-upgrades. Open it with your editor of choice.

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Near the top you'll find an Allowed-Origins (or on newer Ubuntu, Origins-Pattern) block. This decides which repositories the tool is allowed to pull from. The default on Ubuntu keeps the security line active and comments out the rest. That's exactly what we want for a careful setup. Here's roughly what it looks like on Ubuntu:

Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // "${distro_id}:${distro_codename}-updates";
        // "${distro_id}:${distro_codename}-proposed";
        // "${distro_id}:${distro_codename}-backports";
};

The lines that start with // are switched off. If you want security only updates, leave -updates commented out. That's the safer choice for a production game server or website, since regular updates are more likely to change behavior. If you'd rather pull all updates, remove the // in front of the -updates line. Don't enable -proposed; that's a testing channel and it can ship half baked packages.

On Debian the origin names are slightly different. Look for entries referencing Debian-Security and make sure that one is active:

Unattended-Upgrade::Origins-Pattern {
        "origin=Debian,codename=${distro_codename},label=Debian-Security";
        "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};

Step 4: Set up automatic reboots for kernel patches

Some patches, especially kernel ones, only take effect after a reboot. By default the server installs them but waits for you to reboot manually. If you want it to handle that too, find these lines in the same 50unattended-upgrades file and edit them. They're usually present but commented out.

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

The first line turns reboots on. The third picks a quiet time, here 4am server time, so players or visitors aren't kicked off in the middle of the day. Pick an hour that's slow for your service. If your server runs something that really should never restart on its own, leave Automatic-Reboot as "false" and reboot yourself on a schedule you control.

A couple of other lines are worth setting while you're in there. These tell the tool to email you if something goes wrong, and to clean up old downloaded packages so the disk doesn't fill up:

Unattended-Upgrade::Mail "[email protected]";
Unattended-Upgrade::MailReport "on-change";
Unattended-Upgrade::Remove-Unused-Dependencies "true";

The mail lines need a working mail setup on the box (something like postfix or msmtp). If you don't have mail configured, skip those two lines for now. The logs will still record everything.

Step 5: Test it without waiting a day

You don't have to wait for the timer to find out if your config is sane. Run a dry run. This goes through the motions and tells you what it would install, without actually changing anything.

sudo unattended-upgrade --dry-run --debug

You'll see output listing the origins it checked and which packages match. If it prints something like "No packages found that can be upgraded unattended" and no errors, your config is valid and there's just nothing to do right now. If you see a clear list of packages and a clean exit, you're good.

To actually run it once by hand, drop the --dry-run flag:

sudo unattended-upgrade --debug

Fedora, Rocky, AlmaLinux and RHEL with dnf-automatic

The Red Hat family doesn't use apt. It uses dnf, and the automatic update tool is dnf-automatic. The idea is the same, but the files and commands differ.

Step 1: Install it

sudo dnf install dnf-automatic

Step 2: Configure security only or everything

The config file is /etc/dnf/automatic.conf. Open it up.

sudo nano /etc/dnf/automatic.conf

Two settings matter most. In the [commands] section, upgrade_type chooses what to install and apply_updates decides whether it installs them or just downloads them. For a security focused setup, use this:

[commands]
upgrade_type = security
download_updates = yes
apply_updates = yes

Setting upgrade_type = security limits it to security advisories. If you want every available update instead, change that to default. If you'd rather it only downloads patches and lets you apply them yourself, set apply_updates = no and you'll just get a notification. While you're in the file, the [emitters] section controls how you're notified. To get an email, set emit_via = email and fill in the email_from and email_to values.

Step 3: Turn on the timer

dnf-automatic runs through a systemd timer. Enable and start it so it fires on schedule and survives a reboot.

sudo systemctl enable --now dnf-automatic.timer

Confirm the timer is active and see when it's due to run next:

systemctl list-timers dnf-automatic.timer

You should see a line with a NEXT time and the timer marked active. By default it runs roughly once a day.

Step 4: Run it once to check

You can trigger the service immediately rather than waiting for the timer. This actually applies updates based on your config, so only run it when you're ready.

sudo systemctl start dnf-automatic.service

A note on reboots for the Red Hat family. dnf-automatic itself won't reboot the machine. If you want automatic reboots after a kernel update, the clean way is the dnf-automatic-restart approach or a small tool called needs-restarting, which ships with dnf-utils. You can check whether a reboot is needed at any time with:

sudo needs-restarting -r

If it says a reboot is required, schedule one for a quiet hour. Many admins pair this with a cron job that reboots in the early morning only when needed.

Confirm it actually ran

Setting this up and then never checking is how people get a false sense of safety. Verify it. On Debian and Ubuntu, the logs live in a dedicated folder. The main one tells you what was installed and when:

cat /var/log/unattended-upgrades/unattended-upgrades.log

You can also confirm the systemd timer that drives it is healthy:

systemctl status apt-daily-upgrade.timer
systemctl list-timers | grep apt

On the Red Hat side, check the journal for the service. This shows the last few runs and any errors:

journalctl -u dnf-automatic.service --since "-7 days"

If you ever want a quick look at what security updates are currently pending on a Red Hat box, that's a one liner too:

dnf updateinfo list security

Reducing the risk that an update breaks something

Automatic patching is a big net win, but a small number of updates do cause problems. Here's how we keep the risk low without giving up the benefit.

If you host a game server or anything player facing, like the Minecraft and game hosting we run at Bytte.cloud, lean toward security only patches plus a scheduled off peak reboot. Players notice a restart far more than they notice a quietly applied patch.

Troubleshooting

Updates aren't being applied

First, confirm the master switch is on. On Debian and Ubuntu, check /etc/apt/apt.conf.d/20auto-upgrades and make sure both lines read "1". A common mistake is that APT::Periodic::Unattended-Upgrade is set to "0". Then run the dry run, sudo unattended-upgrade --dry-run --debug, and read the output. It almost always tells you why a package was skipped. On Red Hat, run systemctl list-timers dnf-automatic.timer to be sure the timer is enabled, and check the journal for errors.

Some packages are held back

If you run a manual update and see "The following packages have been kept back," it usually means a package needs a new dependency that unattended-upgrades won't pull in on its own, often a phased rollout or a kernel package. That's normal and intentional. Security patches still flow. If you want to push the held back package through manually, run sudo apt full-upgrade at a time you're watching the server, not unattended.

The server rebooted when I didn't expect it

That's the automatic reboot setting doing its job. Open /etc/apt/apt.conf.d/50unattended-upgrades and check Unattended-Upgrade::Automatic-Reboot. Set it to "false" if you'd rather handle reboots yourself, or change Automatic-Reboot-Time to a quieter hour.

The disk filled up with old packages

Downloaded package archives can pile up. Clear them and let the tool prune automatically going forward by setting Unattended-Upgrade::Remove-Unused-Dependencies "true". To clean up right now on apt, run sudo apt autoremove and sudo apt clean. On dnf, sudo dnf clean packages does the same job.

Mail reports never arrive

The mail options only work if the server can actually send mail. If nothing shows up, you probably don't have an MTA installed or configured. Either set up a lightweight sender like msmtp, or drop the mail lines and rely on the logs instead. The patching still happens regardless; you just won't get the email.

"E: Could not get lock" errors

This means another apt process is already running, often the automatic update itself or the package list refresh. Wait a minute and try again. If it persists, find the process with ps aux | grep -i apt and let it finish rather than killing it midway, which can leave the package database in a bad state.

Wrapping up

You've now got a server that quietly keeps itself patched. On Debian and Ubuntu that's unattended-upgrades pulling the security channel daily, on the Red Hat family it's dnf-automatic on a systemd timer, and on both you've got a sensible reboot window and a way to read the logs. Set it once, check the logs a week later to confirm it's working, and then mostly forget about it. The few minutes you spent here saves you from being the easy target that gets caught by a months old bug. If you run anything important, pair this with regular snapshots and you've covered the two things that matter most: staying patched and being able to roll back.

Common questions

Should I install only security updates or all updates automatically?

For a production server, stick to security only. The security channel is small and well tested, while general updates change more behavior and are likelier to break something. On apt, leave the -updates line commented out in 50unattended-upgrades. On dnf, set upgrade_type = security.

Will automatic updates reboot my server?

Only if you tell them to. On Debian and Ubuntu, set Unattended-Upgrade::Automatic-Reboot to true and pick a quiet hour with Automatic-Reboot-Time. dnf-automatic never reboots on its own; you pair it with needs-restarting and a scheduled reboot if you want that.

How do I check that automatic updates actually ran?

On Debian and Ubuntu, read /var/log/unattended-upgrades/unattended-upgrades.log and run systemctl list-timers | grep apt. On the Red Hat family, run journalctl -u dnf-automatic.service and systemctl list-timers dnf-automatic.timer to confirm the timer is active.

What if an automatic update breaks my application?

Take a snapshot before enabling updates so you can roll back fast. Hold critical packages with apt-mark hold or a dnf exclude line, stick to security only patches, and read the email reports so you catch anything unusual early.

Why are some packages kept back during updates?

Held back usually means a package needs a new dependency the tool won't pull in unattended, often a kernel or a phased rollout. It is intentional and security patches still apply. Run sudo apt full-upgrade manually at a time you are watching the server if you want to push them through.

TR
Tom Reyes
Support Engineer at Bytte.cloud

Part of the Bytte.cloud team. We run game servers, bots and websites for a living, and we write these guides from what we see day to day in support and on our own servers.

Want to try this on real hardware?

Bytte.cloud has free plans for game servers, bots and websites. No credit card, set up in seconds.

Start for free See the plans