---
title: "Patching"
description: "How Outpost finds missing updates, approves them by rule or by hand, installs them in a maintenance window, handles restarts, and reports patch compliance."
url: "https://support.outpostplatform.com/automation/patching/"
product: "depot"
type: "how-to"
status: "draft"
ai_summary: "Outpost patching for Windows (Windows Update), Linux (apt, dnf), macOS (Software Update, Preview), FreeBSD (pkg, freebsd-update), and OpenBSD (syspatch, pkg_add). patch.* profile settings auto-approve, defer, and set the maintenance window and restart policy; patch.install_enabled is off by default. Approve, decline, or hold updates in Software > Patching > Approvals. Needs patch:approve."
availability:
  plans: ["home-lab", "essentials", "enterprise", "msp"]
  platforms: ["windows", "linux", "macos", "freebsd", "openbsd"]
  permission: "patch:approve"
  preview: false
source: "https://gitlab.com/outpostplatform/docs/-/edit/main/src/content/docs/automation/patching.md"
license: "CC BY 4.0"
---

# Patching

Patching keeps operating systems and packages current. Each endpoint scans for
the updates it is missing and reports them. Profile rules approve some updates
automatically, and you approve, decline, or hold the rest. The endpoint
installs approved updates in its maintenance window and handles the restart the
way its policy says. This page explains each of those decisions and how to make
them.

## Before you begin

- To see patch state you need `patch:read`. To approve, decline, hold, or
  install updates you need `patch:approve`.
- On the MSP plan, open the client's workspace first. Patching is per client.

:::caution
Endpoints do not install updates until a profile sets `patch.install_enabled`
to `true`. It is off by default, because installing restarts endpoints. Scanning
is on by default and installs nothing.
:::

## How updates reach an endpoint

1. **Scan.** The endpoint scans for missing updates every 12 hours by default
   (`patch.scan_interval_seconds`) and reports them. A scan installs nothing.
2. **Approve.** Each reported update is approved by a rule, approved or declined
   by a technician, or left waiting.
3. **Install.** When its maintenance window opens, the endpoint installs the
   updates that are approved for it, if `patch.install_enabled` is on.
4. **Restart.** If an update needs a restart, the restart policy decides what
   happens.

The endpoint opens its own maintenance window, so it installs on time even
while it cannot reach your Outpost, and reports afterwards.

### Per platform

| Platform | Mechanism | Update ids |
| --- | --- | --- |
| Windows | Windows Update. Set `patch.wsus_server_url` to take updates from your own WSUS server. | KB numbers |
| Linux | apt on Debian and Ubuntu, dnf on the Red Hat family. Security updates are reported as **Security Updates**, the rest as **Updates**. Only approved packages are installed, never a blanket upgrade. | One per package, such as `apt:curl` |
| macOS (Preview) | macOS Software Update. Application updates install in the window. A macOS update needs the credential in `patch.macos_update_credential`. Without one, the update is downloaded and the person at the Mac is asked to finish it in System Settings. | One per update |

| FreeBSD | pkg for packages, and freebsd-update for the base system on a -RELEASE install. On a packaged-base install, the base system arrives as `FreeBSD-*` packages instead. Base-system updates and packages that `pkg audit` flags are reported as **Security Updates**, the rest as **Updates**. | One per package, such as `pkg:curl`. The freebsd-update base system is one row, `freebsd:base`. |
| OpenBSD | syspatch for errata, and pkg_add for packages. Errata are reported as **Security Updates**, packages as **Updates**. | One per package, such as `pkg_add:curl`. All outstanding errata are one row, `syspatch:errata`. |

syspatch and freebsd-update install every outstanding update in order, or none,
so each is one row that names how many updates it carries, such as **OpenBSD
errata: 40 pending (001_xserver ... 040_dbupdate)**. Approving that row installs
all of them. When an installed kernel update needs a restart, the endpoint
reports that it needs one.

On a Linux endpoint without apt or dnf, patching is unavailable, and the
endpoint says so rather than reporting a clean scan.

## Set the patch policy

