Skip to content

Usage Flatpak

Alexander Birkner edited this page Oct 4, 2026 · 1 revision

Usage: Flatpak

A (repo, channel) pair is one OSTree remote. Clients add it with flatpak remote-add and install from it like any other remote; silo serves it under /{repo}/{channel}/ostree/.

A remote holds apps and runtimes, each as a ref such as app/org.example.Hello/x86_64/stable. Publishing a ref again moves it to the new commit. The objects of the commit it moved away from stay in storage, because objects are shared between commits.

Publishing

There are two ways in, and they end in the same remote.

A .flatpak bundle

silo publish ./hello.flatpak --repo myrepo --channel apps

The format is inferred from the .flatpak extension; pass --format flatpak to be explicit. The bundle can be an app or a runtime (flatpak build-bundle --runtime). silo opens the bundle, checks every object against its checksum, checks that the commit's whole tree is present, and rejects the upload otherwise.

A bundle is held in memory while it is opened, and what it unpacks to is bounded by the same decompression limit every other format has.

A local OSTree repository

silo publish-ostree ./repo --repo myrepo --channel apps
silo publish-ostree ./repo --repo myrepo --channel apps \
    --ref app/org.example.Hello/x86_64/stable

This is for builds that already leave a repository behind — flatpak build-export, flatpak-builder --repo. The client walks the repository, asks the server which objects it lacks, uploads only those, and then moves the refs. A repeated push of an unchanged repository uploads nothing, and a push that is interrupted leaves unreferenced objects behind and no half-published ref: a ref moves only once every object under its commit is in storage.

Without --ref, every app and runtime under refs/heads is published. Refs that are not apps or runtimes (appstream/…) are skipped. A ref pulled from another remote lives under refs/remotes/<remote>/…; name it with --ref to publish it.

The repository has to be in archive mode, which is the form silo stores and serves; for anything else the command prints the ostree pull-local conversion.

What silo checks on upload

Each object is verified against the name it is uploaded under, so storage never holds an object that is not what its key says. A commit bound to other refs (ostree.ref-binding) cannot be published under a different one. Device nodes, FIFOs and sockets are refused, as are directory entries that could escape their directory.

Consuming — public repo

Flatpak cannot send a credential to a remote, so a remote is consumed from a public repo (silo repo set myrepo --mode=public, see Usage). Publishing still requires a write-scoped token regardless of repo mode.

flatpak remote-add silo https://silo.example.com/myrepo/apps/silo.flatpakrepo
flatpak install silo org.example.Hello

GET /{repo}/{channel}/silo.flatpakrepo carries the remote's URL and the key its signatures verify against. GET /{repo}/{channel}/flatpakref/{id}.flatpakref is the matching per-app file, so one command both adds the remote and installs the app:

flatpak install https://silo.example.com/myrepo/apps/flatpakref/org.example.Hello.flatpakref

When an id exists in several branches or architectures, ?branch= and ?arch= pick one; otherwise stable is preferred.

An app still needs its runtime. When the runtime is published in the same channel, the .flatpakref carries a RuntimeRepo pointing at the channel's own .flatpakrepo, so the one command installs both. When it is not — a Freedesktop or GNOME runtime, say — add the remote that has it (Flathub, usually) as well.

Signing

If the server has signing.gpg configured (see Setup) — the same key RPM and apt use, not a separate one — silo signs the remote's summary and every commit with it. Both signatures are detached binary OpenPGP signatures, which is the form libostree reads. The .flatpakrepo carries the public key, so flatpak remote-add needs no separate key distribution, and flatpak verifies both signatures on every install and update.

Without a key configured, the remote is unsigned and the .flatpakrepo says so (GPGVerify=false). Commits that arrive already signed by someone else — a Flathub app republished through silo, say — are re-signed with silo's key; the commit itself, and so its checksum, is unchanged.

What is served

path under /{repo}/{channel}/ostree/ what
config, summary, summary.sig regenerated from the database on every publish
refs/heads/{ref} the commit a ref points at
objects/ab/cdef….{filez,dirtree,dirmeta,commit,commitmeta} the objects, redirected to object storage when the backend can presign

Paths of any other shape — summary.idx, static deltas, summaries/ — are a plain 404, which clients treat as "not available". silo publishes neither static deltas nor a summary index, so updates are fetched object by object.

Object downloads are not individually audited or counted in package.download events: one install is thousands of requests. The ref update that made an app visible is audited like any other publish.

Limits

  • Objects are never deleted. Removing a ref (silo delete) takes it out of the summary and deletes its ref file, but leaves the objects, which other commits may share.
  • Pull-through upstreams are not available for Flatpak channels.

Clone this wiki locally