Skip to main content

AppImages are the focus of our Linux distribution. We already include several AppImage-related tools that improve their user experience in our distribution, from desktop integration to sandboxing and management.

In today’s tutorial, we will make an AppImage file using appimage-builder.

appimage-builder makes it very easy to create your favorite applications. appimage-builder works by using recipes; these are simple text files in the YML format that contain the information from which appimage-builder will make our AppImage.

One of the main features of appimage-builder is building an AppImage from existing, pre-compiled packages like Debian packages, RPM packages, etc. Only Debian packages are currently supported; however, more package managers, such as Pacman, will be supported.

The project was developed by Alexis Lopez Zubieta, a former Nitrux developer and an AppImage collaborator.

Difficulty: ★★☆☆☆

📜 Table of Contents

  1. Getting Started
  2. Making a Recipe
  3. Generating the AppImage
  4. Testing the AppImage
  5. Troubleshooting

Getting Started

To make our AppImage for this tutorial, we only need to use Distrobox. We won’t be compiling anything at all (of course, if you want to compile the program instead, you can do that). For this tutorial, we will make an AppImage of mpv; for reference, mpv is a free (as in freedom) media player for the command line.

We strongly recommend installing the following version of appimage-builder. To do that, run the following command.

sudo pip3 install git+https://github.com/AppImageCrafters/appimage-builder.git

Now, we can follow the appimage-builder documentation, enter the container, and create our working directory to put the recipe and the contents of the AppDir. For the sake of simplicity, we will create our directory structure as /builder/mpv/.

mkdir -p /builder/mpv/
cd /builder/mpv/
  • 🔰 Information: This directory structure is not mandatory; you can use your conventions.

And we also need a text editor to use in the container.

Making a Recipe

For appimage-builder to create our AppImage, we must provide a recipe. Using your de facto text editor, we can use one of the documentation examples as a template; here’s ours.

  • 🔰 Information: Although the recipe is self-explanatory, please refer to the appimage-builder documentation to know more about what each section does.
version: 1

script: []

