How to create an AppImage package step by step in GNU/Linux

Last update: 04/12/2025
Author Isaac
  • AppImage allows you to distribute GNU/Linux applications in a single self-contained, portable file without traditional installation.
  • The foundation of any AppImage is a well-structured AppDir with AppRun, .desktop file, icon, and binaries organized under usr/.
  • Tools like linuxdeploy, AppImageKit, and Pkg2appimage simplify dependency detection and final package generation.
  • The format makes it easier to run recent software on multiple distributions, although with some limitations in integration and automatic updates.

What is an AppImage file?

If you navigate the world of GNU/Linux on a daily basis, sooner or later you will come across the famous files .AppImage files, and you'll want to understand what they are, how to use them, and how to create your own step by step.It's not just "another format": behind AppImage there is a very clear philosophy of portability, fewer broken dependencies and fewer headaches with library versions.

Furthermore, when you start compiling your own programs or packaging applications for others, you quickly discover that maintaining .deb, .rpm and other formats for each distro is a real headacheThat's where AppImage, along with tools like linuxdeploy, AppImageKit and Pkg2appimageIt becomes a very powerful alternative for distributing desktop software on almost any modern distribution.

What exactly is an AppImage package and why is it worthwhile?

An AppImage file is, essentially, a self-contained executable for GNU/Linux that includes the application and all its dependencies The necessary files (dynamic libraries, resources, icons, etc.) are compressed into a single image. Instead of installing like a traditional package that distributes files throughout the system, it behaves similarly to:

  • A “portable” .exe in Windows, which you can carry on a USB drive and run wherever you want.
  • A .dmg file on macOS, which contains the application ready to use without a classic installation.

When you run an AppImage, the system mounts internally a compressed ISO image in read-only modeIt prepares the environment and launches the program inside. Once you close the application, the temporary mount disappears. There is no actual "installation" like with DEB or RPM packages. If you delete the .AppImage file, you'll delete the program. without leaving any traces (except for some configuration or integration files if they have been generated).

This format falls under what is known as “Universal applications for GNU/Linux”, along with other systems such as Flatpak and Snap (and, to a lesser extent, proposals like OrbitalApps). The idea is that the developer Package it once and the user can run it on any modern GNU/Linux distribution.avoiding the hell of maintaining specific versions for Debian, Ubuntu, Fedora, openSUSE, etc.

Among the most interesting features of AppImage are several that differentiate it from traditional packages: portable, does not require permissions root to run and does not touch either system libraries or global preferencesIn other words, you can download an AppImage, give it execution permissions, and launch it in a Live environment. USB, in a stable system with old repositories or in a fairly recent rolling release without having to compile anything or resolve dependencies.

Advantages and disadvantages of the AppImage format compared to classic packages

Before delving into the creation process, it's important to be very clear about what this format offers and what its drawbacks are, especially if you're deciding whether to distribute your application as an AppImage, as a native package, or as both..

On the positive side, an AppImage is a A self-contained binary with the .AppImage extension that runs on virtually any distro without needing to install anything additional (beyond FUSE in most cases). This means that:

  • You are not dependent on system librariesThe libraries your program needs are contained within the file itself.
  • You don't need superuser permissions to use the application, since files are not copied to system paths such as /usr or /etc.
  • It is extremely portableYou can put multiple AppImages on a USB drive and use them on different computers and distributions without problems.
  • They eliminate many dependency conflicts, typical of “I want to use a new version of program X on an old stable distro”.
  • Allow use recent applications on LTS or very conservative distributions (Debian stable, Ubuntu LTS, etc.) without breaking the system.
  • They are ideal for testing software without compromising securityespecially if you combine them with sandboxing (for example, Firejail).
  Learn how to add music to iPhone without iTunes

However, it's not all advantages. AppImage also has its weaknesses compared to the traditional repositories of each distribution. For example, applications include all their librariesthe final size is usually greater than that of a native package which reuses shared libraries already present in the system. Furthermore:

  • Desktop integration is not always perfectThere are tools like appimaged or AppImageLauncher to improve this, but in many cases some manual work is required (menus, file associations, etc.).
  • The AppImage applications usually take a little longer to start.because the compressed image must first be mounted, although once opened they work normally.
  • Automatic updates are not always well implementedThere are tools like AppImageUpdate or support for zsync, but much software still requires downloading the new AppImage and replacing the old one manually.
  • El The catalog of applications in AppImage format is not very extensive. like that of the official repositories of the major distributions, although it increasingly includes important projects (Krita, GIMP, Kdenlive, LibreOffice, etc.).
  • In general, it is considered that Packages maintained in official repositories usually undergo an extra security review Regarding binaries downloaded directly from a website, we must be careful about the origin of the AppImages we use.

Even so, for many scenarios AppImage is a very practical solution: for example, Running applications that are not in your distro's repositories, skipping absurd dependencies, or using current software on old machinesAnd from the developer's point of view, packaging a single AppImage for all distros saves a lot of work.

How an AppImage is structured internally: the AppDir directory