Patch policy is a set of `patch.*` settings on a profile. See
[Create and assign a profile](/automation/create-a-profile/), and the
[Patch settings](/automation/policy-settings/#patch) for every key.

| Decision | Settings | Defaults |
| --- | --- | --- |
| Whether endpoints install at all | `patch.install_enabled`, `patch.scan_enabled` | Install off, scan on |
| What approves itself | `patch.auto_approve_critical`, `patch.auto_approve_security`, `patch.auto_approve_feature_updates`, `patch.auto_approve_driver_updates`, `patch.include_optional_updates` | Critical and security on. Feature, driver, and optional updates off. |
| What never installs | `patch.excluded_kb_ids` | Empty |
| How long Windows holds updates back | `patch.deferral_days_quality`, `patch.deferral_days_feature` | 0 days for quality updates, 30 for feature updates |
| When the window opens | `patch.maintenance_window_start`, `patch.maintenance_window_duration_seconds`, `patch.maintenance_window_days` | `22:00` in the endpoint's site time zone, for 4 hours, every day |
| What happens about restarts (Windows) | `patch.reboot_policy`, `patch.reboot_grace_period_seconds`, `patch.notify_user_before_reboot_seconds` | `notify_user`, 24 hours of grace, 15 minutes of warning |

`patch.reboot_policy` takes `never`, `notify_user`, `scheduled`,
`force_after_grace`, or `immediate`. An update listed in
`patch.excluded_kb_ids` is declined by rule, and the console shows it as
declined.

To wake sleeping or shut-down endpoints before the window opens, set
`power.wake_for_maintenance`. See the [Power settings](/automation/policy-settings/#power).

To stage a rollout, assign one patch profile to a test device group and
another, with a later window or install turned off, to the rest of the client.
See [Profiles and policies](/automation/profiles/).

## Approve, decline, or hold updates

1. Go to **Software** > **Patching** and open **Approvals**.

   The list has one row per Windows KB, and one row per Linux, macOS, FreeBSD,
   or OpenBSD package.
   Each row shows the **Update**, its **Severity**, how many **Endpoints** are
   missing it, their count **By state**, and **Outstanding since**. A feature
   update carries the **Feature update** chip.
2. Narrow the list with the search box, or by **State**, **Severity**, **KB**,
   **Endpoint id**, or **Feature updates**.
3. Select the number under **Endpoints** to see the endpoints behind a row.
4. On the row, select:
   - **Approve**, then **Yes, approve**, to approve it on every endpoint that is
     missing it.
   - **Decline**, then **Yes, decline**, to decline it everywhere.
   - **Hold**, then **Yes, hold**, for a Linux, macOS, FreeBSD, or OpenBSD
     package. A hold keeps
     every endpoint from installing that package until you select **Release
     hold**.

Approving or declining a KB is one decision for the whole client. An update
with no KB number, such as some driver and definition updates, cannot be
approved or declined from this list.

### Update states

| State | Meaning |
| --- | --- |
| pending | Reported missing and waiting for a decision. |
| approved | Approved, by a rule or by a technician, and not installed yet. |
| declined | Declined by a technician, or by `patch.excluded_kb_ids`. |
| installed | Installed. |
| failed | The install failed. The row shows the error and the attempt count. |
| deferred | Held back by policy, such as a deferral period. |
| awaiting user | A macOS update downloaded and waiting for the person at the Mac to finish it. |
| superseded | Replaced by a newer update. |
| not applicable | No longer applies to the endpoint. |

A failed install raises a patch alert for the endpoint, which clears when a
later run installs everything it tried.

## Install now on one endpoint

1. Open the endpoint and select **Actions**.
2. Under **Maintenance**, select **Scan for patches** and confirm with **Scan
   now** to refresh its list, or **Install approved patches** and confirm with
   **Install now** to install what is approved for it straight away.

Neither overrides policy. An endpoint does not install where
`patch.install_enabled` is off, or scan where `patch.scan_enabled` is off. The
endpoint's **Patches** tab lists its updates and their history.

## Check compliance

Go to **Software** > **Patching** and open **Compliance**.

| Tile | Meaning |
| --- | --- |
| **Endpoints** | Every endpoint in the client. |
| **Compliant** | Scanned, and missing nothing. |
| **Never scanned** | No scan reported yet. Counted as neither compliant nor not compliant. |
| **Pending reboot** | Patched, waiting on a restart. |
| **Missing critical**, **Missing important**, **Missing other** | Outstanding updates by severity. |
| **Oldest missing update** | The date the oldest outstanding update was first seen, or **None**. |

The compliance percentage counts scanned endpoints only. To raise it honestly,
get the never-scanned endpoints scanned.

**Endpoints with outstanding updates** lists each endpoint with its outstanding
updates by severity. Use **Show** to narrow it to **All outstanding**,
**Awaiting a decision**, **Approved, not installed**, **Held by policy**,
**Failed to install**, or **Waiting on the user**.

Select **Download CSV** to export the compliance report, for example as audit
evidence.

## Verify

After the window has passed, open **Compliance**. Endpoints you patched move to
**Compliant**, or to **Pending reboot** until they restart. On the
**Approvals** tab, the rows you approved show the endpoints as installed.

## If something goes wrong

| Symptom | Cause | Fix |
| --- | --- | --- |
| Updates stay approved and never install | `patch.install_enabled` is off for the endpoint. | Turn it on in a profile that applies, and check on **Profiles** > **Effective config**. |
| Nothing installs in the window | The window days or hours never open while the endpoint is on, or it is asleep. | Check the `patch.maintenance_window_*` settings, or set `power.wake_for_maintenance`. |
| An endpoint is counted **Never scanned** | It has not reported a scan: it is offline, `patch.scan_enabled` is off, or the platform cannot be patched. | Bring it online, turn scanning on, or check [Supported platforms](/get-started/platform-support/). |
| Rows show **failed** | The install failed on the endpoint. | Read the error on the endpoint's **Patches** tab. On Windows, the built-in script **Reset Windows Update components** repairs a stuck update stack. See [Built-in script library](/automation/script-library/). |
| A macOS update stays **awaiting user** | No update credential is set. | Set `patch.macos_update_credential`, or ask the person at the Mac to finish it in System Settings. |

## Next steps

- [Vulnerabilities](/automation/vulnerabilities/)
- [Policy settings reference](/automation/policy-settings/#patch)
