Keepassxc: Provide KeePassX as AppImage

Created on 10 Oct 2016  ·  34Comments  ·  Source: keepassxreboot/keepassxc

I think it would be pretty cool, if we would also provide an AppImage (http://appimage.org/) binary for download, not just distribution-specific packages.

Most helpful comment

Yes and no. It's a self-contained image consisting of an executable header and an appended disk image. When an AppImage file is executed, the disk image is mounted via FUSE and the contained application is started. The advantage is that you don't need anything on the host system: no snapd, no additional libs, no launcher, no nothing. It's like downloading and running a portable .EXE for Windows, but with the option to sandbox the executable. There are quite some applications which provide AppImage nowadays (Krita, KDevelop, …) because it makes it easy for users to just download the latest build which may not be available through their distribution's repositories yet (or will never be available at all because it's an older LTS release).
Snap packages are probably the more advanced option, but require a pre-installed daemon. AppImages are a lot simpler and can also be integrated with a CI system to provide downloadable nightly builds. Since we're already using Travis CI, we might as well let it build AppImages instead of throwing the binaries away.

All 34 comments

Is AppImage something similar to Ubuntu's Snappy?

Yes and no. It's a self-contained image consisting of an executable header and an appended disk image. When an AppImage file is executed, the disk image is mounted via FUSE and the contained application is started. The advantage is that you don't need anything on the host system: no snapd, no additional libs, no launcher, no nothing. It's like downloading and running a portable .EXE for Windows, but with the option to sandbox the executable. There are quite some applications which provide AppImage nowadays (Krita, KDevelop, …) because it makes it easy for users to just download the latest build which may not be available through their distribution's repositories yet (or will never be available at all because it's an older LTS release).
Snap packages are probably the more advanced option, but require a pre-installed daemon. AppImages are a lot simpler and can also be integrated with a CI system to provide downloadable nightly builds. Since we're already using Travis CI, we might as well let it build AppImages instead of throwing the binaries away.

👍 Nice explanation

No one on this?

Maybe it should be good using https://github.com/probonopd/linuxdeployqt

I can support if the project would like to do an upstream-provided AppImage. Shouldn't be hard to do since the project is already using Travis CI for continuous builds; it should be possible to run linuxdeployqt in the process and be done with it. If not, it's likely a bug in linuxdeployqt.

These projects are already using Travis CI and linuxdeployqt to provide AppImages of their builds:

@probonopd Yes, It would be nice to compile upstream AppImage from TravisCI https://github.com/keepassxreboot/keepassx/issues/48

I've seen linuxdeployqt and I like it, but I have some problem using it on my GNU/Linux.

Note: We don't use QtCreator/qmake to compile the project, qmake points to the system's Qt.

The step I follow are the following:

Obviously an ldd on the executable show the system qt linked.

IDK if you want that I open an Issue on linuxdeployqt.
Every help is welcomed 😄

You could use https://launchpad.net/~beineri/+archive/ubuntu/opt-qt57-trusty for one of your builds in the .travis.yml build matrix, and then run linuxdeployqt -appimage on that build. See these .travis.yml files for example:

They all use the ppa from beineri, sudo add-apt-repository --yes ppa:beineri/opt-qt57-trusty.

qmake points to the system's Qt.

@TheZ3ro, can you please retry with sudo add-apt-repository --yes ppa:beineri/opt-qt57-trusty and /opt/qt57/bin/qt57-env.sh. This is a known issue in linuxdeployqt that it cannot bundle system Qt yet.

@probonopd Before editing the Travis build I want to compile the AppImage manually, but when I try to execute the appImage output this: (the first line in repeated 8 times)

/tmp/keepassxcAppImage/src.AppImage: /tmp/keepassxcAppImage/src.AppImage: no version information available (required by /tmp/keepassxcAppImage/src.AppImage)
/tmp/keepassxcAppImage/src.AppImage: symbol lookup error: /tmp/keepassxcAppImage/src.AppImage: undefined symbol:

I've followed this steps:

  • sudo add-apt-repository --yes ppa:beineri/opt-qt57-xenial
  • sudo apt install qt57base qt57tools qt57x11extras
  • /opt/qt57/bin/qt57-env.sh
  • cp -R /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqxcb.so ./src/plugins/platforms
  • linuxdeployqt src/keepassxc -appimage -bundle-non-qt-libs -verbose=2

The output of LinuxDeployQt:

"/tmp/.mount_7CbAyR/usr/bin:/usr/local/bin:/home/thezero/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-8-oracle/bin:/usr/lib/jvm/java-8-oracle/db/bin:/usr/lib/jvm/java-8-oracle/jre/bin:/home/thezero/.rvm/bin:/home/thezero/.go:/home/thezero/.go/bin"
app-binary: "src/keepassxc"
Log: Deploying libraries found inside: ("src/AppRun", "src/autotype/xcb/libkeepassx-autotype-xcb.so", "src/autotype/test/libkeepassx-autotype-test.so", "src/plugins/platforms/libqxcb.so", "src/autotype/xcb/libkeepassx-autotype-xcb.so", "src/autotype/test/libkeepassx-autotype-test.so", "src/plugins/platforms/libqxcb.so")
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5"
Log:  to "src/lib//libQt5Widgets.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5X11Extras.so.5"
Log:  to "src/lib//libQt5X11Extras.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libXi.so.6"
Log:  to "src/lib//libXi.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libXtst.so.6"
Log:  to "src/lib//libXtst.so.6"
Log: Setting deploymentInfo.qtPath to: "/usr/lib/x86_64-linux-gnu/"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5Core.so.5"
Log:  to "src/lib//libQt5Core.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5Gui.so.5"
Log:  to "src/lib//libQt5Gui.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libXext.so.6"
Log:  to "src/lib//libXext.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libicui18n.so.55"
Log:  to "src/lib//libicui18n.so.55"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libicuuc.so.55"
Log:  to "src/lib//libicuuc.so.55"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libpcre16.so.3"
Log:  to "src/lib//libpcre16.so.3"
Log:  copied: "/lib/x86_64-linux-gnu/libpng12.so.0"
Log:  to "src/lib//libpng12.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0"
Log:  to "src/lib//libharfbuzz.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libffi.so.6"
Log:  to "src/lib//libffi.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libXau.so.6"
Log:  to "src/lib//libXau.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libXdmcp.so.6"
Log:  to "src/lib//libXdmcp.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libicudata.so.55"
Log:  to "src/lib//libicudata.so.55"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libfreetype.so.6"
Log:  to "src/lib//libfreetype.so.6"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libgraphite2.so.3"
Log:  to "src/lib//libgraphite2.so.3"
Log:  copied: "/usr/lib/nvidia-367/libGLX.so.0"
Log:  to "src/lib//libGLX.so.0"
Log:  copied: "/usr/lib/nvidia-367/libGLdispatch.so.0"
Log:  to "src/lib//libGLdispatch.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5"
Log:  to "src/lib//libQt5XcbQpa.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libX11-xcb.so.1"
Log:  to "src/lib//libX11-xcb.so.1"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-render-util.so.0"
Log:  to "src/lib//libxcb-render-util.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-render.so.0"
Log:  to "src/lib//libxcb-render.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-image.so.0"
Log:  to "src/lib//libxcb-image.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-icccm.so.4"
Log:  to "src/lib//libxcb-icccm.so.4"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-sync.so.1"
Log:  to "src/lib//libxcb-sync.so.1"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-xfixes.so.0"
Log:  to "src/lib//libxcb-xfixes.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-shm.so.0"
Log:  to "src/lib//libxcb-shm.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-randr.so.0"
Log:  to "src/lib//libxcb-randr.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-shape.so.0"
Log:  to "src/lib//libxcb-shape.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-keysyms.so.1"
Log:  to "src/lib//libxcb-keysyms.so.1"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-xkb.so.1"
Log:  to "src/lib//libxcb-xkb.so.1"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0"
Log:  to "src/lib//libxkbcommon-x11.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxkbcommon.so.0"
Log:  to "src/lib//libxkbcommon.so.0"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libQt5DBus.so.5"
Log:  to "src/lib//libQt5DBus.so.5"
Log:  copied: "/usr/lib/x86_64-linux-gnu/libxcb-util.so.1"
Log:  to "src/lib//libxcb-util.so.1"
Log:  copied: "/lib/x86_64-linux-gnu/libdbus-1.so.3"
Log:  to "src/lib//libdbus-1.so.3"
Log:  copied: "/lib/x86_64-linux-gnu/libsystemd.so.0"
Log:  to "src/lib//libsystemd.so.0"
Log:  copied: "/lib/x86_64-linux-gnu/liblzma.so.5"
Log:  to "src/lib//liblzma.so.5"
Log:  copied: "/lib/x86_64-linux-gnu/libgcrypt.so.20"
Log:  to "src/lib//libgcrypt.so.20"
Log: Deploying plugins from "/tmp/keepassxcAppImage/src/plugins"
Log: File exists, skip copy: "src/plugins/platforms/libqxcb.so"
Log: Created configuration file: "src/qt.conf"
Log: This file sets the plugin search path to "src/plugins"
Log: Creating AppImage for "src"
['/tmp/.mount_MfMSs0/package', 'src', 'src.AppImage']
Creating /tmp/keepassxcAppImage/src.AppImage ...
xorriso 0.5.6 : RockRidge filesystem manipulator, libburnia project.

ok
Embedding runtime...
ok
Embedding magic number 0x414901 at offset 8...
ok
Making /tmp/keepassxcAppImage/src.AppImage executable...
ok
Size: 63.500000 MB

Any help?

I suspect you are running into https://github.com/probonopd/linuxdeployqt/issues/44 which may or may not be caused by https://github.com/NixOS/patchelf/issues/99. Can you retry on a trusty system with Qt 5.7 please?

Yes, Tomorrow I will try and let you know

v2.1.0 has a working AppImage (KeePassXC-2.1.0-x86_64.AppImage).

So I think this can be closed as fixed.

Sorry maybe this doesn't belong here, but don't want to create new issue.
I'm using release-tool build to create AppImage on Ubuntu 16.04.
Not using docker, but vagrant because building in Docker container still needs some python deps on host system (transifex-client???). And also instead of ppa:beineri/opt-qt58-trusty and ppa:chris-lea/libsodium I'm using ubuntu stock dev libraries.

Basically this all deps I've installed on vagrant box

apt-get install --yes libxi-dev libxtst-dev qtbase5-dev \
libqt5x11extras5-dev qttools5-dev qttools5-dev-tools \
libgcrypt20-dev zlib1g-dev libyubikey-dev libykpers-1-dev \
libsodium-dev libboost-system-dev \
python-pip git wget fuse module-init-tools

My problem is when app starts, some resources (images, translations) are not loaded and instead of images I see text placeholders. Running from terminal confirms, that KeePassXC cannot find all resource:

image

QCoreApplication::applicationDirPath: Please instantiate the QApplication object first
FilePath::DataPath: can't find data dir
Couldn't load passphrase wordlist.
Couldn't load translations.
Couldn't load passphrase wordlist.
Couldn't load passphrase wordlist.
QSystemTrayIcon::setVisible: No Icon set

However when I extract AppImage squashfs-root contains all those resources and it has basically same structure as official AppImage, which loads all resources normally.

Also when I install KeePassXC deb package, then resources are loaded also for AppImage version, so it finds them on host filesystem instead of squashed fs. However deb install everything under /usr/local, but AppImage squashfs-root/usr, which is strange.

Any suggestion, where the problem might be? Many thanks.

Seems like the binaries inside the AppImage are looking for the resources in a fixed location at /usr/local rather than a location relative to themselves. This meeds most likely to be changed in the code.

You can build the AppImage entirely without Docker or similar tools if you don't need wide compatibility. The only reason we have it is so we can build it on 14.04 (which has an older glibc).

If you try the current release-tool from develop, Transifex client shouldn't be needed anymore if you are only using release-tool build.

@probonopd @phoerious thank you for the answer. Actually I prefer Docker, just because I don't like dev packages to be present on my host system.

tl;dr

The problem with Docker is, it cannot build AppImage. I mean it can compile keepassxc just fine, but last step of creating AppImage will fail, because of fuse is not supported in docker?
Maybe that's why official wiki is recommending running release-tool on host system instead of docker container ./release-tool build -v VERSION -d keepassxc/ubuntu:14.04. To overcome this I used vagrant/virtualbox (full virtualization).

But my problem is really just the resources not loaded. Maybe I have to adjust https://github.com/keepassxreboot/keepassxc/blob/develop/CMakeLists.txt#L196 to /usr somehow.

I will try release-tool from dev branch as @phoerious is suggesting.

The problem with Docker is, it cannot build AppImage. I mean it can compile keepassxc just fine, but last step of creating AppImage will fail, because of fuse is not supported in docker?

Have you checked https://github.com/AppImage/AppImageKit/wiki/FUSE#docker?

@probonopd thanks, didn't know that. Will try. This will allow me to use Docker instead of Vagrant.

You should not run the release-tool inside the container. The release-tool is built to spawn its own Docker container when you specify an image with -d. This container will have all needed permissions set (including FUSE).

@phoerious ok. The only reason was I don't like dev packages (transifex-client) to be present on my host. But will try release-tool from dev branch, which you said has not such a deps.

The Transifex client is needed for the merge step, but not for build. Generally, you should always use the latest release-tool version (i.e. the one from develop). It will still take care of checking out the correct Git tag for the version you specify with -v.

~Running release-tool from dev branch still complains about transifex-client~

./release-tool build -v 2.2.0-browser-beta5 -d mauron85/keepassxc

KeePassXC Release Preparation Helper
Copyright (C) 2017 KeePassXC Team <https://keepassxc.org/>

[ INFO ] Performing basic checks...
[ INFO ] Changing to source directory...
[ INFO ] Validating toolset and repository...
[ ERROR ] Transifex tool 'tx' not installed! Please install it using 'pip install transifex-client'
[ INFO ] Checking out original branch...
[ INFO ] Leaving source directory..

EDIT: I was using wrong remote.

2.2.0-browser-beta5 is not a tag we have in our repository. Are you sure you are really using our develop branch and not an outdated fork?

@phoerious Yeah, I'm stupid. I was using different remote. Now it's OK. Sorry for confusion.

I assume you were trying to build this branch: https://github.com/varjolintu/keepassxc/blob/2.2.0-browser-beta5/release-tool which does not have an up-to-date release-tool

Yeah exactly. There is develop branch there too. I was doing:

git checkout develop -- ./release-tool

instead of

git checkout origin/develop -- ./release-tool

Because develop in my case is local branch tracking https://github.com/varjolintu/keepassxc.

Ok release-tool now run fine. But I've got permission error (running release-tool directly on host):

fuse: mount failed: Permission denied
open dir error: No such file or directory
+ mkdir -p ../out/
+ mv '*.AppImage*' ../out/
mv: cannot stat '*.AppImage*': No such file or directory
+ mv '../out/*.AppImage' ..
mv: cannot stat '../out/*.AppImage': No such file or directory
+ rmdir ../out

I've resolved fuse permission error. I followed advice https://github.com/moby/moby/issues/9448#issuecomment-144149513

  1. ~I was using AppArmor docker profile in enforce mode. So I switched docker to complain mode instead (not sure if this was necessary, probably not).~ Not necessary. In my case it worked in enforced mode too.

  2. Added --privileged option to docker run

diff --git a/release-tool b/release-tool
index 680cdca..42f01fa 100755
--- a/release-tool
+++ b/release-tool
@@ -615,6 +615,7 @@ build() {
         logInfo "Launching Docker container to compile sources..."

         docker run --name "$DOCKER_CONTAINER_NAME" --rm \
+            --privileged \
             --cap-add SYS_ADMIN --device /dev/fuse \
             -e "CC=${CC}" -e "CXX=${CXX}" \
             -v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \

EDIT: Not sure if anybody interested, but I've customized Dockerfile to use ubuntu stock dev libraries.

FROM ubuntu:16.04

RUN apt-get update && \
    apt-get install --yes build-essential cmake libxi-dev libxtst-dev qtbase5-dev \
    libqt5x11extras5-dev qttools5-dev qttools5-dev-tools \
    libgcrypt20-dev zlib1g-dev libyubikey-dev libykpers-1-dev \
    libsodium-dev libboost-system-dev \
    python-pip git wget fuse module-init-tools

RUN pip install transifex-client

VOLUME /keepassxc/src
VOLUME /keepassxc/out
WORKDIR /keepassxc

You don't need that if the user inside the Docker image is root. You can use our own Dockerfile for building a compatible image. But perhaps you also have some extra AppArmor/SELinux policies on your system.

Not sure why, but I need that ;-). Even though user in docker container is root. But maybe it's specific to my setup.

Probably some AppArmor policies on your host.
Your customized Dockerfile uses 16.04. We can't provide that upstream, because it's too new.

We can't provide that upstream, because it's too new.

That is completely fine. I understand that.

Anyway my problem with resources seems to be resolved. :-) Thank you @phoerious

I'm running Xubuntu Artful and I'm also getting the error:

keepassxc: /tmp/.mount_keepasCiTfLu/lib/x86_64-linux-gnu/libdbus-1.so.3: no version information available (required by /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5)
keepassxc: symbol lookup error: /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5: undefined symbol: FT_Get_Font_Format

This looks like the AppImage tries to load Qt from your system instead of the bundled libs. Are you sure you're running the latest 2.2.4 AppImage from our download page?

Was this page helpful?
0 / 5 - 0 ratings