How to create a flatpak package

We already talked about using flatpak packages in a previous tutorial: with this technology we universally distribute applications, which are packaged together with their dependencies and run inside a sandbox, isolated from the rest of the system. In this tutorial we see how to build and distribute an application inside a flatpak.

In this tutorial you will learn:

  • How to install flatpak and flatpak-builder on the most used Linux distributions
  • How to create and populate a manifest file with the needed parameters
  • How to build, install and run the built application
How to create a flatpak package

Software requirements and conventions used

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Distribution-independent
Software flatpak and flatpak-builder
Other None
Conventions # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux-commands to be executed as a regular non-privileged user

Installing the required software

The first thing we must do to start creating a flatpak package for an application, is to install the software needed to build and run flatpaks: flatpak and flatpak-builder. We can perform such operation using the package manager of our favorite Linux distribution. On Fedora we must run:

$ sudo dnf install flatpak flatpak-builder

On Debian, or one of the many distributions based on it, instead:

$ sudo apt-get update && sudo apt-get install flatpak flatpak-builder

On Archlinux we can use pacman to perform the same operation:

$ sudo pacman -Sy flatpak flatpak-builder

In many cases, the flatpak-builder package already depends on flatpak, so it could be superfluous to specify the latter explicitly; it should be installed anyway as a dependency.



Creating a flatpak: the basics

The whole process of packaging an application into a flatpak is based on a manifest file. A manifest file can be written in the YAML or JSON format. In this tutorial we will see how to create a flatpak for ffmpeg: for those of you who don’t know it, it is a complete framework which can be used to convert and stream audio and video. The manifest file shall contain information such as the id of the application, the runtime and the sdk it uses, the command which shall be used to invoke it once built, the list of the modules used to build it with the flatpak-builder package, and the permissions the application should have. In a moment we will take a look at those parameters in detail, but first let’s create a directory for our project, we will call it ffmpeg-flatpak:

$ mkdir ffmpeg-flatpak

Creating and populating the manifest file

Inside the project directory we must create our manifest. How to name the manifest file? The manifest file should be named after the application ID: every flatpak application must have an unique ID, created using a reverse-DNS style. It is composed of two sections:

  1. Domain controlled by the project
  2. The specific project name

The application ID for the gnome-dictionary application, for example, is org.gnome.Dictionary. For the sake of this tutorial we will use the org.linuxconfig.FFmpeg ID to build our flatpak. Inside our project directory, we create the org.linuxconfig.FFmpeg.yml file, and start reporting the ID of the application as the value of the app-id parameter:

app-id: org.linuxconfig.FFmpeg

After the application ID, we should specify the runtime and runtime-version used by the application. What is it? A runtime is basically the “environment” inside which the application will run, and contains a set of essential libraries and services. There are currently 3 available runtimes:

  1. Freedesktop
  2. GNOME
  3. KDE

The first one contains a set of essential libraries and services, the other two are based on it, and expands it with a set of utilities and libraries for the specific environments they represent.

What of those we should use for our example? Since the application we are trying to build and distribute via flatpak (ffmpeg) has no desktop-environment specific requirements, we can avoid using the GNOME or KDE runtimes and just use org.freedesktop.Platform. There are usually many versions of a runtime available. In this case we will use the 21.08 version of the freedesktop one. Inside the manifest file, the runtime version is specified via the runtime-version parameter:

app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'

After the runtime we must also specify its matching SDK. What is an SDK? Every runtime we saw above has a matching SDK, which contains everything that is contained in the environment, and, in addition, development tools and package headers. In our case we will use the org.freedesktop.Sdk SDK:

app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk

The specified runtime and sdk are not be installed automatically, we have to do it manually. To install them only for our user, from the flathub repository, we use the following command:

$ flatpak install flathub --user org.feedesktop.Platform.ffmpeg-full//21.08 org.freedesktop.Sdk//21.08

After specifying the app-id, the runtime, runtime-version and the sdk, we should provide the name of the main binary of the application. We do it via the command parameter:

app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
command: ffmpeg

The app modules



Another very important thing we have do specify inside the manifest file is the list of the modules which should be built. The most important module is the one dedicated to the application itself (ffmpeg in this case), the (eventual) others are dedicated to its dependencies. Modules are listed under the modules parameter of the manifest file:
app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
modules:
  - name: ffmpeg
    sources:
      - type: archive
        url: https://www.ffmpeg.org/releases/ffmpeg-4.4.1.tar.xz
        sha256: eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02
    config-opts:
      - --enable-gpl
      - --enable-libmp3lame
      - --enable-libopus
      - --enable-libvpx
      - --enable-libx264
      - --disable-static
      - --enable-shared
      - --disable-doc