Most tools that generate AppImages work from a basic concept: AppDir, a directory with a structure recognized by the AppImage ecosystemEverything that will end up inside the .AppImage file is first organized in that directory tree.

In its minimal form, an AppDir needs at least three key files in your root:

  • Apprun: The script or executable that launches when you do ./MiPrograma.AppImageIt is responsible for preparing the environment (PATH, LD_LIBRARY_PATH, etc.) and for running the actual application.
  • A .desktop file: contains the application metadata (name, comment, categories, icon, execution command…) following the Desktop Entry specification of freedesktop.org.
  • An icon (usually .png or .svg): used both to display the AppImage file icon in file explorers and for system-integrated application launchers.

Beyond that minimum base, the AppDir typically adheres to a structure similar to that of a conventional GNU/Linux system, respecting the FHS (Filesystem Hierarchy Standard). That is to say, Create subdirectories such as ./usr/bin, ./usr/lib, or ./usr/shareYou will place the following inside them:

  • En usr/bin/, the main binary of your application (for example, hello-world, Rectball, nvim, etc.).
  • En usr/lib/, the shared libraries (.so) that your program needs and that you shouldn't assume the user has installed on their system.
  • En usr/share/applications/, the file .desktop which describes the application.
  • En usr/share/icons/hicolor/ (and similar routes), the application icons in different sizes.

It is essential that the executable be independent of the location in the file systemIf your program assumes absolute paths like this: /usr/bin/miapp o /usr/share/miappYou'll have problems running the AppImage because at runtime it's mounted in a different temporary location. The correct approach is working with relative routes or build them dynamically from the actual path of the binary or the AppRun script.

A more complete AppDir might look like this in a directory list:

$ ls -l
AppRun
miaplicacion.desktop
miaplicacion.svg
usr/

$ ls -R usr
usr/bin/miaplicacion
usr/lib/…
usr/share/applications/miaplicacion.desktop
usr/share/icons/hicolor/…

Once you have this structure, tools like linuxdeploy or appimagetool (from AppImageKit) They will be responsible for converting your AppDir into the final .AppImage file.

.desktop file and basic desktop integration

The .desktop file is a key component, both for AppImage and for integrating any desktop application into GNU/Linux. It is a simple text file with the appropriate formatting. Desktop Entry which can be edited with a plain text editor or with graphical menu editing utilities.

  The way to Delete Picture Albums on iPhone & iPad

A simple example of content could be:

[Desktop Entry]
Type=Application
Name=Rectball
Comment=Match gems and collect points in this puzzle game
Categories=Game;
Exec=Rectball
Icon=rectball

In this example, the key Exec indicates the command to be executed (without absolute path) and, if in your AppRun configures the PATH to include ${HERE}/usr/binThe system will find the binary without any problems. It is important to emphasize that:

  • The Categories entry is required for many tools related to AppImage (for example, some variants of linuxdeploy fail if it is not defined).
  • The key Icon It is usually mapped to a file type nombre.png o nombre.svg which should be accessible in the expected icon directories (for example, in the AppDir under usr/share/icons or alongside the .desktop depending on the workflow).

In some real AppImages, you'll see that the Icon key is omitted or handled slightly differently. Even so, if you want to avoid surprises (for example, icons not displaying correctly when using .png instead of .svg), it's worth it. Define the icon explicitly and check that it looks good on several distributions..

The AppRun script: the heart of execution in AppImage

The file Apprun This is the entry point for the AppImage. When the user runs the .AppImage file, what is actually launched is AppRun within the mounted AppDir. This script can be a simple shell script that:

  • Resolve the actual path from which it is running (taking into account symbolic links and temporal assemblies).
  • Prepare environment variables such as PATH, LD_LIBRARY_PATH and others that your program needs to find libraries or resources.
  • Launch the actual executable (either by reading the Exec key from the .desktop or by directly invoking usr/bin/miapp).

A very common pattern, which you'll find in AppImageKit, looks something like this:

#!/bin/sh
SELF=$(readlink -f "$0")
HERE=${SELF%/*}

export PATH="${HERE}/usr/bin:$PATH"
export LD_LIBRARY_PATH="${HERE}/usr/lib:$LD_LIBRARY_PATH"

EXEC=$(grep -e '^Exec=' "${HERE}"/*.desktop | head -n 1 | cut -d '=' -f 2 | cut -d ' ' -f 1)
exec "${EXEC}" "$@"

This approach dynamically seeks the value of Exec in the .desktop file and runs it with the arguments passed by the user, which is very flexible. Other projects opt for even simpler versions. For example, Neovim's AppImage uses a minimalist AppRun like this:

#!/bin/bash
unset ARGV0
exec "$(dirname "$(readlink -f "${0}")")/usr/bin/nvim" ${@+"$@"}

Whichever variant you use, the idea is that AppRun It does not depend on absolute system paths and is able to function correctly in any location. where the AppImage is mounted.

Tools for creating AppImages: linuxdeploy, AppImageKit and Pkg2appimage

When creating your own AppImage package, you have several main tools at your disposal, each with its own focus. The most recommended for modern workflows is linuxdeployalthough AppImageKit and Pkg2appimage still have their place.

linuxdeploy takes care of Analyze your executable, detect its dependencies, and automatically build the AppDir structure. appropriate (copying libraries to usr/lib(organizing files, etc.). It is especially useful when you already have a working binary and want to package it without racking your brains too much about which libraries to include.

For its part, AppImageKit It provides, among other things, the tool appimagetoolwhich takes an already mounted AppDir as input and generates the .AppImage file from it. You can download appimagetool directly from its GitHub repository; interestingly, It is distributed as an AppImageA typical use would be:

./appimagetool-x86_64.AppImage MiApp.AppDir MiApp-x86_64.AppImage

In environments like Docker or CI, it's important to keep in mind that AppImageKit requires FUSE to be able to mount the image internally. If FUSE is not available in the container or on the machine, the process may fail, so it's advisable to check this before automating builds.

The third important piece is pkg2appimage, designed for cases where you already have an existing package (for example, tar.gz, .deb or even PPA repositoriesand you want to convert it into an AppImage. This tool is controlled through a .yml description file, where you define where the software is downloaded from, how the packages are installed, and what files end up in the resulting AppDir.

  Fix: DNS probe completed No error on net

The typical way to work with Pkg2appimage is something like this:

  1. Clone a repository with the appropriate .yml file. for the application you want to convert (for example, a customized Packet Tracer YAML).
  2. Download Pkg2appimage from your GitHub repository and give it execute permissions with chmod +x.
  3. Adjust the .yml file to update download URLs that have changed or new dependencies.
  4. Launch ./pkg2appimage NombreArchivo.yml and wait for it to generate the final AppDir and AppImage.

This approach is very practical for Recycle existing packages that don't work well on your distro or that require complex library downgrades. Pkg2appimage automates much of that work and leaves you with a ready-to-use .AppImage for different systems.

Create an AppImage from your own executable step by step

Imagine you have a simple program, for example a project called hello-world, with its binary in bin/ and their libraries in lib/You could package it as a .zip, learn how to generate a .deb or .rpm file, but you can also Take the opportunity to package it as an AppImageThe flow with linuxdeploy is usually quite straightforward.

The basic steps would be these: key steps

1. Prepare the environment and obtain linuxdeploy

The first is Download the linuxdeploy tool and make it executable.It is usually distributed as ready-to-use binaries (for example, as an AppImage). terminalsomething like:

wget https://github.com/linuxdeploy/linuxdeploy/releases/.../linuxdeploy-x86_64.AppImage
chmod +x linuxdeploy-x86_64.AppImage

Additionally, if you plan to offer efficient updates via zsyncYou can install the zsync utility, for example on Debian/Ubuntu-based systems with:

sudo apt-get install zsync

2. Build the AppDir structure

Next, you create a directory that will function as an AppDir (for example, MiApp.AppDirand inside you organize the minimum structure This is necessary. You can do it manually or let linuxdeploy generate part of it. The idea is:

  • Place your main executable in MiApp.AppDir/usr/bin/. For example, MiApp.AppDir/usr/bin/hello-world.
  • Allow linuxdeploy to automatically copy the required libraries a MiApp.AppDir/usr/lib/ when you run it with the appropriate options.
  • Create the .desktop file within MiApp.AppDir/usr/share/applications/ with the correct fields: Name, Comment, Exec, Icon, Categories, etc.
  • Prepare the icons and place them on typical routes MiApp.AppDir/usr/share/icons/hicolor/, making sure that the value of the Icon key in the .desktop matches the file name (without the extension).

It is important to remember that in the .desktop field Exec should point to the executable name exactly as linuxdeploy will look for it in usr/bin. If you use Exec=hello-worldlinuxdeploy will assume that in usr/bin That executable exists.

3. Run linuxdeploy to package the application

With the AppDir structure in place, indicate the route to AppDir and, optionally, specific modules or plugins (for example, to integrate icons, .desktop files, etc.). linuxdeploy handles:

  • Scan the main binary and detect which dynamic libraries it needs.
  • Copy those libraries into usr/lib within the AppDir, provided they are not libraries that are assumed to already exist in the user's system.
  • Get the AppDir ready so that it can later become an AppImage (sometimes, linuxdeploy itself can generate the AppImage in combination with plugins).

After this process, you will have a file with the extension in the current directory. .AppImagesuch as hello-world-x86_64.AppImagewhich you can copy wherever you want and run on other compatible GNU/Linux systems.

4. Make it executable and test it on various distributions

When linuxdeploy (or appimagetool) generates the AppImage, it is very possible that at the beginning do not have the execution bit setIn that case, simply do the following:

chmod +x hello-world-x86_64.AppImage
./hello-world-x86_64.AppImage

It is highly recommended that Test your AppImage on different distributions and versionsThis includes a relatively old version within the range you want to support (for example, the minimum version of Ubuntu or Debian you intend to support). This ensures that you haven't left out any important dependencies and that the executable behaves the same everywhere.