Building your own AppImages with appimagetool

Understanding AppDir

AppDir is the foundational directory structure used to create an AppImage. It is not a formal packaging format in itself, but rather a convention, a layout that mimics how an application would be installed on a Linux system. When you feed this directory into appimagetool, it wraps everything inside into a single, portable AppImage file.

The AppDir contains your application binary, a .desktop file that tells Linux how to launch it, and an icon that gives it a visual identity. These elements are arranged in a way that mirrors the Linux filesystem hierarchy, so the application behaves like a native app once packaged.

To build your AppDir, start by creating a folder, typically named AppDir, and inside it, place your executable in a subdirectory called usr/bin. This is where your PyInstaller-generated binary goes. Then, you add a .desktop file at the root of the AppDir. This file describes your application's name, executable command, icon, and category. It is what allows Linux desktop environments to recognize and launch your app properly. Alongside the .desktop file, you include an icon file, usually in PNG format, named to match the icon field in the desktop entry. Listing 2 shows the structure of the AppDir.

Listing 2

AppDir Structure

AppDir/
  |-- usr/
  |    |-- bin/
  |         |-- hw
  |-- hw.desktop
  |-- hw.png

A .desktop file is a small but essential component in the Linux desktop ecosystem. It acts as a shortcut that tells the operating system how to launch an application, what icon to display, and how to categorize it within menus. When you double-click an app icon or search for it in your application launcher, it is the .desktop file that defines what happens behind the scenes.

Creating a .desktop file is straightforward. You write a plain text file with a specific format, starting with a header that reads [Desktop Entry]. Below that, define key attributes such as the name of the application, the command used to execute it, the icon file to represent it visually, and the type of application it is. For example, if you have built a Python app called HelloWorld and bundled it into a binary named hello, your .desktop file might include lines like Name=HelloWorld, Exec=hello, and Icon=hello. You also specify Type=Application to indicate that this is a launchable program, and you can add a Categories= line to help Linux categorize it, for instance, under Utility or Development.

Place the .desktop file at the root of your AppDir. It needs to be properly formatted so that appimagetool can recognize it when building your AppImage. If everything is in place, your application will appear in the system menu with its icon and name, ready to launch like any other native Linux app. Listing 3 is an example of a .desktop file for this project.

Listing 3

Example of .desktop File

[Desktop Entry]
Name=HelloWorld
Exec=hw
Icon=hw
Type=Application
Categories=Utility;
Terminal=true

The line Name=HelloWorld defines the name that will appear in application menus and launchers, giving the app its visible identity. Exec=hw tells the system which command to run when the app is launched; this should match the name of the executable produced by PyInstaller. The Icon=hw entry points to the icon file, hw.png in this case, that sits in the AppDir, and while the file extension isn't required in the desktop entry, it must match the actual filename. By declaring Type=Application, you are signaling that this is a launchable program, not a link or a service. The Categories=Utility; line helps Linux desktop environments organize your app appropriately, placing it in the right section of the menu. Finally, Terminal=true ensures that the app opens in a terminal window, which is important for this project because your script prints output directly to the console.

The Final Step: appimagetool

To create a standalone AppImage using appimagetool, you begin with a properly structured AppDir that contains everything your application needs to run. appimagetool wraps it into a single AppImage file. This tool scans the directory, validates its structure, and compresses everything into a portable binary that can run on most Linux distributions without installation or root access.

Open a terminal, navigate to the folder containing your AppDir, and run the command

./appimagetool-x86_64.AppImage AppDir

The result is a new file, usually named after your application, that behaves like a native Linux app. Again, you'll need to make sure it is executable:

chmod +x hw.AppImage

When launched, AppImage unpacks itself into a temporary location and runs just like any installed application. The beauty of this format is that it is self-contained: Users do not need to install Python, PyInstaller, or any libraries. They just download the AppImage, make it executable, and run it. The AppImage format provides a streamlined and distribution-agnostic mechanism for software deployment, marking the final stage of the packaging workflow.

You might be wondering why I used appimagetool in addition to PyInstaller. The file created by PyInstaller and the one produced by appimagetool serve different purposes, even though they both aim to make your Python application portable. When you use PyInstaller with the -onefile option, it generates a single executable binary. This file contains your Python script, the Python interpreter, and all the necessary libraries bundled together. It is self-contained in the sense that it doesn't rely on the user having Python installed, and it can run directly from the terminal. However, it's still just a raw executable: It does not integrate with the Linux desktop environment, and it lacks metadata like icons or menu entries. Appimagetool takes your PyInstaller-generated binary and wraps it inside an AppImage, along with a .desktop file and an icon. The result is a polished, portable application that behaves like a native Linux app. You can launch it from the file manager, and it appears in the Application menu. The AppImage format also ensures compatibility across many Linux distributions, thanks to its standardized structure.

Conclusion

What began as a playful Python script has now evolved into a fully portable Linux application, neatly packaged and ready to launch from any desktop. Along the way, I described how PyInstaller can turn code into a standalone executable and how appimagetool elevates that binary into a polished AppImage, complete with icon, metadata, and cross-distro compatibility.

With just a few tools and a bit of structure, you can take your ideas, whether they're simple utilities or full-fledged applications, and make them accessible to users across the Linux ecosystem. No installation hurdles, no dependency nightmares: just one file, one click, and your app is alive.

Infos

  1. AppImage: https://appimage.org/
  2. VS Code Linux Setup Guide: https://code.visualstudio.com/docs/setup/linux
  3. appimagetool GitHub Page: https://github.com/AppImage/appimagetool

The Author

Andrea Ciarrocchi is a technology enthusiast. Visit Andrea's homepage at https://andreaciarrocchi.altervista.org.

Buy this article as PDF

Download Article PDF now with Express Checkout
Price $2.95
(incl. VAT)

Buy Linux Magazine

Related content

  • Universal Package Formats

    Modern-day package systems solve some problems posed by classic formats like DEB and RPM. We look at Flatpak, AppImage, and Snap and describe how they differ.

  • Stacer

    Stacer is a handy graphical tool for cleaning up your Linux system.

  • bauh

    The bauh package manager can cope with Flatpaks, Snaps, AppImages, AUR, and native web apps.

  • Parcel Service

    The traditional package management systems on Linux are now somewhat outdated, but AppImage, Flatpak, and Snap see some interesting new management systems enter the fray.

  • KTools: Klik

    Klik brings convenient two-click installation to the KDE desktop.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News