Double-click an AppImage on a fresh Fedora Workstation and, depending on how that AppImage was built, nothing happens. No window, no dialog, no error on screen. The failure goes to the journal, and most people never look there.
This guide shows how to run AppImages on Fedora properly. You’ll check which runtime an AppImage uses, install the FUSE 2 library the older ones need (fuse-libs on Workstation, rpm-ostree layering on Silverblue and Kinoite), run one with no FUSE at all, and add it to the GNOME app menu with Gear Lever or a hand-written desktop entry. One rule applies throughout: an AppImage runs with your full user privileges and no sandbox, so treat every download as code you are about to execute.
Tested October 2026 on Fedora 45 Workstation and Silverblue with SELinux enforcing, then repeated on Fedora 44.
Why some AppImages fail on Fedora and others don’t
An AppImage is a squashfs image with a small runtime binary at the front. The runtime mounts the image with FUSE and starts the app inside it. There are two runtimes in circulation, and they need different things from the host.
The older runtime loads libfuse.so.2 at run time and calls the FUSE 2 fusermount helper. The newer static runtime from the AppImage project has FUSE 3 compiled in and works with the fusermount3 helper every Fedora edition already has. Fedora ships FUSE 3 everywhere. FUSE 2 is a different story:
| Fedora edition | fuse (fusermount) | fuse-libs (libfuse.so.2) | FUSE 3 |
|---|---|---|---|
| Workstation 45 | installed | not installed | installed |
| Cloud 45 | not installed | not installed | installed |
| Silverblue 45 and Kinoite 45 | not installed | not installed | installed |
| Silverblue 44 | not installed | not installed | installed |
So a static-runtime AppImage runs on every edition, and an old-runtime AppImage fails on all of them until you add FUSE 2. We tested three real AppImages on Workstation with nothing extra installed. Obsidian failed. Joplin and appimagetool ran.
You can tell which runtime a file uses before you run it. The old runtime carries the string libfuse.so.2 in its first megabyte:
cd ~/Applications; for f in *.AppImage; do printf "%-34s " $f; head -c 1000000 $f | grep -c -a "libfuse.so.2"; done
Any non-zero count means the AppImage needs FUSE 2:
Joplin-3.7.21.AppImage 0
Obsidian-1.14.4.AppImage 5
appimagetool-x86_64.AppImage 0
Step 1: Download the AppImage and verify it
Download from the project’s own release page, never from a mirror or a “free download” site. Keep AppImages in one place in your home directory so you know what you are running. The commands below fetch the latest Obsidian release into ~/Applications:
mkdir -p ~/Applications && cd ~/Applications
OBS_URL=$(curl -s https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest | grep -oE "https://[^\"]*Obsidian-[0-9.]+\.AppImage" | head -1)
curl -LO "$OBS_URL"
Then check the file against the digest GitHub publishes for each release asset. jq was already installed on our Workstation; add it with sudo dnf install jq if yours lacks it:
curl -s https://api.github.com/repos/obsidianmd/obsidian-releases/releases/latest | jq -r '.assets[] | select(.name|endswith(".AppImage")) | "\(.digest) \(.name)"'
sha256sum ~/Applications/Obsidian-*.AppImage
The x86_64 digest and the local hash must match character for character. Ours did:
sha256:721829a4f0ffadf7674f396aed58a5699e116b76b78747873d1751193efb66a9 Obsidian-1.14.4-arm64.AppImage
sha256:6362ddbeeeebb7bbccb48fae009572cf2284ef92f5c919c1332aba48de6ffeaa Obsidian-1.14.4.AppImage
6362ddbeeeebb7bbccb48fae009572cf2284ef92f5c919c1332aba48de6ffeaa /home/mercy/Applications/Obsidian-1.14.4.AppImage
If they do not match, delete the file. Do not run it to “see what happens”.
Step 2: Make the AppImage executable
Downloaded files are not executable, and an AppImage that is not executable won’t start. From a terminal:
chmod +x ~/Applications/Obsidian-*.AppImage
In GNOME Files, right-click the file, open Properties and turn on Executable as Program. The switch sets the same execute bits:

Step 3: Run it and read the real error
Start the AppImage from a terminal the first time, not from Files. The terminal shows you what the desktop hides:
~/Applications/Obsidian-*.AppImage
An old-runtime AppImage on a stock Workstation stops before the app loads:
dlopen(): error loading libfuse.so.2
AppImages require FUSE to run.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
See https://github.com/AppImage/AppImageKit/wiki/FUSE
for more information
Double-clicking the same file in Files gives you nothing at all. The window stays as it was, and no error appears:

