Skip to content
← All posts

guides

SUSE Patching Process with zypper: SLES 15 and 16 Step by Step

October 10, 2026

Patching SLES runs through zypper's patch workflow: zypper refresh, zypper list-patches --category security to see what is pending, zypper patch --category security to apply it, and zypper needs-rebooting to decide on a reboot. Btrfs snapshots taken around every zypper transaction give you the rollback. The same commands apply to SLES 15, SLES 16 and openSUSE Leap.

SUSE Linux Enterprise Server patches differently from the Debian and Red Hat families. Instead of upgrading packages one by one, SLES ships patches: curated update sets that each carry a category, a severity and the CVEs they fix, and zypper applies them as units. This guide is the patching process in the order you run it, for SLES 15 (SP7 is the current service pack), SLES 16 (generally available since November 2025) and openSUSE Leap, which share the same zypper workflow.

The commands at a glance

StepCommandWhat it tells you or does
1. Check registration and reposSUSEConnect --status-text, zypper refreshWhether the host can see patches at all
2. List pending security patcheszypper list-patches --category securityEach patch, its severity and status
3. Apply security patcheszypper patch --category securityInstalls the security patch set
4. Patch one CVEzypper patch --cve=CVE-…A targeted fix ahead of the window
5. Check for a rebootzypper needs-rebootingExit 102 if a reboot is suggested
6. Roll backsnapper list, snapper rollbackReturn to the pre-patch snapshot
7. Automate ita systemd timer running zypper patchThe same steps on a schedule

Step 1: Confirm the host can see patches

An SLES host that is not registered sees no update repositories and reports nothing to install. Check registration first:

sudo SUSEConnect --status-text      # every module should show "Registered"
sudo zypper repos                   # the *-Updates repositories must be enabled
sudo zypper refresh                 # pull fresh metadata

openSUSE Leap has no registration step; zypper repos and zypper refresh are enough. If zypper refresh exits with 106, a repository failed to refresh and was skipped, so the rest of the run is working from incomplete data. Fix the repository before you patch.

Step 2: See what is pending, by category and severity

sudo zypper patch-check; echo $?                     # 100 = patches pending, 101 = security patches pending
sudo zypper list-patches --category security          # short form: zypper lp -g security
sudo zypper list-patches --category security --severity critical
sudo zypper info -t patch SUSE-SLE-Module-Basesystem-15-SP7-2026-1234

zypper patch-check is the one for scripts and monitoring, because its exit code alone says whether the host is behind on security: 101 means at least one security patch is pending.

Step 3: Apply security patches

sudo zypper --non-interactive patch --category security

Two zypper behaviours catch people out here:

  • Interactive patches are skipped in non-interactive mode. A patch is “interactive” if it needs a reboot, shows a message or asks to accept a license. Kernel patches are interactive, so an unattended zypper --non-interactive patch silently leaves the kernel behind. Add --with-interactive to include them, and then plan for the reboot in step 5.
  • Exit code 103 means run it again. When the patch stack updates zypper or libzypp, zypper installs that first, exits with 103, and expects a second run for everything else.

Run the full zypper patch (all categories) in your monthly window. zypper patch --with-update also picks up package updates no patch covers, which on SLES is rarely needed and on Leap is more common.

Step 4: Patch one CVE ahead of the window

sudo zypper list-patches --cve=CVE-2026-12345     # which patch fixes it, and whether it is installed
sudo zypper patch --cve=CVE-2026-12345            # apply only that fix

If no patch is listed, SUSE has either not released a fix or does not consider the CVE to affect that service pack. SUSE’s CVE page for the ID says which, and is the evidence an auditor will ask for.

Step 5: Decide whether the host needs a reboot

sudo zypper needs-rebooting; echo $?   # 102 = reboot suggested, 0 = not needed
sudo zypper ps -s                      # processes still using deleted files, with service names

needs-rebooting reads a flag that zypper sets when it installs a package marked as needing a reboot (the kernel, glibc, systemd and the others listed in /etc/zypp/needreboot). It is the check to script against. When it returns 0 but zypper ps -s lists services, restarting those services finishes the job. SLES also offers kernel live patching through the SUSE Linux Enterprise Live Patching extension, which defers the kernel reboot but does not remove it.

Step 6: Roll back with snapper

SLES installs its root filesystem on Btrfs by default, and the snapper zypp plugin takes a “pre” and “post” snapshot around every zypper transaction. That makes rollback a filesystem operation instead of a package downgrade:

sudo snapper list                     # find the pre/post pair for the patch run
sudo snapper status 41..42            # what changed between the two
sudo snapper undochange 41..42        # revert those files on the running system
sudo snapper rollback 41 && sudo reboot   # or boot back into the pre-patch state