Let’s analyze what we added in the manifest under the modules section. First of all, we specified the name of the module, ffmpeg. We than added the sources dictionary, where we specified various parameters. First of all the type of the source, which, can be one of the following:

  • archive (we use this for sources in tar archives)
  • git (to clone a git repository)
  • file (for local files)
  • dir (for local directories)
  • script (array of shell commands)
  • shell (array of shell commands run during source extraction)
  • patch
  • extra-data (extra data to be downloaded at install time)

In our case we used archive as the source type, since we want to download the archive containing the ffmpeg source code. With the url key we provided the URL of said archive, and with the sha256 parameter, the checksum which is used to verify it (the complete list of parameters which can be used for a source type is available here. We than specified a list of config-opts, which are the ones we would pass to the ./configure script when building the application manually.

Adding the sandbox permissions

Flatpak applications run in a sandbox, isolated from the main system, and are designed to have the least possible access to the host. If the application we are packaging needs specific permissions, we need to specify them inside the manifest file. In our case, for example, the application needs to read and write files to the host filesystem. Permissions are specified as a list, under the finish-args parameter:

app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
modules:
  - name: ffmpeg
    sources:
      - type: archive
        url: https://www.ffmpeg.org/releases/ffmpeg-4.4.1.tar.xz
        sha256: eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02
    config-opts:
      - --enable-gpl
      - --enable-libmp3lame
      - --enable-libopus
      - --enable-libvpx
      - --enable-libx264
      - --disable-static
      - --enable-shared
      - --disable-doc
finish-args:
  - --filesystem=home:rw

In this case we used the --filesystem=home:rw permissions: this grants the packaged application full access (read and write) to files inside our home directory. This could be too much, but will be ok for the sake of this tutorial. For a comprehensive list of the available permissions that can be specified inside this section, you can take a look at the dedicated page of the official documentation. The principle, however, is simple: give an application the least possible privileges.

Building the application

At this point, we theoretically have everything we need inside the manifest to build the flatpak. We open a terminal inside the directory where the manifest file is, and we run the following command:

$ flatpak-builder build org.linuxconfig.Ffmpeg.yml

The flatpak-builder command takes the directory in which the build should happen as first argument, and the manifest of the application as second. If we launch the command with our current manifest, however, we are notified of an error:

ERROR: libx264 not found

Why this happened? Since we specified the --enable-libx264 configure option for ffmpeg inside the manifest, we should also add a module to build the library which is needed by ffmpeg. Let’s do this. Our manifest becomes:

app-id: org.linuxconfig.FFmpeg
runtime: org.freedesktop.Platform
runtime-version: '21.08'
sdk: org.freedesktop.Sdk
modules:
  - name: x264
    sources:
      - type: git
        url: https://code.videolan.org/videolan/x264.git
    config-opts:
      - --enable-shared
  - name: ffmpeg
    sources:
      - type: archive
        url: https://www.ffmpeg.org/releases/ffmpeg-4.4.1.tar.xz
        sha256: eadbad9e9ab30b25f5520fbfde99fae4a92a1ae3c0257a8d68569a4651e30e02
    config-opts:
      - --enable-gpl
      - --enable-libmp3lame
      - --enable-libopus
      - --enable-libvpx
      - --enable-libx264
      - --disable-static
      - --enable-shared
      - --disable-doc
finish-args:
  - --filesystem=home:rw

In this case, to clone the repository containing the x264 sources, we specified git as the sources type, and provided the url of the repository. Let’s try to build the application again. This time we add the --force-clean option to the command, to clean the build directory which already contains stuff (an error would be generated otherwise):

$ flatpak-builder build org.linuxconfig.FFmpeg.yml --force-clean

This time the build process should be completed successfully.

Installing and running the application

Once the application is built we can install it. All we have to do is to run the following command:

$ flatpak-builder --user --install build --force-clean org.linuxconfig.FFmpeg.yml



After the installation is performed we can test the application works as intended. Just as an example we can try to convert a flac music file to the vorbis opus format. Here is what we would run:
$ flatpak run org.linuxconfig.FFmpeg \
  -i /home/egdoc/bk/Music/ripped/ac_dc/highway_to_hell/01_highway_to_hell.flac \
  -acodec libopus \
  -b:a 192K \
  01_highway_to_hell.opus

With the command above we converted the flac file /home/egdoc/bk/Music/ripped/ac_dc/highway_to_hell/01_highway_to_hell.flac to opus (-acodec libopus) with a variable bitrate of 192K (-b:a 192K) and saved it as 01_highway_to_hell.opus. All should have worked correctly!

Conclusions

The flatpak technology provides a universal method of distributing applications packaged with all their needed dependencies. In this tutorial we saw how to create a flatpak package for an application (ffmpeg): we saw how to install the needed software on the most commonly used Linux distributions, how to create and populate the “manifest” file with all the needed parameters (consult the flatpak-manifest manual for the complete list of parameters which can be used inside a manifest), and finally how to build, install and run the application.



Comments and Discussions