I occasionally discussed the modern alternatives to using packages, meaning AppImages, Flatpaks and snaps. Politics and hatred aside, both Flatpaks and snaps are usable. AppImages, on the other hand, are an abomination.

Let’s accept this limitation

I’m not sure whether they’re flawed by design, or if their creators are often dumb. I’ll give you a few examples.

Before that, let me stress that AppImages do have a limitation by design: there is no way to theme them! If they’re designed to look a certain way, this is how they’ll look. A Flatpak app that supports theming can be themed once its permissions are properly granted, the easiest way being through Flatseal. I noticed this difference while I was finding ways to use various apps under AlmaLinux KDE. Such an example can be found towards the end of that post; look for the screenshots showing DB Browser for SQLite as AppImage vs. the same as a normal app.

How they’re broken by design

But at least they should work, right? The official documentation says:

Do not depend on system-provided resources

The author of an AppImage needs to decide for which target systems (Linux distributions) they want to offer the AppImage. Then, the author needs to bundle any dependencies that cannot reasonably be assumed to come with every target system (Linux distributions) in its default installation in a recent enough version.

To be able to run on any Linux distribution, an AppImage should bundle all the resources it needs at runtime that cannot be reasonably expected to be “there” in the default installation of all still-supported target systems (Linux distributions). The most common resources are the actual binaries, shared library dependencies, icons and other graphics and of course one or more desktop files for desktop integration.

This doesn’t mean an AppImage must not use resources provided by the system, like for example basic libraries that can be assumed to be part of every target system (e.g., the C standard library or graphics libraries), user interface themes or the like. See the excludelist for a list of the libraries we consider to currently be part of each still-supported target system (distribution).

Except that they do depend on some system-provided resources! This concept is fucked-up. The exclusion list, too. The way the developers don’t properly observe that list is the cherry on the cake.

As long as they’re based on the One app = one file concept, AppImages should include everything! But they don’t, which means there are fat chances they won’t work.

Why they should include everything

There’s one major difference between AppImages and any of Flatpaks or snaps: there’s no AppImage subsystem. What do I mean by this?

When you design a solution against “package dependency hell” (in Linux) or “DLL hell” (in Windows), you should really make sure you include every single shared library that might be missing or ❷ might be present in a version that your app can’t work with (incomplete ABI compatibility). I remember all those Windows apps that installed in their own folders (or sometimes globally) everything, such as the MSVCRT.DLL shit, the .NET crap, even OCX files in older versions of Windows. Only what’s part of the core Windows wasn’t duplicated. But what’s “core” in Linux, and since when is Linux backward compatible at the ABI level? It isn’t and it never was! And just take a look at the comments in the exclusion list!

Duplication is minimized in a very specific way in the Flatpak and snap architectures.

As I mentioned in my post about shifting from AlmaLinux KDE to Ubuntu MATE, specifically in chapter 2 and chapter 9, the Flatpak and snap subsystems include shared versions of GNOME, KDE, and other libraries:

$ snap list
Name               Version          Rev    Tracking         Publisher   Notes
bare               1.0              5      latest/stable    canonical✓  base
core22             20240904         1621   latest/stable    canonical✓  base
core24             20240710         490    latest/stable    canonical✓  base
firefox            131.0-1          5018   latest/stable/…  mozilla✓    -
firmware-updater   0+git.5007558    127    latest/stable/…  canonical✓  -
gnome-42-2204      0+git.510a601    176    latest/stable/…  canonical✓  -
gnome-46-2404      0+git.5d6be1b    48     latest/stable/…  canonical✓  -
gtk-common-themes  0.1-81-g442e511  1535   latest/stable/…  canonical✓  -
gtk-theme-breeze   1.0              2      latest/stable/…  kde✓        -
icon-theme-breeze  1.0              3      latest/stable/…  kde✓        -
mesa-2404          24.0.9           143    latest/stable/…  canonical✓  -
snapd              2.63             21759  latest/stable    canonical✓  snapd
thunderbird        128.2.2esr-1     518    latest/stable/…  canonical✓  -

The idea is as follows:

  • When multiple Flatpak apps need the same version of a runtime, it is installed once and used by all the applications that require it. If different applications require different versions of the same library, Flatpak will handle these cases by installing the necessary version for each specific application, ensuring compatibility. Shared frameworks include “platforms” such as GNOME and KDE, but also graphics, codecs, themes, etc.
  • Snap packages can also share libraries through the “core22” and “core24” (or other core versions) bases, then through GNOME and other libraries. Similar to Flatpak, if multiple Snap applications require the same libraries, they can share the installed version without duplication.

Despite such shared resources taking up to a couple of GB, the duplication is less severe than if each app had brought its own copy of the required libraries!

However, AppImages are supposed to “just run” without benefiting or any shared resources. There’s no AppImage subsystem! Therefore, using AppImages is a form of Russian roulette.

Let the show begin!

