# 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'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:

* Or, download the `.flatpakref` from [Flathub](https://flathub.org/) website:

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).

## 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

- It launches the WebView app

### 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.