AppDir:
  path: ./AppDir

  app_info:
    id: mpv
    name: mpv
    icon: mpv
    version: 0.32.0-1ubuntu1
    exec: usr/bin/mpv

  apt:
    arch: amd64
    sources:
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main restricted universe multiverse'
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal-security main restricted universe multiverse'
      - sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal-updates main restricted universe multiverse'
        key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920D1991BC93C'
    
    include:
      - mpv
      - libdc1394-22
      - libwbclient0

    exclude:
      - adwaita-icon-theme
      - appmenu-gtk-module-common
      - appmenu-gtk2-module
      - appmenu-gtk3-module
      - baloo-kf5
      - bolt
      - breeze
      - breeze-cursor-theme
      - breeze-icon-theme
      - bubblewrap
      - cpp
      - cpp-9
      - dconf-cli
      - dconf-gsettings-backend
      - dconf-service
      - dirmngr
      - dmidecode
      - drkonqi
      - e2fsprogs
      - fdisk
      - fuse
      - gamin
      - gcc-10-base
      - gcc-9-base
      - gdb
      - gdisk
      - gir1.2-atk-1.0
      - gir1.2-freedesktop
      - gir1.2-gdkpixbuf-2.0
      - gir1.2-glib-2.0
      - gir1.2-gtk-3.0
      - gir1.2-ibus-1.0
      - gir1.2-pango-1.0
      - glib-networking
      - glib-networking-common
      - glib-networking-services
      - gnupg
      - gnupg-l10n
      - gnupg-utils
      - gpg
      - gpg-agent
      - gpg-wks-client
      - gpg-wks-server
      - gpgconf
      - gpgsm
      - gpgv
      - gsettings-desktop-schemas
      - gtk-update-icon-cache
      - hicolor-icon-theme
      - humanity-icon-theme
      - hwdata
      - ibus
      - ibus-data
      - ibus-table
      - ibus-table-emoji
      - liba52-0.7.4
      - libaa1
      - libacl1
      - libaom0
      - libapparmor1
      - libappmenu-gtk2-parser0
      - libappmenu-gtk3-parser0
      - libappstream4
      - libappstreamqt2
      - libarchive13
      - libaribb24-0
      - libasn1-8-heimdal
      - libasound2
      - libasound2-data
      - libasound2-plugins
      - libass9
      - libassuan0
      - libasyncns0
      - libatasmart4
      - libatk-bridge2.0-0
      - libatk1.0-0
      - libatk1.0-data
      - libatspi2.0-0
      - libaudit-common
      - libaudit1
      - libavahi-client3
      - libavahi-common-data
      - libavahi-common3
      - libavc1394-0
      - libavcodec58
      - libavformat58
      - libavutil56
      - libbabeltrace1
      - libbasicusageenvironment1
      - libblkid1
      - libblockdev-fs2
      - libblockdev-loop2
      - libblockdev-part-err2
      - libblockdev-part2
      - libblockdev-swap2
      - libblockdev-utils2
      - libblockdev2
      - libbluetooth3
      - libbluray2
      - libbrotli1
      - libbsd0
      - libbz2-1.0
      - libcaca0
      - libcairo-gobject2
      - libcairo2
      - libcanberra-pulse
      - libcanberra0
      - libcap-ng0
      - libcap2
      - libcddb2
      - libchromaprint1
      - libcodec2-0.9
      - libcolorcorrect5
      - libcolord2
      - libcom-err2
      - libcrypt1
      - libcups2
      - libcurl3-gnutls
      - libdatrie1
      - libdb5.3
      - libdbus-1-3
      - libdbusmenu-qt5-2
      - libdca0
      - libdconf1
      - libdevmapper1.02.1
      - libdmtx0b
      - libdouble-conversion3
      - libdvbpsi10
      - libdvdnav4
      - libdvdread7
      - libdw1
      - libebml4v5
      - libeditorconfig0
      - libelf1
      - libepoxy0
      - libevdev2
      - libevent-2.1-7
      - libexpat1
      - libext2fs2
      - libfaad2
      - libfdisk1
      - libffi7
      - libflac8
      - libfontenc1
      - libfribidi0
      - libfuse2
      - libgamin0
      - libgcrypt20
      - libgdbm-compat4
      - libgdbm6
      - libgdk-pixbuf2.0-0
      - libgdk-pixbuf2.0-common
      - libgirepository-1.0-1
      - libgit2-28
      - libglib2.0-0
      - libglib2.0-bin
      - libglib2.0-data
      - libgme0
      - libgmp10
      - libgnutls30
      - libgomp1
      - libgpg-error0
      - libgpgme11
      - libgpgmepp6
      - libgpm2
      - libgps26
      - libgraphite2-3
      - libgroupsock8
      - libgsm1
      - libgssapi-krb5-2
      - libgssapi3-heimdal
      - libgstreamer-plugins-base1.0-0
      - libgstreamer1.0-0
      - libgtk-3-0
      - libgtk-3-common
      - libgudev-1.0-0
      - libharfbuzz0b
      - libhcrypto4-heimdal
      - libheimbase1-heimdal
      - libheimntlm0-heimdal
      - libhogweed5
      - libhttp-parser2.9
      - libhunspell-1.7-0
      - libhx509-5-heimdal
      - libibus-1.0-5
      - libice6
      - libicu66
      - libidn11
      - libidn2-0
      - libinput10
      - libisl22
      - libixml10
      - libjack-jackd2-0
      - libjansson4
      - libjbig0
      - libjpeg-turbo8
      - libjpeg8
      - libjs-underscore
      - libjson-glib-1.0-0
      - libjson-glib-1.0-common
      - libk5crypto3
      - libkmod2
      - libkrb5-26-heimdal
      - libkrb5-3
      - libkrb5support0
      - libksba8
      - libkscreenlocker5
      - liblcms2-2
      - libldap-2.4-2
      - libldap-common
      - liblirc-client0
      - liblivemedia77
      - liblmdb0
      - libltdl7
      - liblua5.2-0
      - liblz4-1
      - liblzma5
      - libmad0
      - libmatroska6v5
      - libmbedcrypto3
      - libmbedtls12
      - libmbedx509-0
      - libminizip1
      - libmm-glib0
      - libmount1
      - libmp3lame0
      - libmpc3
      - libmpcdec6
      - libmpdec2
      - libmpeg2-4
      - libmpfr6
      - libmpg123-0
      - libmtdev1
      - libmtp-common
      - libmtp9
      - libmysofa1
      - libncurses6
      - libncursesw6
      - libndp0
      - libnettle7
      - libnewt0.52
      - libnfs13
      - libnghttp2-14
      - libnl-3-200
      - libnl-genl-3-200
      - libnl-route-3-200
      - libnm0
      - libnotificationmanager1
      - libnpth0
      - libnspr4
      - libnss3
      - libnuma1
      - libogg0
      - libopenconnect5
      - libopenjp2-7
      - libopenmpt-modplug1
      - libopenmpt0
      - libopus0
      - liborc-0.4-0
      - libp11-kit0
      - libpackagekitqt5-1
      - libpam-modules
      - libpam-systemd
      - libpam0g
      - libpango-1.0-0
      - libpangocairo-1.0-0
      - libpangoft2-1.0-0
      - libpangoxft-1.0-0
      - libparted-fs-resize0
      - libparted2
      - libpci3
      - libpcre2-16-0
      - libpcre2-8-0
      - libpcre3
      - libpcsclite1
      - libperl5.30
      - libphonon4qt5-4
      - libphonon4qt5-data
      - libpipewire-0.3-0
      - libpipewire-0.3-modules
      - libpixman-1-0
      - libplacebo7
      - libplasma-geolocation-interface5
      - libpng16-16
      - libpopt0
      - libpostproc55
      - libprocesscore9
      - libprocessui9
      - libprotobuf-lite17
      - libproxy1v5
      - libpsl5
      - libraw1394-11
      - libre2-5
      - libreadline8
      - libresid-builder0c2a
      - librest-0.7-0
      - libroken18-heimdal
      - librsvg2-2
      - librsvg2-common
      - librtmp1
      - libsamplerate0
      - libsasl2-2
      - libsasl2-modules-db
      - libscim8v5
      - libsdl-image1.2
      - libsdl1.2debian
      - libsecret-1-0
      - libsecret-common
      - libselinux1
      - libshine3
      - libshout3
      - libsidplay2
      - libslang2
      - libsm6
      - libsmartcols1
      - libsnapd-glib1
      - libsnappy1v5
      - libsndfile1
      - libsndio7.0
      - libsoup-gnome2.4-1
      - libsoup2.4-1
      - libsoxr0
      - libspa-0.2-modules
      - libspatialaudio0
      - libspeex1
      - libspeexdsp1
      - libsqlite3-0
      - libsrt1
      - libss2
      - libssh-4
      - libssh-gcrypt-4
      - libssh2-1
      - libssl1.1
      - libstemmer0d
      - libstoken1
      - libswresample3
      - libswscale5
      - libsystemd0
      - libtag1v5
      - libtag1v5-vanilla
      - libtaskmanager6
      - libtasn1-6
      - libtdb1
      - libteamdctl0
      - libthai-data
      - libthai0
      - libtheora0
      - libtiff5
      - libtinfo6
      - libtomcrypt1
      - libtommath1
      - libtss2-esys0
      - libtwolame0
      - libudev1
      - libudisks2-0
      - libunistring2
      - libupnp13
      - libusageenvironment3
      - libusb-1.0-0
      - libuuid1
      - libva-drm2
      - libva-wayland2
      - libva-x11-2
      - libva2
      - libvdpau1
      - libvlc5
      - libvlccore9
      - libvorbis0a
      - libvorbisenc2
      - libvorbisfile3
      - libvpx6
      - libvulkan1
      - libwacom-common
      - libwacom2
      - libwavpack1
      - libweather-ion7
      - libwebp6
      - libwebpdemux2
      - libwebpmux3
      - libwebrtc-audio-processing1
      - libwind0-heimdal
      - libwrap0
      - libx264-155
      - libx265-179
      - libxau6
      - libxaw7
      - libxdamage1
      - libxext6
      - libxfixes3
      - libxft2
      - libxi6
      - libxinerama1
      - libxkbcommon-x11-0
      - libxkbcommon0
      - libxkbfile1
      - libxml2
      - libxmu6
      - libxmuu1
      - libxpm4
      - libxslt1.1
      - libxss1
      - libxt6
      - libxtst6
      - libxv1
      - libxvidcore4
      - libxxf86dga1
      - libxxf86vm1
      - libyaml-0-2
      - libzstd1
      - libzvbi-common
      - libzvbi0
      - logsave
      - milou
      - mime-support
      - mobile-broadband-provider-info
      - ocl-icd-libopencl1
      - oxygen-sounds
      - parted
      - pci.ids
      - pciutils
      - perl
      - perl-base
      - perl-modules-5.30
      - pinentry-curses
      - pipewire
      - pipewire-bin
      - python3
      - python3-gi
      - python3-ibus-1.0
      - python3-minimal
      - python3.8
      - python3.8-minimal
      - qtchooser
      - qtvirtualkeyboard-plugin
      - readline-common
      - sed
      - sound-theme-freedesktop
      - sudo
      - tpm-udev
      - tzdata
      - ubuntu-mono
      - udev
      - udisks2
      - usb.ids
      - usbutils
      - vlc-data
      - vlc-plugin-base
      - vlc-plugin-video-output
      - wpasupplicant
      - x11-utils
      - x11-xserver-utils
      - xdg-desktop-portal
      - xdg-desktop-portal-kde
      - xkb-data
      - zlib1g

  runtime:
    env:
     PATH: $APPDIR/usr/bin:$PATH
     APPDIR_LIBRARY_PATH: $APPDIR/usr/lib/x86_64-linux-gnu/:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio:$APPDIR/usr/lib/x86_64-linux-gnu/samba/

  files:
    exclude:
      - usr/lib/x86_64-linux-gnu/gconv
      - usr/share/man
      - usr/share/doc/*/README.*
      - usr/share/doc/*/changelog.*
      - usr/share/doc/*/NEWS.*
      - usr/share/doc/*/TODO.*

