<!--
{
  "documentType" : "article",
  "framework" : "DeviceManagement",
  "identifier" : "/documentation/DeviceManagement/installing-packages",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Installing packages"
}
-->

# Installing packages

Use declarative package management to install and remove packages in macOS.

## Discussion

Device management services can install and monitor packages using declarative management on macOS devices. The services apply a declarative management configuration to the device and subscribe to a declarative management status item. Devices support packages with any type of content. If a package installs an app, a service can manage the app using the [`AppManaged`](/documentation/DeviceManagement/AppManaged) configuration with an `AppComposedIdentifier` key.

Devices can install packages only on supervised devices in the system scope (the device management service device channel).

The [`Package`](/documentation/DeviceManagement/Package) configuration type is `com.apple.configuration.package`. Use this configuration to install a package.

## Install packages

To install packages, the device downloads a manifest document from the URL in the configuration’s `ManifestURL` key. The manifest needs to match the [`ManifestURL`](/documentation/DeviceManagement/ManifestURL) format and reference a single package file. It also needs to contain a `bundle-version` key for the package, which the device uses to detect package updates when updating configurations.

The device can install a package immediately after it applies a configuration, or it can wait for the user to start the install. The `Install` key in the [`PackageInstallBehaviorObject`](/documentation/DeviceManagement/PackageInstallBehaviorObject) object controls this behavior:

|Value     |Description                                                                                                                     |
|----------|--------------------------------------------------------------------------------------------------------------------------------|
|`Required`|The device installs the package when it applies the configuration.                                                              |
|`Optional`|The device doesn’t install the package when it applies the configuration. Instead, the user chooses when to install the package.|

A *management app* displays required and optional packages to the user, provides details about packages, and allows the user to initiate installs of optional packages. For more information, see [Displaying managed apps and packages](/documentation/DeviceManagement/displaying-managed-apps-and-packages).

## Update packages

The device doesn’t automatically update packages. To update a package, the device management service needs to:

- Change the `bundle-version` key in the manifest document.
- Change the package configuration’s `ServerToken` key.

The device checks the manifest during configuration updates, and updates packages if needed.

## Remove packages

The device removes a package when it deactivates or removes the configuration for a package, or when it unenrolls.

The device tracks the files and directories that the package creates or updates at install time. The device removes the files and directories it tracks, when the `Remove` key in the [`PackageUninstallBehaviorObject`](/documentation/DeviceManagement/PackageUninstallBehaviorObject) object is set to `true`. Any changes to files or directories after install, such as via a post-install script in the package or by user changes, are not tracked.

> Note:
> Removal of files and directories only occurs when the `Remove` key is set to `true` when the package is installed. If you change the key from `false` to `true` in a configuration that the device has already installed, then the device won’t track the files and directories and it won’t remove them when it removes the package configuration.

When the `Remove` key in the [`PackageUninstallBehaviorObject`](/documentation/DeviceManagement/PackageUninstallBehaviorObject) object is set to `false` or isn’t present, the device only removes the system metadata for the package.

## Get the status of packages

The device reports the status of each declarative managed package in the [`StatusPackageList`](/documentation/DeviceManagement/StatusPackageList) status item, which device management services can subscribe to. When the package status changes, the device reports incremental updates to the [`StatusPackageList`](/documentation/DeviceManagement/StatusPackageList) status item elements.

## Process the status item

The [`StatusPackageList`](/documentation/DeviceManagement/StatusPackageList) status item type is `package.list`, which is the device’s list of declarative packages.

The status item’s value is an array of objects, where each object represents a declarative managed package. The device uses normal status-item array value reporting behavior to report changes incrementally to the device management service; for more information, see [`StatusReport`](/documentation/DeviceManagement/StatusReport). The status includes required and optional packages, regardless of whether they are installed.

The `identifier` key provides the unique identifier of the package for incremental reporting in the overall status item (see [`StatusReport`](/documentation/DeviceManagement/StatusReport)). The `declaration-identifier` key contains the `Identifier` of the package configuration. Additional properties show the package’s name and version identifiers.

The `state` key indicates the package’s management state, for example, `queued`, `downloading`, `installing`, and `installed`. If an error occurs during installation, the device reports the `failed` state and includes the `reasons` key to provide more details.

Use this status item in declarative device management activation predicates using the same format for expressions that [Processing status for managed apps](/documentation/DeviceManagement/processing-status-for-managed-apps) describes for managed app status.

## Handle errors

The device reports errors to the device management service in two ways:

- It reports an error in a configuration using the declarative management [`StatusManagementDeclarations`](/documentation/DeviceManagement/StatusManagementDeclarations) status item. The status item shows the configuration as active but invalid, with a reason code. Examples include syntax errors or missing required keys.
- It reports an error during package installation using the declarative management [`StatusPackageList`](/documentation/DeviceManagement/StatusPackageList) status item, described above.

## Build a package

The device only installs signed packages and only when it can verify the signature. The package signature needs to use an appropriate certificate that the device can verify, such as a TLS certificate with signing usage. Only sign the package; you don’t need to sign the app because Gatekeeper doesn’t check apps that are installed using device management.

Use the following command-line invocation to build your own signed package for an app:

```bash
$ sudo pkgbuild --component <APP> --install-location /Applications --sign <CERT> /tmp/MyPackage.pkg
```

Set the `<APP>` argument to the path of the app to install, and the `<CERT>` argument to the signing certificate identifier. Set the install location to `/Applications` because the device only manages apps in that location.

In addition to the `.pkg` file, create a [`ManifestURL`](/documentation/DeviceManagement/Package/ManifestURL) document that the device management service uses to install the package, as the following example shows:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>items</key>
  <array>
    <dict>
      <key>assets</key>
      <array>
        <dict>
          <key>kind</key>
          <string>software-package</string>
          <key>url</key>
          <string>https://devicemanagement.example.com/packages/MyPackage.pkg</string>
          <key>sha256</key>
          <string>49f6554726ae98521b02d89a86f2a7eea5611295fa2f67bf8bc44f679c121a2d</string>
        </dict>
      </array>
      <key>metadata</key>
      <dict>
        <key>bundle-identifier</key>
        <string>com.test.MyPackage.pkg</string>
        <key>bundle-version</key>
        <string>1</string>
        <key>kind</key>
        <string>software</string>
        <key>title</key>
        <string>MyApp.app</string>
      </dict>
    </dict>
  </array>
</dict>
</plist>
```

The [`ManifestURL`](/documentation/DeviceManagement/Package/ManifestURL) needs to adhere to the following requirements:

- Set the `items/assets/kind` key to `software-package`.
- Set the `items/assets/url` key to the URL the device uses to download the package file.
- Set the `items/assets/sha256` key to the SHA-256 hash value of the package file. For large package files, you can instead use the `sha256s` key to provide an array of hashes for each “chunk” of the package file, with the chunk size specified by the `sha256-size` key.
- Set the `items/metadata/bundle-identifier` key to a unique value for the package. The device uses this value to determine whether a package is an update to an existing package, or a new package.
- Set the `items/metadata/bundle-version` key to a version for the package. The device uses this value to determine whether a package needs to be updated.
- Set the `items/metadata/kind` key to `software`.
- Set the `items/metadata/title` key to the title of the package.

To determine the SHA-256 hash of the package file, use the following command-line invocation:

```bash
$ shasum -a 256 /tmp/MyPackage.pkg
```

You can build more complex packages — for example, ones that contain multiple apps or other types of files — using the `pkgbuild` and `productbuild` command-line tools.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)