The error is in your user journal. Search it when a double-click does nothing:
journalctl --user -b --no-pager -o short-iso | grep -A5 "libfuse.so.2"
The runtime logged the same message under the AppImage’s own name:
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: dlopen(): error loading libfuse.so.2
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: AppImages require FUSE to run.
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: You might still be able to extract the contents of this AppImage
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: if you run it with the --appimage-extract option.
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: See https://github.com/AppImage/AppImageKit/wiki/FUSE
2026-10-05T21:25:53+03:00 ws-lab01 Obsidian-1.14.4.AppImage[2452]: for more information
A static-runtime AppImage behaves differently. Joplin opened from Files on the same machine with no extra packages:

It mounted itself with FUSE 3. The mount type shows the image name:
mount | grep -i joplin
The mount is read-only, nosuid and owned by your user:
Joplin-3.7.21.AppImage on /tmp/.mount_JoplinagoFbp type fuse.Joplin-3.7.21.AppImage (ro,nosuid,nodev,relatime,user_id=1001,group_id=1001)
Step 4: Install FUSE 2 on Fedora Workstation and Server
Install both FUSE 2 packages. fuse-libs provides libfuse.so.2, and fuse provides the fusermount helper the old runtime calls. Workstation already has fuse, but Cloud and minimal installs do not, and the library alone is not enough (Step 5 shows that failure):
sudo dnf install fuse fuse-libs
On Workstation only the library was new:
Package "fuse-2.9.9-26.fc45.x86_64" is already installed.
Package Arch Version Repository Size
Installing:
fuse-libs x86_64 0:2.9.9-26.fc45 fedora 300.9 KiB
Run the AppImage with --appimage-mount to prove the runtime works without starting the app. It prints the mount point and holds the mount until you stop it:
~/Applications/Obsidian-*.AppImage --appimage-mount
The image is now mounted under /tmp:
/tmp/.mount_Obsidi57H68e
In a second terminal, the mount table shows it as a read-only FUSE filesystem:
mount | grep -i obsidian
It is mounted read-only, nosuid, as your user:
/home/mercy/Applications/Obsidian-1.14.4.AppImage on /tmp/.mount_Obsidi57H68e type fuse.Obsidian-1.14.4.AppImage (ro,nosuid,nodev,relatime,user_id=1001,group_id=1001)
Press Ctrl+C to unmount. The same file now opens from Files:

