Skip to content

Production Updates: A Safe and Predictable Upgrade Policy

The previous articles covered installing, upgrading, and managing packages through apt, dpkg, and Snap. On a workstation, running apt upgrade at any moment is low-risk — worst case, you restart a browser. On a production server, the exact same command carries different weight: an untested update applied at the wrong time can stop a service, break configuration, or force a reboot — all of which have a real, visible impact on users.

This article is not about a new command — it is about when, in what order, and with what precautions you should apply the apt/dpkg commands you already know. It covers the difference between a security patch and a larger version update, the tools that automate that safely, and what to check after an update actually lands.

Security Updates vs. Ordinary Updates: Why They Are Not the Same

Ubuntu's repository separates two distinct update streams:

  • security updates — arrive from a dedicated repository such as noble-security, address a specific identified vulnerability, and barely change the software's external behavior; this is the layer that shows up as a separate source in apt-cache policy output;
  • ordinary version updates (feature/point updates) — arrive from noble-updates, and may bring a new feature, a changed default setting, or a newer major library version.

This distinction matters in practice: delaying a security update means leaving the system exposed to a known vulnerability, so it is usually applied as quickly as possible, often automatically. An ordinary version update brings more change, so it is normally tested in a staging environment first before reaching production.

apt-get upgrade -s

-s (simulate) shows which packages would be upgraded without changing anything. For each listed package, apt-cache policy <package> reveals whether it is coming from noble-security or noble-updates.

Applying Only Security Updates

Sometimes a production server needs only the security patches applied immediately, with everything else deferred to the next scheduled maintenance window. Separating this by filename alone is not reliable — on Ubuntu 24.04, the standard ubuntu.sources file described in apt and Repositories combines noble, noble-updates, and noble-security into a single file, so there is usually no separate "security only" file to point at.

The filtering actually happens by source origin, not by file — which is exactly how the unattended-upgrades tool covered below operates. To preview which packages it would apply before actually running it:

sudo unattended-upgrade --dry-run -d

--dry-run installs nothing; -d (debug) shows in detail which package is selected from which origin. This is a far more reliable, officially supported path than trying to filter apt-get flags by hand.

unattended-upgrades: Automating Security Patches

unattended-upgrades is Ubuntu's official package for keeping a system updated independently, on a schedule, from designated repositories (usually security only). Install it with:

sudo apt install unattended-upgrades

Main configuration lives in /etc/apt/apt.conf.d/50unattended-upgrades:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
  • Allowed-Origins defines which sources are eligible for automatic updates — by default usually only the -security layer; -updates is added only as a deliberate administrator choice;
  • Automatic-Reboot controls whether the system should reboot itself automatically if an update requires it.

Danger

Automatic-Reboot "true" is a setting to use with caution on a production server: it can reboot the machine without asking, once a kernel patch is installed. If long-running processes or minimizing visible service interruption matter on this server, leave this false and perform the reboot manually, during a scheduled maintenance window, using the method covered below. Even if automatic reboot is genuinely needed, use Automatic-Reboot-Time to pin it to a specific, low-traffic time (for example, overnight).

Check whether it is enabled:

systemctl status unattended-upgrades.service
cat /etc/apt/apt.conf.d/20auto-upgrades

The second command typically shows:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

1 means enabled, 0 means disabled. This file enables a systemd timer-driven mechanism that runs daily — similar in spirit to the scheduling concept covered later in Cron Basics, but specific to apt.

Updates That Require a Reboot

When the kernel, glibc, or certain core libraries are updated, the change only fully takes effect after a reboot — a running process keeps its old code copy in memory in the meantime. Ubuntu signals this with a dedicated flag file:

cat /var/run/reboot-required

If present:

*** System restart required ***

If absent, cat reports "No such file or directory" — a good sign, meaning a reboot is not currently required. To see which package specifically triggered this requirement:

cat /var/run/reboot-required.pkgs

Tip

Hook these two files into your monitoring — a daily cron check or an existing monitoring tool — as a simple, reliable way to avoid manually forgetting whether a production server needs a reboot.

When a reboot is required, it is standard practice to schedule it rather than perform it immediately:

sudo shutdown -r +5 "Scheduled reboot: security patch"

+5 means the reboot happens in 5 minutes, and a warning message is sent to connected users. To cancel it:

sudo shutdown -c

Which Services Need Restarting: needrestart

Aside from the kernel, many package updates (a new openssl version, for example) only fully take effect once the running process using that library is restarted — the process keeps the old library copy resident in memory otherwise. Tracking this manually is impractical, so use needrestart:

sudo apt install needrestart
sudo needrestart

Sample output:

Services to be restarted:
 systemctl restart nginx.service
 systemctl restart ssh.service

