First we need to talk a bit about OSTree. This is the core distribution and installation mechanism of xdg-app. OSTree is similar to git, but has been designed to handle trees of large binaries. Just like git it has the concept of repositories, commits and branches (refs) . Branches are names which points to a commit id, and an application stored in a repository is such a branch.
On your machine there is a local OSTree repository which has a bunch of “remotes” configured. When you install or update an application from one on these remotes, what happens is that we
ostree pull the branch from the remote, then do a local checkout of the branch (with hard links back to the repository files, so this is cheap).
The OSTree repositories created by
xdg-app build-export are of a type (called archive-z2) that are meant to be served by a dumb webserver. So, to distribute your application, all you have to do is copy the repository to a webserver and give the url to your users.
There are however some extra details you have to be aware off .
First of all, the format of the archive-z2 repositories is one file per file in the app. This means a pull operation will do a lot of http requests. Since new requests are slow, make sure you enable support for HTTP keep-alive in your webserver.
OSTree also supports something called static deltas. These are single files in the repo that contains all the data needed to go between two revisions (or from nothing to a revision). Creating such deltas will take a bit more space, but will make downloads much faster.
xdg-app has the
build-update-repo command that is very useful to manage repositories. Starting at version 0.4.13 it supports
--generate-static-deltas to generate the deltas. but it also has several other features that are useful. For instance, you can use:
xdg-app build-update-repo --title="Nice name" repo
To set a user readable name for the repository, which will be used by default in the UI when users see this repository.
It also lets you prune (
--prune) unused objects and deltas from the repository, and even remove older revisions from your repository (
--prune-depth) which is useful for things like automatic nightly build repositories.
build-update-repo does is appstream extraction. It scans all the branches in the repository and looks for an AppStream xml file. For instance, the dictionary app from part 3 contains such a file in
files/share/app-info/xmls/org.gnome.Dictionary.xml.gz. All these files plus the icons they reference are collected and commited into a repo-wide appstream branch. xdg-app keeps a local copy of this branch for each remote, which you can manually update with:
xdg-app --user update --appstream nightly
This is used by graphical installation tools such as gnome-software, so having appstream data for your applications is important.
Note: xdg-app-builder automatically runs the appstream-compose command after the build. This will collect information from appdata files and desktop files and create the right xml.gz and icon files. This is where the xml in gnome-dictionary came from.
Another important part about app distribution is gpg signatures. By default OSTree refuses to pull anything from a remote repository that is not signed. This is only allowed if you use
--no-gpg-verify when you add the remote (or you can change it with
In OSTree, signatures are on each commit and on the summary file that lists all the branches in the repositories. These objects are created by the
build-export commands, as well as indirectly by
xdg-app-builder. So, when you call these, you should pass in the gpg keys to sign with, and optionally the gpg home directory to use. For example:
xdg-app build-export --gpg-sign=KEYID --gpg-homedir=/some/dir appdir repo
That concludes this tutorial series, and you should now know enough to package and distribute your own applications.