Neither runtime triggered an SELinux denial on our enforcing system. We counted AVCs that mention AppImage or FUSE after all the tests:
echo "matches: $(sudo ausearch -m AVC -ts today 2>/dev/null | grep -ciE "appimage|fuse")"
The count was zero:
matches: 0
Step 5: Run AppImages on Silverblue and Kinoite
Fedora Atomic desktops ship neither FUSE 2 package. We checked the current Silverblue and Kinoite images directly:
VERSION="45.20261001.n.0 (Silverblue Prerelease)"
package fuse-libs is not installed
package fuse is not installed
fuse3-libs-3.18.3-1.fc45.x86_64
ls: cannot access '/usr/lib64/libfuse.so.2*': No such file or directory
VERSION="45.20261001.n.0 (Kinoite Prerelease)"
package fuse-libs is not installed
package fuse is not installed
fuse3-libs-3.18.3-1.fc45.x86_64
ls: cannot access '/usr/lib64/libfuse.so.2*': No such file or directory
Most guides tell you to layer fuse-libs and reboot. We did exactly that on a Silverblue machine, and the AppImage still failed after the reboot:
fuse: failed to exec fusermount: No such file or directory
Cannot mount AppImage, please check your FUSE setup.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
See https://github.com/AppImage/AppImageKit/wiki/FUSE
for more information
open dir error: No such file or directory
Error: “fuse: failed to exec fusermount: No such file or directory”
The library loaded this time, then the runtime tried to call the FUSE 2 fusermount helper, which lives in the fuse package. Layer both packages together. --apply-live applies them to the running system, so you do not have to reboot:
sudo rpm-ostree install --apply-live fuse fuse-libs
From a clean deployment, both packages went in without a reboot:
Added:
fuse-2.9.9-26.fc45.x86_64
fuse-libs-2.9.9-26.fc45.x86_64
Successfully updated running filesystem tree.
The --appimage-mount test from Step 4 then mounted Obsidian straight away.
Layering costs you a little: rpm-ostree reapplies those two packages on every future upgrade. If you would rather keep the base image untouched, run old-runtime AppImages with the flag in the next step, or ask the project for a static-runtime build. The Silverblue package management guide covers how layering and removal work.
Step 6: Run an AppImage without FUSE at all
Every type 2 AppImage runtime accepts --appimage-extract-and-run. It unpacks the image to a temporary directory and starts the app from there, with no FUSE involved:
~/Applications/Obsidian-*.AppImage --appimage-extract-and-run
The cost is space, and on Fedora that means RAM. While the app runs, check the extracted copy from a second terminal:
du -sh /tmp/appimage_extracted_*; df -h /tmp; findmnt -no FSTYPE /tmp
/tmp is a tmpfs, and Obsidian unpacked to 343 MB:
343M /tmp/appimage_extracted_6040e6eb46f215c8fbba5471e1e956f7
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.9G 343M 3.6G 9% /tmp
tmpfs
The runtime waits for the app and deletes the directory when it exits, so closing the window normally cleaned up. Killing the runtime itself does not. We stopped the whole app with systemctl --user stop, which is what a logout or an OOM kill does, and the copy stayed behind:
ls -d /tmp/appimage_extracted_*
The directory was still there:
/tmp/appimage_extracted_6040e6eb46f215c8fbba5471e1e956f7
It stays there until the next reboot. Clean up after that kind of exit with rm -rf /tmp/appimage_extracted_*. Use this flag for one-off runs and locked-down machines, not as your default.
Step 7: Add the AppImage to the GNOME app menu
An AppImage does not appear in Activities until something writes a desktop entry for it. There are two ways to do that.
Option A: Gear Lever
Gear Lever is a Flathub app that registers itself as the handler for AppImage files. It needs the Flathub remote, which a fresh Workstation keeps disabled until you enable third-party repositories (our Flatpak and Flathub guide covers that). Install it system-wide:
sudo flatpak install flathub it.mijorus.gearlever
Read its permissions before you trust it with your files:
flatpak info --show-permissions it.mijorus.gearlever
It has full access to your home directory and the host filesystem, plus talk access to org.freedesktop.Flatpak, the session helper behind flatpak-spawn --host, which lets it run any command on the host outside its sandbox. That is what it needs to manage AppImages. It also means the Flatpak packaging gives you no isolation here:
[Context]
shared=ipc;network;
sockets=fallback-x11;wayland;
devices=dri;
filesystems=/tmp;host;
[Session Bus Policy]
org.freedesktop.Flatpak=talk
Open the AppImage in Gear Lever. The file is already executable from Step 2, so a double-click in Files would start the app itself; use the terminal:
flatpak run it.mijorus.gearlever ~/Applications/Obsidian-*.AppImage
Click Move to the app menu:

Gear Lever moves the file rather than copying it. It renamed Obsidian-1.14.4.AppImage to ~/AppImages/obsidian.appimage, extracted the icon, and wrote a desktop entry:
Name=Obsidian
Icon=/home/mercy/AppImages/.icons/obsidian
TryExec=/home/mercy/AppImages/obsidian.appimage
Exec=env DESKTOPINTEGRATION=1 /home/mercy/AppImages/obsidian.appimage --no-sandbox %U
X-AppImage-Version=1.14.4
X-AppImage-Name=Obsidian
Obsidian then showed up in Activities search like any installed app:

Look at the Exec line. Gear Lever copied --no-sandbox from the desktop file inside the Obsidian AppImage, whose own Exec line is AppRun --no-sandbox %U. That flag turns off Chromium’s sandbox. Fedora allows unprivileged user namespaces, so the sandbox works here. We compared the processes both ways: without the flag, Obsidian’s sandboxed zygote ran in its own user namespace, and with the flag, every process stayed in the host namespace. Remove it:
sed -i "s/ --no-sandbox//" ~/.local/share/applications/obsidian.desktop
grep ^Exec ~/.local/share/applications/obsidian.desktop
The launch line no longer disables the sandbox:
Exec=env DESKTOPINTEGRATION=1 /home/mercy/AppImages/obsidian.appimage %U
Launched from Activities with the edited entry, Obsidian started normally, and two of its zygote processes ran in a separate user namespace from the host:
zygote 8432 user:[4026531837]
zygote 8433 user:[4026533121]
zygote 8435 user:[4026533121]
zygote 8544 user:[4026531837]
host user:[4026531837]
With Gear Lever installed, double-clicking an AppImage that is not executable yet opens Gear Lever instead of failing, so you can integrate a fresh download in one step:

