# Package Applications as Flatpaks ###### tags: `flatpak`, `GTK`, `pywebview`, `HTTP server`, `python`, `bottle` This includes examples to package applications as flatpak apps. ## Documents from Flatpak * [Basic concepts](https://docs.flatpak.org/en/latest/basic-concepts.html) * [Building your first Flatpak](https://docs.flatpak.org/en/latest/first-build.html) * [Manifests](https://docs.flatpak.org/en/latest/manifests.html) * [Requirements & Conventions](https://docs.flatpak.org/en/latest/conventions.html) * [Sandbox Permissions](https://docs.flatpak.org/en/latest/sandbox-permissions.html) * [Python](https://docs.flatpak.org/en/latest/python.html) Previous lightning talk: [Package a PyApp as a Flatpak Package: An HTTP Server for Example](https://www.slideshare.net/chienhungpan/package-a-pyapp-as-a-flatpak-package-an-http-server-for-example) ## The Comparison Between Container and Flatpak ![container-flatpak.jpg](https://hackmd.io/_uploads/H1mzL5476.jpg) * Container's key tech: [chroot](https://en.wikipedia.org/wiki/Chroot), [control groups (cgroups)](https://en.wikipedia.org/wiki/Cgroups), [Union Filesytem](https://en.wikipedia.org/wiki/UnionFS), and [namespaces](https://www.linux.com/news/understanding-and-securing-linux-namespaces/) ... * Flatpak uses: * Sandbox idea implemented by [**bubblewrap**](https://github.com/containers/bubblewrap), which is like a super-powered version of chroot. * Each file, including binary and library in the container cannot be shared with other containers. Unless the files come from the based on container image. * [**OSTree**](https://github.com/ostreedev/ostree) uses [**FUSE (Filesystem in Userspace)**](https://github.com/libfuse/libfuse) for mounting filesystem now. https://github.com/ostreedev/ostree/blob/v2023.7/configure.ac#L336-L338 * A flatpak application is based on a runtime, then adds some more files. The runtime is share with other flatpak applications. And, the runtime provides basic binaries and libraries. Some flatpak's security discussion: * [The flatpak security model – part 1: The basics](https://blogs.gnome.org/alexl/2017/01/18/the-flatpak-security-model-part-1-the-basics/) * [The flatpak security model – part 2: Who needs sandboxing anyway?](https://blogs.gnome.org/alexl/2017/01/20/the-flatpak-security-model-part-2-who-needs-sandboxing-anyway/) * [The flatpak security model, part 3 – The long game](https://blogs.gnome.org/alexl/2017/01/24/the-flatpak-security-model-part-3-the-long-game/) ## Install Flatpak Tools Some major Linux distributions, like Fodora, openSUSU and Endless OS have already pre-installed flatpak. Please follow [Flathub's **setup**](https://flathub.org/setup) for your OS distribution. If it is not installed, basically install it like: * `apt install flatpak flatpak-builder` * `yum install flatpak flatpak-builder` * `dnf install flatpak flatpak-builder` * `pacman -S flatpak flatpak-builder` * `apk add flatpak flatpak-builder` * … Then, add the Flathub repository ``` flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo ``` The **flatpak** is for common usage, and **flatpak-builder** is for packaging as a flatpak package. Not only x86(_64) platforms, but also [arm64](https://github.com/flatpak/flatpak-github-actions/blob/v4/README.md?plain=1#L74) and so on … ### Manual * [flatpak-builder](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html) * [flatpak](https://docs.flatpak.org/en/latest/flatpak-command-reference.html) ## Flatpak Runtime The `org.freedesktop.Sdk` runtime commands for developing, like **sh** & **echo**, compiler **gcc**, and **python** & **pip**. ```shell $ flatpak run --command=sh org.freedesktop.Sdk//23.08 [📦 org.freedesktop.Sdk ~]$ ls -l /bin/{sh,echo,gcc,python,pip} -rwxr-xr-x 5 nfsnobody nfsnobody 45736 Jan 1 1970 /bin/echo lrwxrwxrwx 1 nfsnobody nfsnobody 28 Nov 5 18:44 /bin/gcc -> x86_64-unknown-linux-gnu-gcc -rwxr-xr-x 7 nfsnobody nfsnobody 220 Jan 1 1970 /bin/pip lrwxrwxrwx 1 nfsnobody nfsnobody 16 Nov 5 18:44 /bin/python -> /usr/bin/python3 lrwxrwxrwx 1 nfsnobody nfsnobody 4 Nov 5 18:44 /bin/sh -> bash ``` The `org.freedesktop.Platform` runtime has commands for common usage, like **sh** & **echo** and **python**. But, no development tools. ```shell $ flatpak run --command=sh org.freedesktop.Platform//23.08 [📦 org.freedesktop.Platform ~]$ ls -l /bin/{sh,echo,gcc,python,pip} ls: cannot access '/bin/gcc': No such file or directory ls: cannot access '/bin/pip': No such file or directory -rwxr-xr-x 5 nfsnobody nfsnobody 45736 Jan 1 1970 /bin/echo lrwxrwxrwx 1 nfsnobody nfsnobody 16 Oct 31 20:34 /bin/python -> /usr/bin/python3 lrwxrwxrwx 1 nfsnobody nfsnobody 4 Oct 31 20:34 /bin/sh -> bash ``` PS. More well-known runtimes in [Available Runtimes](https://docs.flatpak.org/en/latest/available-runtimes.html). ## Common Usage ### Installation * If it is GNOME desktop, you can install flatpak applications from the Software/App Center directly: ![image](https://hackmd.io/_uploads/BJ1v03aXp.png) * Or, download the `.flatpakref` from [Flathub](https://flathub.org/) website: ![image](https://hackmd.io/_uploads/rykqMaaQT.png) Then, install application with the downloaded `.flatpakref`: ``` flatpak install <Application ID>.flatpakref ``` * Or, install the application with flatpak command directly: ``` flatpak install [flathub] <Application ID> ``` The "flathub" is the Flathub "REMOTE". ### Execute the Application * Click the desktop launcher with the icon. * Or, run with flatpak command: ``` flatpak run <Application ID> ``` ### Uninstallation * If it is GNOME desktop, you can uninstall the application from Software/App Center. * Or, uninstall the application with flatpak command: ``` flatpak uninstall [--delete-data] <Application ID> ``` "--delete-data": Delete app data ## Build A Simple Flatpak App 1. Go into work directory 2. Have a source file `run.sh`: ```shell $ cat run.sh #!/bin/sh echo "Hello world!" ``` 3. Have the manifest `io.github.starnight.simpledemo.yml` for build: ```shell $ cat io.github.starnight.simpledemo.yml app-id: io.github.starnight.simpledemo runtime: org.freedesktop.Platform runtime-version: '23.08' sdk: org.freedesktop.Sdk command: run.sh modules: - name: simpledemo buildsystem: simple build-commands: - install -D run.sh /app/bin/run.sh sources: - type: file path: run.sh ``` Note: More sources types can be found in [Manifests' Modules](https://docs.flatpak.org/en/latest/manifests.html#modules). PS. You may need the SDK. It can be installed from Flathub: ```shell flatpak install flathub org.freedesktop.Sdk//23.08 ``` 4. Build the `io.github.starnight.simpledemo` as a flatpak app, and install it: ``` flatpak-builder build-dir io.github.starnight.simpledemo.yml --force-clean --install --user ``` 5. Check `io.github.starnight.simpledemo` is installed: ``` $ flatpak list Name Application ID Version Branch Origin Installation simpledemo io.github.starnight.simpledemo master simpledemo-origin user ... Freedesktop Platform org.freedesktop.Platform 23.08.6 23.08 flathub system ... Freedesktop SDK org.freedesktop.Sdk 23.08.6 23.08 flathub system ... ``` 6. Run the `io.github.starnight.simpledemo` flatpak app ```shell $ flatpak info io.github.starnight.simpledemo ID: io.github.starnight.simpledemo Ref: app/io.github.starnight.simpledemo/x86_64/master Arch: x86_64 Branch: master Origin: simpledemo-origin Collection: Installation: user Installed: 2.0 kB Runtime: org.freedesktop.Platform/x86_64/23.08 Sdk: org.freedesktop.Sdk/x86_64/23.08 Commit: badf1daffd1f6ec3b4d3ca35bab60b4beecb15b22e7b3dc8fa041609d8913040 Subject: Export io.github.starnight.simpledemo Date: 2023-11-05 14:37:17 +0000 $ flatpak run --command=ls io.github.starnight.simpledemo /app/bin run.sh $ flatpak run io.github.starnight.simpledemo Hello world! ``` ## A GTK Demo Flatpak App 1. Get the GTK app in flatpak demo: ```shell git clone https://github.com/starnight/flatpak-example-gtkdemo ``` 2. GNOME 45 runtime has GTK 4 library: ```shell $ flatpak run --command=sh org.gnome.Sdk//45 [📦 org.gnome.Sdk ~]$ ls -l /lib/x86_64-linux-gnu/libgtk-4* lrwxrwxrwx 1 nfsnobody nfsnobody 13 Oct 31 20:34 /lib/x86_64-linux-gnu/libgtk-4.so -> libgtk-4.so.1 lrwxrwxrwx 1 nfsnobody nfsnobody 20 Oct 31 20:34 /lib/x86_64-linux-gnu/libgtk-4.so.1 -> libgtk-4.so.1.1200.3 -rwxr-xr-x 3 nfsnobody nfsnobody 8999080 Jan 1 1970 /lib/x86_64-linux-gnu/libgtk-4.so.1.1200.3 ``` 3. Follow README's [Build](https://github.com/starnight/flatpak-example-gtkdemo#build), and then [Execute](https://github.com/starnight/flatpak-example-gtkdemo#execute). ![image.png](https://hackmd.io/_uploads/Sy4qbVrXa.png) ## A WebView Demo Flatpak Using pywebview 1. Get the WebView app in flatpak demo: ``` git clone https://github.com/starnight/flatpak-example-pywebview ``` 2. Follow README's [Build](https://github.com/starnight/flatpak-example-pywebview#build), and then [Execute](https://github.com/starnight/flatpak-example-pywebview#execute). - Click the desktop launcher with the icon ![image](https://hackmd.io/_uploads/SklfBa2jXa.png) - It launches the WebView app ![image](https://hackmd.io/_uploads/H1d0i2iQT.png) ### Dependent Modules Because this example is written in Python and uses [pywebview](https://github.com/r0x0r/pywebview), which depends on [bottle](https://bottlepy.org/) ..., and more. The dependecies heads are listed in [**requirements.txt**](https://github.com/starnight/flatpak-example-pywebview/blob/main/requirements.txt). The dependencies, like pywebview and bottle ... must be installed as part of the flatpak app as well. So, we need [flatpak-builder-tools](https://github.com/flatpak/flatpak-builder-tools)'s **flatpak-pip-generator** to generate the required modules’ meta information for the manifest from [**requirements.txt**](https://github.com/starnight/flatpak-example-pywebview/blob/main/requirements.txt). ```shell $ git clone https://github.com/flatpak/flatpak-builder-tools $ python3 ~/flatpak-builder-tools/pip/flatpak-pip-generator --requirements-file=requirements.txt ``` The required modules’ meta information is generated & saved as [**python3-requirements.json**](https://github.com/starnight/flatpak-example-pywebview/blob/main/build-aux/flatpak/python3-requirements.json) in [Build's step 3](https://github.com/starnight/flatpak-example-pywebview/tree/main#build). Then, [**python3-requirements.json**](https://github.com/starnight/flatpak-example-pywebview/blob/43bae83d051f4fbb3d58540351ac2719663850b7/build-aux/flatpak/io.github.starnight.http.yml#L17) is invoked as a module by the flatpak's manifest. PS. flatpak-builder-tools depends on **requirements-parser** ### Exported Resources to Desktop According to [Freedesktop.org Specifications](https://specifications.freedesktop.org/): * [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#file-naming) defines desktop entry, or known as desktop launcher `<application ID>.dekstop`. The [desktop launcher](https://github.com/starnight/flatpak-example-pywebview/blob/main/src/io.github.starnight.http.desktop) should be saved under path `$XDG_DATA_DIRS/applications`. * [Icon Theme Specification](https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html) defines the dekstop launcher's icon. The [icon](https://github.com/starnight/flatpak-example-pywebview/blob/main/src/assets/http-svgrepo-com.svg) should be saved under path `$XDG_DATA_DIRS/icons`. Because this flatpak demo is in user installations, the [**desktop launcher**](https://github.com/starnight/flatpak-example-pywebview/blob/43bae83d051f4fbb3d58540351ac2719663850b7/build-aux/flatpak/io.github.starnight.http.yml#L24) and the [**icon**](https://github.com/starnight/flatpak-example-pywebview/blob/43bae83d051f4fbb3d58540351ac2719663850b7/build-aux/flatpak/io.github.starnight.http.yml#L26) in the flatpak are exported into user's `~/.local/share/flatpak/exports/share`: ```shell $ echo $XDG_DATA_DIRS /home/zack/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/ $ ls -l ~/.local/share/flatpak/exports/share/applications/io.github.starnight.http.desktop lrwxrwxrwx 1 zack zack 111 Nov 10 22:16 /home/zack/.local/share/flatpak/exports/share/applications/io.github.starnight.http.desktop -> ../../../app/io.github.starnight.http/current/active/export/share/applications/io.github.starnight.http.desktop $ ls -l ~/.local/share/flatpak/exports/share/icons/hicolor/scalable/apps/io.github.starnight.http.svg lrwxrwxrwx 1 zack zack 131 Nov 10 22:16 /home/zack/.local/share/flatpak/exports/share/icons/hicolor/scalable/apps/io.github.starnight.http.svg -> ../../../../../../app/io.github.starnight.http/current/active/export/share/icons/hicolor/scalable/apps/io.github.starnight.http.svg ``` ### Flatpak Installation Path According to [flatpak-installation](https://docs.flatpak.org/en/latest/flatpak-command-reference.html#flatpak-installation): * system-wide: `$prefix/var/lib/flatpak/` ```shell $ flatpak info --show-location org.gnome.gedit /var/lib/flatpak/app/org.gnome.gedit/x86_64/stable/09a23c12f530b56b84db84dc8cbc24d949f352e154c1a5aef5cdaaf3df2f573c ``` * user: `$HOME/.local/share/flatpak/` ```shell $ flatpak info --show-location io.github.starnight.http /home/zack/.local/share/flatpak/app/io.github.starnight.http/x86_64/master/e44f532e79374461e4e3c32db5f11ef75c1a7dee03fa7634c64a46c88dff5f19 ``` ## Appendix ### Publish to Flathub Flathub's [For app authors](https://docs.flathub.org/docs/category/for-app-authors): * [Submission](https://docs.flathub.org/docs/for-app-authors/submission) * [AppData guidelines](https://docs.flathub.org/docs/for-app-authors/appdata-guidelines/) * [Requirements](https://docs.flathub.org/docs/for-app-authors/requirements/) * ... ### Update Modules (Half) Automatically Flatpak app builds with external data (git checkouts, tarballs, simple files, etc.) listed as **modules** in the manifest. Maintaining the external data's source/link is important. [Flatpak External Data Checker](https://github.com/flathub/flatpak-external-data-checker) is a tool to create pull requests to the repository on GitHub automatically, if there is new version of the external data's source/link. * Runner: [GitHub's action as the runner](https://github.com/flathub/flatpak-external-data-checker#custom-workflow) * And, add [`"x-checker-data"` into each modules](https://github.com/flathub/flatpak-external-data-checker#changes-to-flatpak-manifests) of the manifest Will Thompson shared a talk: "[Automate your Flatpak manifest updates today](https://conf.linuxappsummit.org/event/3/contributions/60/attachments/19/52/8%20Will%20Thompson%20%E2%80%93%20Automate%20y%20our%20Flatpak%20manifest%20updates%20today.pdf)" {%youtube c_dG_ngnJk4 %} The [WebView Demo](#A-WebView-Demo-Flatpak-Using-pywebview) uses [Flatpak External Data Checker](https://github.com/flathub/flatpak-external-data-checker) to update the dependencies: * [GitHub action](https://github.com/starnight/flatpak-example-pywebview/blob/main/.github/workflows/update.yaml) * The [`x-checker-data`](https://github.com/starnight/flatpak-example-pywebview/blob/43bae83d051f4fbb3d58540351ac2719663850b7/build-aux/flatpak/python3-requirements.json#L12-L15) section as an example ### AppStream MetaInfo This is more related to the original application, because it should come from there. However, Flathub reads the application's metainfo, then renders the introduction on Flathub. And, Software/App Center does the same thing. [AppStream metadata](https://docs.appimage.org/packaging-guide/optional/appstream.html): * AppStream's [Metadata Quickstart](https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html#sect-Quickstart-DesktopApps) * [AppData guidelines](https://docs.flathub.org/docs/for-app-authors/appdata-guidelines/) Cassidy James Blaede shared a talk: "[How to make a delightful app listing](https://events.gnome.org/event/101/contributions/471/attachments/202/427/How%20to%20Make%20a%20Delightful%20App%20Listing%20-%20Cassidy%20James%20Blaede%20-%20GUADEC%202023.pdf)" {%youtube jIDk0frev7M %} Note: The talk starts at 12 minute of the video.