On this page

Package Installation

Dynamically Installing, Updating, and Removing Packages

After applications have been packaged by the appman-packager tool, they can be installed by the application manager at runtime. There are two interfaces for this functionality:

  • A QML interface for use within the application manager process.
  • A D-Bus interface for use by any process that is allowed to talk to the application manager's PackageManager interface.

Both interfaces are very similar and are described in the PackageManager.

Note: A prerequisite for dynamically installed application packages is a valid installationDir configuration for the application manager.

Packages

The application manager has its own Package Format. It comes with the appman-packager command-line tool, for you to create and verify those packages.

Installation Sources

When triggering a package installation, you have to provide a URL to the application manager as the source of the package. Out of the box, the application manager accepts the following schemes:

SchemeDescription
file://A local filesystem path.
http://, https:// and ftp://A remote path that is downloaded via QNetworkAccessManager.
socket://A path to a UNIX-domain socket in the local filesystem. This is very useful for streaming in packages, if you do not want to (or can) use the built-in downloader, or if your packages are wrapped inside another customer-specific distribution file format.

All of the above methods work asynchronously and also support streaming: this means that the actual installation is done while the package is being downloaded. If the package is successfully verified after the download, it only needs a quick finalization step. Otherwise, if an error occurred, the installation process is simply canceled and rolled back.

Public Key Infrastructure

To use signed packages, you require a Public Key Infrastructure (PKI) to support this, which means that you need two Certificate Authorities (CAs):

  • A Developer CA: responsible for creating certificates that are distributed to developers in P12 format. The developers use these certificates to developer-sign their packages, using the Packager, before submitting to an app store.
  • An App-Store CA: responsible for creating certificates for use by app store server back ends to store-sign packages, before they are downloaded and installed onto devices.

Both these CAs can be the same or they can be derived from a common root CA.

For the device, you need to install one or both of these CA certificates, including any root or intermediary ones. But, this depends on the type of package you want the user to be able to install. Which CA certificates to load is specified via the config file.

The application manager sources have a script, tests/data/certificates/create-test-certificates.sh, that sets up such a PKI for the internal unit tests. This script is not for use in production, but only for use in developing with signed packages.

New in 6.11:

  • Developer certificates can be bound to one or more specific package IDs, to prevent shadowing or replacement of packages that are not owned by the developer. See below for more information.
  • Developer certificates need to have the decipherOnly bit set in the Key Usage X509 extension, while App-Store certificates need to have the encipherOnly bit set. This ensures that developer and app-store certificates cannot be used interchangeably. The X509 format is not easily extensible, but these otherwise unused key-usage bits can easily be set in any tool used for creating certificates.
  • Certificate Revocation Lists (CRLs) can be loaded to revoke developer or app-store certificates.

New in 6.12:

  • Developer certificates can be bound to application IDs, capabilities, categories and runtimes, in addition to package IDs. Signing or installing a package that requests anything that is not covered by the certificate fails. See below for more information.
  • Every certificate states which set of restrictions it was issued for, in the form of a version. Certificates older than the configured minimum version are rejected at install time. As that minimum defaults to the newest version the application manager was built with, 6.10 and 6.11 certificates are not accepted anymore out of the box. See below for more information.

Creating Developer Certificates

The examples below use the openssl command-line tool to create keys, CSRs, and certificates. You are however free to use any other tool that is able to create X.509v3 and PKCS#12 certificates.

For a developer to receive a developer certificate, they would typically generate a private key and a certificate signing request (CSR) for their package:

$ openssl req -new -nodes -newkey rsa:2048 -subj "/CN=Developer 1" \
              -addext "subjectAltName=URI:qtam://version/6.12,\
URI:qtam://packageid/my-package-id,URI:qtam://applicationid/my-package-id,\
URI:qtam://category/*,URI:qtam://runtime/qml-launcher" \
              -keyout developer.key -out developer-req.csr

Please note that the actual parameters like key size and subject name would depend on your PKI policy. In this example, a 2048-bit RSA key is created with the common name "Developer 1".

The subjectAltName extension is used to bind the developer certificate to the package contents the developer is allowed to sign: here, the single package my-package-id, containing a single application of the same ID, using the qml-launcher runtime, with any category, but without any capability. See below for more information.

The developer-req.csr file would then be sent to the Developer CA for signing, while the developer.key file is kept private by the developer.

On the CA side, the CSR is then verified and signed to create the developer certificate. Please note that developer certificates need to have the decipherOnly bit set in the Key Usage X509 extension.

The restrictions requested in the CSR are just that: a request. Only the CA's copy ends up in the signed certificate, so it is the CA's responsibility to verify them and to replace them with whatever the PKI policy grants this developer.

$ openssl ca -batch -config dev-ca.conf -policy signing_policy -extensions signing_req \
             -out developer.crt -infiles developer-req.csr

This generates the signed developer.crt file, which is then sent back to the developer.

The final step for developers is to bundle their private key and the signed certificate into a P12 file, which is the format that the appman-packager tool expects:

$ openssl pkcs12 -export -out developer.p12 -in developer.crt -inkey developer.key

Restricting Developer Certificates

Up to version 6.10, all developer certificates were treated equally, meaning that a developer could sign any package. Version 6.11 added package ID restrictions, to prevent shadowing or replacement of packages that are not owned by the developer. Version 6.12 added restrictions on application IDs, capabilities, categories and runtimes, so that a certificate can no longer be used to sign a package that grants itself capabilities or a runtime the developer was never given.