Since on each Linux computer I use a home partition that’s separate from the root partition (a separate SSD, actually), I always inherit my full profile across distros. So I got in Ubuntu all the AppImages I was using with AlmaLinux! Before even trying to search for the existence of official Ubuntu packages or of PPAs, I thought of giving a try to some of them.

🟢 Some AppImages worked, such as:

  • DB_Browser_for_SQLite-v3.12.2-x86_64.AppImage
  • FBReader_Book_Reader-x86_64-2.1.AppImage

🔴 Some failed to work, including:

  • Freezer-1.1.24.AppImage
  • marktext-x86_64.AppImage
  • Nulloy-0.9.9-x86_64.AppImage
  • Obsidian-1.6.5.AppImage and Obsidian-1.7.4.AppImage

There is a distinction to be made here. Some of the AppImages that don’t work under Ubuntu 24.04 are Electron apps (Chromium + JS), some aren’t. Electron is the second-worst thing after anal rape, but for some reason it’s still used. And it’s not only slow; it can also be buggy.

The Electron apps failed the same way:

ludditus@grumpy:~/Downloads$ ./Freezer-1.1.24.AppImage 
[173303:1031/000045.327959:FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that /tmp/.mount_FreezedS6CuI/chrome-sandbox is owned by root and has mode 4755.
Trace/breakpoint trap (core dumped)
ludditus@grumpy:~/Downloads$ ./marktext-x86_64.AppImage 
[171785:1030/235339.197122:FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that /tmp/.mount_markte7SgCbu/chrome-sandbox is owned by root and has mode 4755.
Trace/breakpoint trap (core dumped)
ludditus@grumpy:~/Downloads$ ./Obsidian-1.7.4.AppImage 
[173031:1030/235915.251880:FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that /tmp/.mount_ObsidiOvhpbh/chrome-sandbox is owned by root and has mode 4755.
Trace/breakpoint trap (core dumped)

Non-Electron apps can have different ways of saying, “look at me how dumb I am”:

ludditus@grumpy:~/Downloads$ ./Nulloy-0.9.9-x86_64.AppImage 
Gtk-Message: 23:59:46.425: Failed to load module "appmenu-gtk-module"
Gtk-Message: 23:59:46.426: Failed to load module "appmenu-gtk-module"
Gtk-Message: 23:59:46.427: Failed to load module "atk-bridge"
/tmp/.mount_Nulloy5jvWOv/usr/bin/nulloy: symbol lookup error: /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libgail.so: undefined symbol: g_once_init_enter_pointer

To fix or not to fix

Obsidian being a rather popular piece of software, I was bound to find references: Obsidian AppImage – The SUID sandbox helper binary was found, but is not configured correctly.

Moderator’s Note: There is currently an issue in AppArmor (Launchpad Bugs #2046844, #2064672 (SRU’d fix for Noble), and #2072811 (the regression bug that reverted it)) that is known to be causing problems with sandboxing of AppImages and such at this time.

There is currently no ETA on a fix for this issue at this time. Due to that, if your application you are trying to use is absolutely critical to your needs, you can use the options stated here to run the application without sandboxing. However, be advised that this can be dangerous as this lets the application directly alter things on your system.

Note that if you choose to use this answer’s solutions, you accept all security risks of running any applications unsandboxed. Ask Ubuntu and the poster of this answer accept no responsibility if you damage your system in some way running applications in this manner.

Answer author’s Note: The method described below seemed to be the only option at the time I wrote this answer. Due to the security issues this method should not be used anymore. Apparmor has been updated since and now we can use an apparmor profile which allows the application the use of unprivileged usernamspaces, please see my other answer.

Insisting that all hell would break loose if you don’t use AppArmor or SELinux is stupid. Linux distros existed before AppArmor and SELinux were invented, and they were working just fine. Considering that every single piece of software has a huge potential for malevolence and that the system is ridden with zero-day vulnerabilities is simply FUD. It’s like only screwing with your wife, which doesn’t cheat on you, yet being obsessed with getting an STD. But let’s keep using AppArmor in this case.

So there are two workarounds:

  1. Running the AppImage file with --no-sandbox
  2. Creating an AppArmor profile for that AppArmor

Disabling the sandboxing works for Obsidian and other AppImages:

ludditus@grumpy:~/Downloads$ ./Obsidian-1.7.4.AppImage --no-sandbox
2024-10-30 22:02:20 Loading main app package /tmp/.mount_ObsidiUsM490/resources/obsidian.asar
2024-10-30 22:02:21 Checking for update using Github
[173576:1031/000221.460450:ERROR:nss_util.cc(345)] After loading Root Certs, loaded==false: NSS error code: -8018
2024-10-30 22:02:21 Success.
2024-10-30 22:02:21 Latest version is 1.7.4
2024-10-30 22:02:21 App is up to date.

and it works! This one works too, despite the apparent error:

ludditus@grumpy:~/Downloads$ ./marktext-x86_64.AppImage --no-sandbox
strict mode: missing type "string" for keyword "pattern" at "#/properties/spellcheckerLanguage" (strictTypes)
libva error: /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so init failed
[173798:1031/000318.202087:ERROR:sandbox_linux.cc(374)] InitializeSandbox() called with multiple threads in process gpu-process.

Also, creating an AppArmor profile works too. I created a file /etc/apparmor.d/Obsidian with the following content:

abi <abi/4.0>,
include <tunables/global>

profile Obsidian /home/ludditus/Downloads/Obsidian-1.7.4.AppImage flags=(unconfined) {
  userns,
}

It looks like shit, but it’s simpler than SELinux. Then I ran:

sudo systemctl reload apparmor.service
sudo systemctl daemon-reload

And then it worked.

However, not all AppImages that don’t work can be fixed. That’s because they’re fucking broken.

Fixing Nulloy

Nulloy displaying an error that has nothing to do with permissions, it cannot be fixed by using --no-sandbox. It would just spit out the same error, and die.

But it can be installed in Ubuntu as a package:

. /etc/os-release
sudo apt install curl
curl -fsSL https://download.opensuse.org/repositories/multimedia:/apps:/nulloy/$VERSION_CODENAME/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/nulloy.gpg
echo "deb https://download.opensuse.org/repositories/multimedia:/apps:/nulloy/$VERSION_CODENAME/ /" | sudo tee /etc/apt/sources.list.d/nulloy.list
sudo apt update
sudo apt install nulloy

Fixing Freezer

Freezer is a special animal. You shouldn’t be using it. It’s immoral, it breaks Deezer’s TOS, and in theory it’s probably illegal. It’s even abandoned, but it still works, but for the fact that it can’t display the home page. Its final 1.1.24 build can be found here.

But it fails to run even with --no-sandbox, despite being an Electron app:

ludditus@grumpy:~/Downloads$ ./Freezer-1.1.24.AppImage --no-sandbox
error: Unhandled Exception: ArgError: unknown or unexpected option: --no-sandbox
Stack: ArgError: unknown or unexpected option: --no-sandbox
    at arg (/tmp/.mount_FreezeS7bIsj/resources/app.asar/node_modules/arg/index.js:98:13)
    at Object.<anonymous> (/tmp/.mount_FreezeS7bIsj/resources/app.asar/background.js:19:14)
    at Module._compile (internal/modules/cjs/loader.js:1078:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1108:10)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12913)
    at Object.<anonymous> (electron/js2c/browser_init.js:193:3237)
    at Object../lib/browser/init.ts (electron/js2c/browser_init.js:193:3441)
    at __webpack_require__ (electron/js2c/browser_init.js:1:128)
libva error: /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so init failed

In Fedora 41, the error is different, because the problem is not a permission issue:

liveuser@localhost-live:~/Downloads$ ./Freezer-1.1.24.AppImage 
error: Unhandled Exception: Error: libcrypto.so.1.1: cannot open shared object file: No such file or directory
Stack: Error: libcrypto.so.1.1: cannot open shared object file: No such file or directory
    at process.func [as dlopen] (electron/js2c/asar_bundle.js:5:1846)
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:1138:18)
    at Object.func [as .node] (electron/js2c/asar_bundle.js:5:2073)
    at Module.load (internal/modules/cjs/loader.js:935:32)
    at Module._load (internal/modules/cjs/loader.js:776:14)
    at Function.f._load (electron/js2c/asar_bundle.js:5:12913)
    at Module.require (internal/modules/cjs/loader.js:959:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at bindings (/tmp/.mount_FreezeJNZZ37/resources/app.asar/node_modules/bindings/bindings.js:112:48)
    at Object.<anonymous> (/tmp/.mount_FreezeJNZZ37/resources/app.asar/node_modules/nodeezcryptor/decryptor.js:1:38)

The problem is the way the AppImage is built. And not only it, because there’s also a .deb file available!

In Ubuntu 24.04, trying to install the .deb file using GDebi fails because of the following unmet dependencies:

  • libflac8
  • libssl1.1 | libssl1.0.0

Don’t look for such packages in Ubuntu 24.04, as they don’t exist! This is the problem with poorly-built AppImages: they expect obsolete packages that don’t ship anymore with newer distros! In this case, the .deb was built with the same wrong expectations as the AppImage.

Fortunately, these dependencies can be solved by the manual download and installation of the proper packages that provide such old dependencies:

Now freezer_1.1.24_amd64.deb would install just fine.

“By using this program, you disagree with Deezer’s ToS.”

Deezer stopped supporting some countries (so it never supported them); therefore, some people might need to temporarily use a VPN (until they get that arl string, which is a cookie). Obviously, Spotify is better, but there’s no such hack for it.

Bottom line

AppImages are indeed the worst possible choice! If they “just work” in a distro, this doesn’t mean they’ll keep working in the future or in a different distro, which really nullifies their “portability” and their raison d’être.

Over and out.