Greetings to all!
My name is Joao Machado, and I am looking for feedback, constructive feedback, and or volunteers.
I maintain a little niche distro called DeLinuxCo, a Manjaro Cinnamon Spin mainly focused as a workstation. One of the goals of the project is to focus on AppImages integrated into the OS. I currently have 23 AppImages available in the DeLinuxCo repo. After reading this post, please give the disto a test drive in a VM, see how well the AppImages work, install and uninstall some them to see the whole thing works.
The goal is to make the AppImages completely transparent to the user. To achieve this, I used the Arch Linux PKGBUILD system to create packages that installs the AppImage, Icon and a desktop launcher. The Arch Packages is singed with the DeLinuxCo GPG keys. The package name is also appended with -appimage, example, GIMP would be named gimp-appimage, in order to differentiate the packages from say, gimp or gimp-bin etc.
When a package is updated, it is just a matter of changing the package version and the sha256sum and you can build the new package, push it to the repo and the user will update the package with the rest of the system.
This offers, as just discussed, not only seamles user experience, but also the ability to include AppImages directly in the ISO just like any other package!
One other cool feature is that you can customize the launcher for better user usability. Allow me to give a couple of examples.
First, in Cinnamon Desktop, when you run Kdenlive, either as a regular package or as an AppImage fonts just look a little off, but in the launcher, you can use the env to adjust the QT_SCALE_FACTOR to increase the font size. The executable command normally looks like this: Exec=/opt/appimages/Kdenlive.AppImage but by changing it to Exec=env QT_SCALE_FACTOR=1.2 /opt/appimages/Kdenlive.AppImage the font size is increased and the application looks much better, actually it looks great!
Second, you can add the ability of running the AppImage in firejail mode, simply by adding an additional exec command in the launcher. In DeLinuxCo, Firefox and Zen-Browser both are installed as AppImages, but in the launcher there is an extra exec command to run them jailed using firejail just by right clicking on the launcher and selecting Run Firefox Jailed or Run Zen-Browser Jailed etc.
firefox-jailed
zen-firejail
The beauty of this whole thing is that the AppImage is pulled directly from the developer, packaged and pushed directly to the user without any changes, any compiling any modifications to the AppImage at all. What the developer built, the user gets!
THE VISION
I have procured the domain appimage.xyz and I am prepared to donate it to appimage.org in order to use it for the purpose that I am about to expand on.
The application developer would have to do a little extra but not much, here are the tasks that would fall on the developer:
- add SVG icon to AppImage root directory:assets/icons/application.svg
- add Desktop Launcher to AppImage root directory:assets/launcher/application.desktop
- publish a git repo of the build files for each package type, .zst, .deb, .rpm, xbps.
Appimage.xyz would create package repos for each type of package, zst.appimage.xyz for Arch, deb.appiamge.xyz for Debian/Devuan, rpm.appimage.xyz for RPM distros and xbps.appimage.xyz for Void Linux etc. A separate server/container for each package type would pull the developers git repos, build the package and push it to the appimage.xyz repos.
From this point on, any distro could add the package repo to their distro and serve AppImages just like any package.
There is also the issue of the GPG keys and renewing them on a regular basis. As it turns out, there is really no need to replace package keys regularly because there is no real issue with dependencies and pushing packages out based on dependencies because they are builtin to the AppImage. This actually allows multiple versions of the package in the repos in case someone wants to revert to a previous version of a package. I currently keep three version of each package in the DeLinuxCo repo.
ARM packages could easily be included in the package repos, and, at least in Arch PKGBUILD files, you can include both x86_64 and arm in the PKGBUILD.
THE ENVIRONMENT
So the AppImages are installed to /opt/appimages/ directory, /opt/ as it turns out is where all non system OS applications are supposed to be installed, a very good read: https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/opt.html
The SVG icon is installed to /usr/share/icons/hicolor/scalable/apps The system always picks up the icons stored here, non-scalable icons is a hit an miss not sure why.
The Launcher is installed in the default location of /usr/share/applications/
AppImage.xyz would provide some templates for each package type for the developers to reference, here is an example for an Arch system using Darktable and a template. ( I plan on sharing these on my github).
Maintainer: John Machado <john at delinuxco dot com>
pkgname=darktable-appimage
pkgver=5.6.0
pkgrel=3
pkgdesc="Darktable is an open source photography workflow application and raw developer."
arch=('x86_64')
url="https://www.darktable.org/"
license=('GPL-3.0')
provides=('darktable')
conflicts=('darktable-desktop' 'darktable-bin')
depends=(
'fuse2'
'fuse3'
'libxcrypt-compat'
)
optdepends=()
options=(!strip)
# Using a single source definition is cleaner for single-arch packages
source=("https://github.com/darktable-org/darktable/releases/download/release-${pkgver}/darktable-${pkgver}-x86_64.AppImage")
sha256sums=('cbad7bf4be2607e1725db156d73c799d267a79fc29a572c3136a5deb9c9be948')
_appimage_name="darktable-${pkgver}-x86_64.AppImage"
_install_path="/opt/appimages/darktable.AppImage"
prepare() {
cd "${srcdir}"
chmod +x "${_appimage_name}"
# Extract to modify the desktop entry and icons
./"${_appimage_name}" --appimage-extract
# Create directories for the extracted assets
mkdir -p "${srcdir}/squashfs-root/assets/icons/"
mkdir -p "${srcdir}/squashfs-root/assets/launchers/"
# Move and rename desktop entry/icon to be clean
cp "${srcdir}/squashfs-root/darktable.svg" "${srcdir}/squashfs-root/assets/icons/darktable.svg"
cp "${srcdir}/squashfs-root/org.darktable.darktable.desktop" "${srcdir}/squashfs-root/assets/launchers/darktable.desktop"
# Fix the Desktop Entry to point to our specific install path
sed -i "s|Exec=.*|Exec=${_install_path} %U|" "${srcdir}/squashfs-root/assets/launchers/darktable.desktop"
sed -i "s|TryExec=.*|TryExec=${_install_path}|" "${srcdir}/squashfs-root/assets/launchers/darktable.desktop"
}
package() {
# 1. Install the actual AppImage
install -d "${pkgdir}/opt/appimages"
install -Dm755 "${srcdir}/${_appimage_name}" "${pkgdir}${_install_path}"
# 2. Install the modified Desktop Entry and Icon
install -d "${pkgdir}/usr/share/applications"
install -d "${pkgdir}/usr/share/icons/hicolor/scalable/apps"
install -Dm644 "${srcdir}/squashfs-root/assets/icons/darktable.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/darktable.svg"
install -Dm644 "${srcdir}/squashfs-root/assets/launchers/darktable.desktop" "${pkgdir}/usr/share/applications/darktable.desktop"
# 3. Create the symlink in /usr/bin
install -d "${pkgdir}/usr/bin"
ln -s "${_install_path}" "${pkgdir}/usr/bin/darktable"
}
Here is a typical PKGBUILD template for Arch Linux to package an AppImage.
# Maintainer: <Your Name> <Your Email>
###############################################################################
# CONFIGURATION SECTION
# Replace these values with your specific application details.
###############################################################################
pkgname="your-app-name-appimage"
pkgver="1.0.0"
pkgrel=1
pkgdesc="A brief description of the application."
arch=('x86_64')
url="https://example.com/project-url"
license=('GPL-3.0-or-later') # Replace with actual license
provides=('your-app-name')
conflicts=('your-app-name-bin' 'your-app-name-desktop')
# The filename as it appears in the download URL (e.g., app-1.0.0-x86_64.AppImage)
_appimage_filename="your-app-${pkgver}-x86_64.AppImage"
# The source URL
_source_url="https://example.com/downloads/your-app-${pkgver}-x86_64.AppImage"
# Where the file will live in your system (Standard is /opt/appimages/)
_install_dir="/opt/appimages"
_install_path="${_install_dir}/${pkgname}.AppImage"
# Inside the AppImage, what is the name of the .desktop file?
# Usually it matches the app name, e.g., 'org.kde.kcalc.desktop'
_desktop_file="your-app.desktop"
# Inside the AppImage, what is the name of the icon file?
_icon_file="your-app.svg"
###############################################################################
depends=(
'fuse2'
'fuse3'
'libxcrypt-compat' # Often needed for older AppImages on Arch
)
optdepends=()
options=(!strip)
source=("${_source_url}")
sha256sums=('${sha256sum_goes_here'})
prepare() {
cd "${srcdir}"
# 1. Make the AppImage executable and extract it
chmod +x "${_appimage_filename}"
./"${_appimage_filename}" --appimage-extract
# 2. Setup directory structure inside squashfs-root for the build process
mkdir -p "${srcdir}/squashfs-root/assets/icons/"
mkdir -p "${srcdir}/squashfs-root/assets/launchers/"
# 3. Move the icon and desktop file to a known location for easy installation
# Note: We check if they exist to prevent build failure if names differ
if [ -f "squashfs-root/${_icon_file}" ]; then
cp "squashfs-root/${_icon_file}" "squashfs-root/assets/icons/${_icon_file}"
fi
if [ -f "squashfs-root/${_desktop_file}" ]; then
cp "squashfs/root/${_desktop_file}" "squashfs-root/assets/launchers/${_desktop_file}"
# 4. CRITICAL: Rewrite the .desktop file to point to our /opt path
# This fixes the 'Exec' line so it doesn't try to run from a temporary folder
sed -i "s|Exec=.*|Exec=${_install_path} %U|" "squashfs-root/assets/launchers/${_desktop_file}"
sed -i "s|TryExec=.*|TryExec=${_install_path}|" "squashfs-root/assets/launchers/${_desktop_file}"
fi
}
package() {
# 1. Install the AppImage to /opt
install -d "${pkgdir}${_install_dir}"
install -Dm755 "${srcdir}/${_appimage_filename}" "${pkgdir}${_install_path}"
# 2. Install the Desktop Entry and Icon to standard system paths
install -d "${pkgdir}/usr/share/applications"
install -d "${pkgdir}/usr/share/icons/hicolor/scalable/apps"
if [ -f "${srcdir}/squashfs-root/assets/launchers/${_desktop_file}" ]; then
install -Dm644 "squashfs-root/assets/launchers/${_desktop_file}" "${pkgdir}/usr/share/applications/${_desktop_file}"
fi
if [ -f "${srcdir}/squashfs-root/assets/icons/${_icon_file}" ]; then
install -Dm644 "squashfs-root/assets/icons/${_icon_file}" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/${_icon_file}"
fi
# 3. Create the symlink in /usr/bin so you can launch it from terminal via 'appname'
install -d "${pkgdir}/usr/bin"
ln -s "${_install_path}" "${pkgdir}/usr/bin/${pkgname}"
}
Note, this template file does not include how to add the firejail.
In a nut shell, here is what the script does;
- You declare all of your variables
- Download the source AppImage
- Extract the appimage to get the SVG and launcher file
- Make modifications to the launcher file
- Install untouched AppImage, Icon and Desktop Launcher
- Create Symbolic Link to /usr/bin/your_app just in case, plus you can launch it from the terminal without having to type /opt/appimages/my_app.AppImage.
Your thoughts, questions are all welcomed.
Peace,
Joao
All reactions
Replies: 4 comments 1 reply
Hi @delinuxco. Thanks for reaching out. I appreciate that you'd like to treat AppImages as first-class citizens on your desktop.
However, I think you should look at it from another perspective. The AppImage file format was explicitly made so that users don't need a package manager, don't need to be root, can store AppImages wherever they want (including network shares and USB devices). AppImages were made so that the user can download one file and run it, without needing to install anything.
The key to proper AppImage integration is not in wrapping AppImages into distribution packages; this would combine the worst aspects of both formats.
The key to proper AppImage integration is in making the file manager AppImage aware:
- When the user double clicks an executable ELF file (any such file - not just AppImages), the file manager should ask the user whether to set the executable bit and run the application
- The file manager should use a thumbnailer to show correct icons for AppImage files
- The file manager could install AppImageUpdate or a similar updater and invoke it when the user chooses "Update" from the context menu
I invite you to think about these ideas. Have a look at how macOS works - no installation needed, just drag-and-drop in the file manager, no package manager involved.
If you want to see these ideas in practice, you can have a look at Gershwin Desktop and how it handles AppImages.
All reactions
Hi @probonopd , thank you pointing out what I should have included, I was not attempting to invalidate those very options, but to offer an option. Even if an AppImage is installed with the package manager, one can still download AppImages and test/run them without installing them, nothing changes there.
Regarding the "root" issue, this is a misconception, you do not need to be "root" to run an application from /opt/, anyone can navigate to /opt/appimages/ and double click on the AppImage and it will open, there is no "root" required. Root privileges are used only during package installs because that is how package managers work.
There is also the fact that, multiple users can share the AppImages in /opt/, they do not have to be duplicated.
I will check out Gershwin Desktop, never heard of it before.
Joao
All reactions
But you need to be root to use apt or rpm or whatever. Which is not desirable for AppImages.
I just don't see why one would add back to AppImage all the downsides of package managers I wanted to avoid when I invented the format.
- Need root
- Cannot decide where the files get stored
- Cannot put on USB
- Need a package manager
- Cannot keep all versions in parallel
- ...
All reactions
Reverting back to, what you call, downsides, by all means, that is not my intent. What I am trying to convey, and probably not very well, is that you can also use the existing package/repo system in conjunction with downloading directly, and running from anywhere. These are fantastic ways to run an application! In fact, this is what drew me to using AppImages, the fact that I could just download the package, and run it.
But, when I started to work with making my own distro, there is no mechanism for including AppImages in an ISO, all packages used in an ISO must come from a repo and a repo that has a GPG key. There is currently no real way to include AppImages in an ISO properly.
The more non-system applications that can be moved to AppImages, the less potential for system corruption and or breakage. It is a win/win. If the user prefers to download a particular AppImage from a developer and run it separately, they still can, they can even just copy the AppImage from /opt/appimages/ and take it with them. From my vantage point, it is enhancing the availability and access to AppImages not reverting backwards.
Then there is the huge potential for businesses to use the repo system to push packages to users remotely, I have worked at a fortune 500 company, they want full control of the packages installed and easily be able to update them.
Pushing the AppImage through a repo, just another option, like deciding where to put it, like putting it on USB drive, or running AppImages in parallel, all of which you can still do. But now, unlike Flatpaks, which cannot be easily included in an ISO, AppImages can.
It is/was not my intent to offend in anyway. Like all things software related, we can always agree to disagree.
-Joao
All reactions
Then there is the huge potential for businesses to use the repo system to push packages to users remotely, I have worked at a fortune 500 company, they want full control of the packages installed and easily be able to update them.
If that is a use case of yours, you are of course to do that. I am not offended by that at all, I am just wondering why anyone would want to do that.
With AppImage, I want the end user to be in full control. Not some system administrator. That is the whole point of the format, imho.
But again, nothing is stopping you. I am just wondering why ever since I made a format that doesn't need installation, people are obsessed with "installing" AppImages. ;-)