These restrictions are stored in the subjectAltName X.509v3 extension of the developer certificate as URI:qtam://<type>/<value> entries. This extension is conventionally used to store alternative domain names for HTTPS server certificates. The following types are recognized:

TypeRestrictsSince
packageidThe package's id.6.11
applicationidThe id of every application in the package.6.12
capabilityEvery capability requested by any application in the package.6.12
categoryEvery category of the package itself and of its applications.6.12
runtimeThe runtime of every application in the package.6.12

A package is only accepted if every value it requests is matched by at least one entry of the corresponding type: a single unmatched capability, category, application ID or runtime is enough to fail the signing or the installation. Types that the package does not use at all - for example categories in a package that has none - do not need any entries.

As with HTTPS certificates, you can use the * wildcard character to match multiple values. For example, a developer certificate with these subjectAltName entries:

  • URI:qtam://version/6.12
  • URI:qtam://packageid/com.vendor.*
  • URI:qtam://packageid/io.qt.example
  • URI:qtam://applicationid/com.vendor.*
  • URI:qtam://category/*
  • URI:qtam://runtime/qml-launcher

would allow the developer to create and sign packages with an ID starting with com.vendor., as well as the specific package with the ID io.qt.example. Their applications' IDs all have to start with com.vendor. and they all have to use the qml-launcher runtime. Any category is allowed, but no capabilities at all, as there is no capability entry.

Runtime entries are matched against the runtime field of the manifest as it is written, without resolving runtime aliases: a certificate bound to qml-launcher does not match a package requesting the qml runtime, and vice versa. Bind certificates to the actual runtime IDs (qml-launcher, qml-inprocess, or native) - the qml alias resolves to a different runtime depending on whether the application manager runs in single- or multi-process mode, so a certificate bound to qml would not confine the package to either of them.

Note: These restrictions are only enforced for certificate versions that carry them, so an unrestricted certificate is not the same thing as a certificate that omits the entries: see below. If you need to issue an unrestricted 6.12 developer certificate, add an explicit * entry for every type.

App-store certificates are not restricted this way, as a store-signed package has been vetted by the app store, which is expected to check the package's contents: any restriction entries on an app-store certificate are ignored. They do need a version entry, though.

Certificate Versions

The set of restrictions carried by certificates has changed over time, so every certificate states which set it was issued for, as a URI:qtam://version/<x.y> entry in its subjectAltName extension. This value is the application manager version in which the set of restrictions last changed: it is neither the version of the tooling that created the certificate, nor does it move with every release. A certificate issued while 6.14 is current still states 6.12, as long as the set of restrictions has not changed since then.

Certificates that predate this mechanism are recognized by their contents:

VersionRecognized byEnforced restrictions
6.10A missing or unexpected Key Usage extension.None.
6.11A Key Usage extension matching a developer or app-store certificate, but no version entry.Package IDs.
6.12A URI:qtam://version/6.12 entry.Package IDs, application IDs, capabilities, categories and runtimes.

Restrictions that a certificate's version does not know about are not enforced, because such a certificate simply does not carry the corresponding entries: a 6.11 developer certificate can sign a package requesting any capability. This is why the installer rejects any certificate - developer or app-store - that is older than the configured minimum version, which defaults to the newest version the application manager was built with. Since that default excludes 6.10 and 6.11 certificates, upgrading a device to 6.12 requires re-issuing them. Configuring a lower minimum re-enables the older certificates, together with their weaker guarantees.

Everything a certificate's version is derived from - the version entry as well as the Key Usage extension - is asserted by the issuing CA and cannot be changed by the holder of the certificate.

Changing the minimum version only affects new installations. Already installed packages were verified when they were installed and are not re-checked.

Note: A certificate with more than one version entry, or with an unparseable one, is rejected outright, independently of the configured minimum version.

The appman-packager tool warns when signing a package with a certificate that is older than the newest version the tool itself knows about, but still creates the package: the packager and the target device can run different application manager versions, so only the device can decide whether a certificate is acceptable.

Developer Signing Packages

Each package can only have exactly one developer signature.

A developer would sign their package as follows, after obtaining a valid developer certificate in P12 format (see above).

$ appman-packager dev-sign-package the-pkg.ampkg the-pkg.dev-signed.ampkg developer.p12

This takes the input package the-pkg.ampkg, signs it with the developer.p12 signature, and writes the output to the-pkg.dev-signed.ampkg.

The signed package would then be uploaded/sent to an app-store for further processing.

Store Signing Packages

Each package can only have exactly one app-store signature.

When a developer submits a package to an app-store, the app-store server backend and/or a human tester would verify the developer signature on the package first:

$ appman-packager dev-verify-package --verbose the-pkg.dev-signed.ampkg dev-ca.crt intermediate-ca.crt root-ca.crt

The actual number and names of the requires CA certificates depends on your PKI setup. The above is just an example.

Next, the contents of the package should be verified: first and foremost the contents of info.yaml, but also the actual application code.

Finally the package is signed with a store key:

$ appman-packager store-sign-package the-pkg.signed.ampkg the.pkg.dev-store-signed.ampkg store.p12

This takes the input package the-pkg.dev-signed.ampkg, signs it with the store.p12 signature, and writes the output to the-pkg.dev-store-signed.ampkg.

The store-signed package would then be made available for download and installation.

In order to differentiate between developer and store certificates (even if you use the same CA for everything), store certificates need to have the encipherOnly bit set in the Key Usage X509 extension.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.