Option B: Write the desktop entry by hand
You do not need another app for this. Pull the desktop file and an icon out of the AppImage, point Exec at the AppImage, and drop both into your home directory. Here it is for Joplin, downloaded the same way as Obsidian in Step 1:
cd ~/Applications
JOP_URL=$(curl -s https://api.github.com/repos/laurent22/joplin/releases/latest | grep -oE "https://[^\"]*Joplin-[0-9.]+\.AppImage" | head -1)
curl -LO "$JOP_URL" && chmod +x Joplin-*.AppImage
Move it next to your other AppImages and extract the two files:
mkdir -p ~/AppImages && mv ~/Applications/Joplin-*.AppImage ~/AppImages/joplin.AppImage
cd /tmp
~/AppImages/joplin.AppImage --appimage-extract "*.desktop"
~/AppImages/joplin.AppImage --appimage-extract "usr/share/icons/hicolor/256x256/apps/joplin.png"
install -Dm644 squashfs-root/usr/share/icons/hicolor/256x256/apps/joplin.png ~/.local/share/icons/hicolor/256x256/apps/joplin.png
sed "s|^Exec=AppRun|Exec=$HOME/AppImages/joplin.AppImage|" squashfs-root/*.desktop > ~/.local/share/applications/joplin.desktop
rm -rf squashfs-root
The .DirIcon at the root of most AppImages is a symlink, and --appimage-extract writes the link without its target, so extract the icon from its real path under usr/share/icons. Validate the entry:
desktop-file-validate ~/.local/share/applications/joplin.desktop && cat ~/.local/share/applications/joplin.desktop
No validation errors, and Exec now points at the AppImage:
[Desktop Entry]
Name=Joplin
Exec=/home/mercy/AppImages/joplin.AppImage %U
Terminal=false
Type=Application
Icon=joplin
StartupWMClass=appimagekit-joplin
X-AppImage-Version=3.7.21
MimeType=x-scheme-handler/joplin;
Comment=Joplin for Desktop
Categories=Office;
GNOME picks up the new entry without a logout:

Step 8: Remove an AppImage completely
Gear Lever’s Remove button deletes the AppImage, its icon and its desktop entry. It leaves the app’s settings behind. After removing Obsidian, its config directory was still there:
du -sh ~/.config/obsidian
Three megabytes of settings remained:
3.0M /home/mercy/.config/obsidian
For a hand-integrated AppImage, delete the three files you created, then the app’s data. Joplin keeps it in two directories:
rm ~/AppImages/joplin.AppImage ~/.local/share/applications/joplin.desktop ~/.local/share/icons/hicolor/256x256/apps/joplin.png
rm -rf ~/.config/joplin-desktop ~/.config/Joplin
Check ~/.config and ~/.local/share for a directory named after the app before you call it gone.
Before you run the next AppImage
AppImages skip everything a package manager does for you: signature checks, updates and dependency tracking. Run through this list for every new one:
- Download it from the project’s release page and compare the SHA-256 against the published digest (Step 1).
- Check the runtime with the
libfuse.so.2grep, so you know whether FUSE 2 is needed before you install anything. - If the grep finds
libfuse.so.2, installfuseandfuse-libstogether. One without the other still fails. Static-runtime AppImages need neither. - Run it from a terminal the first time. A silent double-click hides the error.
- Remove
--no-sandboxfrom any desktop entry that a tool generated for an Electron app. - Keep AppImages in one directory, so a single
lsshows every unmanaged binary on the machine. - Plan updates. None of the three AppImages we tested embedded update information (
--appimage-updateinformationprinted nothing), so a hand-integrated AppImage only updates through the app itself or a new download. Gear Lever can track an update source for the ones it manages.
If an app is on Flathub, the Flatpak version is usually the better choice on Fedora: it updates with the system and runs in a real sandbox. Obsidian is one of them, and our Obsidian, Logseq and Trilium comparison covers both packages. For a CLI tool that only ships for another distro, a Toolbx or Distrobox container is the cleaner option. AppImages earn their place for apps that ship nothing else, as long as you keep track of what you’ve downloaded.