This is a direct, practical application of the idea covered in /proc Filesystem: needrestart searches /proc/*/maps for old, deleted-but-still-referenced library copies and identifies which process still depends on them.

Warning

Many .deb package install scripts automatically restart the affected service during an update, but this is not always guaranteed — especially when the updated package is only a library with no direct awareness of which service depends on it. Running needrestart routinely after any update is a reliable way to catch a service still running against an outdated library.

apt-mark hold: Deliberately Skipping an Update

apt-mark hold, covered in apt and Repositories, takes on particular importance in production: if your application is confirmed to depend on a specific version (a database driver, for instance), you can deliberately keep that package at its current version:

sudo apt-mark hold postgresql-16

This setting is respected even alongside unattended-upgrades — a held package is skipped by automatic updates too. But leaving this forgotten indefinitely is risky: a held package also stops receiving security patches, so periodically review the list of held packages:

apt-mark showhold

Major Version Upgrades: do-release-upgrade

Moving from one Ubuntu LTS version to the next (for example, 22.04 to 24.04) is not done with apt upgrade/full-upgrade — it uses a dedicated tool, do-release-upgrade, because this operation replaces hundreds of packages and can involve configuration format changes as well.

sudo do-release-upgrade

Danger

do-release-upgrade is the heaviest, most far-reaching operation covered in this module. Never run it directly on a production server without preparation:

  1. take a snapshot or full backup first (at the disk level, or via your cloud provider's VM snapshot tool);
  2. fully test it first on a staging server with an identical configuration;
  3. prepare a fallback access path (such as console access) in case the SSH connection drops during the process — do-release-upgrade usually prompts for this itself;
  4. only start the process during a scheduled, sufficiently long maintenance window — it can take several hours;
  5. if something goes wrong, restoring from the prepared backup is the most reliable "rollback" strategy, since attempting to reverse a partially upgraded system is often unreliable.

A Practical Scenario: A Weekly Update Check

Problem. You manage a small production server and review its security status manually each week, applying updates during a scheduled window when needed.

Step 1. See what updates are available (nothing changes yet).

sudo apt update
apt list --upgradable
Listing... Done
nginx/noble-security 1.24.0-2ubuntu7.1 amd64 [upgradable from: 1.24.0-2ubuntu7]
openssl/noble-security 3.0.13-0ubuntu3.4 amd64 [upgradable from: 3.0.13-0ubuntu3.3]

Both packages come from noble-security — meaning these are security patches that should not be delayed.

Step 2. Simulate the change.

apt-get upgrade -s

Step 3. Apply the update.

sudo apt upgrade -y

Step 4. Check whether a reboot is required.

cat /var/run/reboot-required 2>/dev/null || echo "reboot not required"

Step 5. Check which services need restarting.

sudo needrestart

Verify:

apt list --upgradable

An empty result confirms every available update was successfully applied.

Conclusion. The weekly check is five short commands, but their order matters: see what would change, apply it, then check whether a reboot or service restart is needed — never "update and forget."

Common Mistakes

Forgetting to Restart a Service After an Update

A package is updated, but the running process keeps using its old library copy — from the outside, everything can look fine, while the service is actually still running old, possibly vulnerable code. Make needrestart a routine habit after every update.

Enabling unattended-upgrades and Then Never Checking It Again

Once automatic updates are configured, never reviewing what they actually apply — including never checking /var/log/unattended-upgrades/unattended-upgrades.log — leads to discovering a problem much later than necessary.

Running a Major Version Upgrade Without a Backup

Running do-release-upgrade without a prior snapshot risks leaving the system unusable if the process is interrupted or hits a configuration mismatch, with no reliable way back without a prepared backup.

Forgetting About a Held Package Entirely

A held package does not receive security patches. Failing to periodically check apt-mark showhold gradually leaves the system exposed to known vulnerabilities.

Exercises

  1. Use apt list --upgradable to see how many updates are pending on your system, then determine each package's origin with apt-cache policy <package> and separate security updates from ordinary ones.
  2. Check with systemctl status unattended-upgrades.service and cat /etc/apt/apt.conf.d/20auto-upgrades whether automatic updates are enabled on your system.
  3. Run cat /var/run/reboot-required 2>/dev/null and sudo needrestart (if installed) and determine whether your system currently requires a reboot or a service restart — these commands only check, they change nothing.

Verification criterion: for each exercise, you should be able to clearly distinguish a security update from an ordinary one, state definitively whether your system currently requires a reboot, and justify why a backup is essential before any major upgrade.

Summary

Updating a production server uses the exact same apt upgrade command as anywhere else, but the approach around it is entirely different: separating security updates from ordinary ones, deliberately configuring automation (unattended-upgrades), checking whether a reboot or service restart is needed, managing held packages, and always taking a backup before a major version transition — all of it serves one goal: making updates predictable rather than a source of unexpected downtime.

This module has now covered a package's entire life cycle in the Debian/Ubuntu ecosystem — from basic concepts, through the apt/dpkg pair, to Snap, and finally to a production update policy. The next article, RPM, YUM, and DNF, covers the same ideas as they appear in the RHEL family (Rocky Linux, AlmaLinux, Fedora) — essential knowledge for anyone working in a mixed environment.

References

  • Ubuntu Server documentation: automatic updates (unattended-upgrades): https://ubuntu.com/server/docs/automatic-updates
  • Ubuntu Server documentation: package management: https://ubuntu.com/server/docs/package-management
  • Debian Wiki: UnattendedUpgrades: https://wiki.debian.org/UnattendedUpgrades
  • Ubuntu manual page: do-release-upgrade(8): https://manpages.ubuntu.com/manpages/noble/man8/do-release-upgrade.8.html
  • Ubuntu Launchpad: needrestart: https://launchpad.net/ubuntu/+source/needrestart
  • Linux man-pages: apt-get(8): https://man7.org/linux/man-pages/man8/apt-get.8.html