undochange is fine for a configuration or single-package mistake. For a bad kernel or core library, rollback plus a reboot is the safe choice, and the GRUB menu also lists snapshots if the patched system will not boot. Hosts installed on XFS or ext4 have no snapshots, so rollback there means zypper install --oldpackage <package>-<version> from the repositories. To keep a package at its current version, lock it with zypper addlock <package> and release it later with zypper removelock.

Step 7: Automate it

There is no dnf-automatic equivalent shipped as one package. The YaST Online Update Configuration module (yast2-online-update-configuration) schedules unattended patching, or you can write the systemd timer yourself, which keeps the behaviour visible:

# /etc/systemd/system/zypper-security-patch.service
[Unit]
Description=Apply SUSE security patches

[Service]
Type=oneshot
ExecStart=/usr/bin/zypper --non-interactive refresh
ExecStart=/bin/sh -c '/usr/bin/zypper --non-interactive patch --category security; rc=$?; [ $rc -eq 103 ] && /usr/bin/zypper --non-interactive patch --category security; exit 0'
# /etc/systemd/system/zypper-security-patch.timer
[Timer]
OnCalendar=*-*-* 03:00
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now zypper-security-patch.timer

The unit leaves kernel patches out on purpose (no --with-interactive), so it never sets up a reboot nobody planned. Kernel patches wait for the monthly window. On SLE Micro and other transactional systems, transactional-update replaces all of this and applies patches into a new snapshot that becomes active at the next reboot.

What a timer does not give you is a view across hosts: which servers are behind on security patches, which are waiting for a reboot and which failed last night. That is where a Linux patch management tool earns its keep.

From one host to a fleet

ApproachGood atWhere it stops
A zypper timer on every hostFree, transparent, security-only by flagNo central view, no staging, no reboot coordination
Ansible with the community.general.zypper moduleBatches and reboots from one playbookTreat exit code 102 as success; you build the reporting
SUSE Multi-Linux Manager or UyuniChannels, content lifecycle, SUSE supportA server to run; see Satellite and Spacewalk alternatives
A cross-distro tool such as SysWardSLES next to Ubuntu and RHEL in one view, grouped rollouts, historyAgent per host; upgrades packages rather than applying patch sets; no channel management

SysWard’s agent reads zypper list-patches to mark which pending updates are security fixes, locks packages with zypper addlock, and flags hosts where zypper ps finds processes still running replaced files. One difference from the process above: it upgrades the affected packages with zypper up rather than applying SUSE patch sets with zypper patch, so if your change process is written around patch IDs, keep zypper patch in the monthly window and use SysWard for the inventory, CVE view and scheduling. The SUSE patching guide covers the fleet side.

A monthly SLES patching checklist

  1. Confirm registration and refresh every host; treat exit code 106 as a failure (step 1).
  2. Record zypper patch-check and the pending security patches in the change ticket (step 2).
  3. Patch a staging group with --with-interactive, reboot, run your smoke tests.
  4. Patch production in batches, rerunning on exit code 103 (step 3).
  5. Reboot the hosts where zypper needs-rebooting returns 102 (step 5).
  6. Keep the snapper pre/post numbers in the ticket as your rollback point (step 6).
  7. Leave the security timer on between windows (step 7).

If you run RHEL or Rocky alongside SLES, the RHEL patching process is the same checklist with dnf. To see SLES, RHEL and Ubuntu hosts in one view, start free with 5 agents, no card required.

Frequently Asked Questions

What is the difference between zypper patch and zypper update?

zypper patch installs released patches: SUSE's curated update sets, each with a category (security, recommended, optional), a severity and the CVEs it fixes. zypper update upgrades every package that has a newer version in the repositories, whether or not a patch covers it. On SLES, patch is the supported path; zypper patch --with-update does both. zypper dup is a distribution upgrade and is not for routine patching.

How do I install only security patches on SLES?

Run zypper patch --category security. Add --severity critical or --severity important to narrow it. zypper list-patches --category security shows the same set first without installing anything.

How do I patch a specific CVE on SUSE?

Run zypper list-patches --cve=CVE-YYYY-NNNNN to find the patch that fixes it, zypper info -t patch <patch-name> to read it, and zypper patch --cve=CVE-YYYY-NNNNN to apply only that fix.

How do I check if SLES needs a reboot after patching?

Run zypper needs-rebooting. It exits with 102 when an update to the kernel or a core library has set the reboot-needed flag, and 0 otherwise. zypper ps -s lists processes still using deleted files, which you can usually fix by restarting the services it names instead of rebooting.

Why does zypper patch need to run twice?

When a patch updates the package manager itself, zypper installs that patch first and exits with code 103, asking to be run again. The second run installs everything else. Scripts should loop on exit code 103 rather than treat it as a failure.

Stop patching Linux servers by hand

SysWard automates patch management across your entire fleet — CVE scanning, scheduled rollouts, and audit-ready reports in one dashboard.

Start free