AppImage:
  update-information: None
  sign-key: None
  arch: x86_64

Many packages are in the “exclude” section because we prefer to keep the small AppImages we generate. While this has the apparent benefit of a smaller file, it also means that the probability that the file works across multiple Linux distributions (from different families and versions, i.e., fixed release distributions) is reduced; in other words, the AppImage file we generate will be less portable.

So, you have to keep that in mind.

To put it another way, everything you don’t put inside the AppImage is something you’re expecting to find in the target system, and vice-versa, i.e., desktop Linux distributions are likely to include the adwaita-icon-theme package, so that’s something that we can exclude from the final binary.

  • 🔰 Information: In my recipe, I’m using Ubuntu repositories to tell appimage-builder from where to pull the packages. However, this is not mandatory; you can use any APT/dpkg repository (Debian, Devuan, Ubuntu, Trisquel, etc.), including Launchpad PPAs.

Now that we have a recipe, we can build our AppImage.

Generating the AppImage

To generate the AppImage using appimage-builder, we only need to run a single command.

appimage-builder --recipe recipe.yml --skip-tests
  • 🔰 Information: In the command above, our recipe name is recipe.yml; like before, you can name your recipe any way you want, and then we tell appimage-builder not to perform the built-in tests (to save time).

The AppImage will begin to be generated from the recipe by this point.

Testing the AppImage

To test that the AppImage works, run it from Station or double-click it on Index.

Troubleshooting

If your AppImage doesn’t work, it may be because of one or two things. Either your AppImage is missing a library, or the AppRun runtime does not find the library path in the AppDir.

  • In the first scenario, you will want to continue fine-tuning your recipe by adding packages to the section include (and removing them from the exclude section if you added them here).
  • In the second scenario, you will want to check to add the library path to the section runtime.

If your recipe failed to generate an AppImage, it might be because of missing GPG keys, connectivity problems with the repositories used, or missing packages, i.e., the package doesn’t exist.


That’s it; this concludes today’s tutorial.