Zen + Flatpak + KeePassXC
First off, a critical security caveat: These instructions bust open the flatpak sandbox by giving Zen (or Firefox–you can adapt these same instructions to work with any FF-based browser) the ability to run executables on the host system.
Now, in my case, the alternative is running a native version of the browser via tarball or AppImage1, so for me it’s six of one and a half dozen of the other. But you have been warned!
Secondly, I should note these instructions are specifically for getting a flatpak version of Zen (or Firefox) working with a native KeePassXC installation. If your KeePassXC install is also a flatpak, you’re gonna have to look elsewhere (I tend to use native packages as much as possible and only fall back on Flatpak when I have no other option).
With that disclaimer out of the way, here’s the instructions I lifted from this Github comment, but with a bit more exposition to make various assumptions in that comment explicit.
First off, I’m going to assume you have an existing and working native KeePassXC installation. So to begin with, you’re going to install the KeePassXC-Browser add-on in Zen. This add-on communicates with KeePassXC via a separate proxy application, so what we’re going to do is replace that proxy application with a wrapper script that our flatpak’d Zen browser will launch.
Additionally, you need to make sure you have flatpak-spawn
available. On Debian or Ubuntu, this executable is part of the flatpak-xdg-utils
package, and the binary is located at /usr/libexec/flatpak-xdg-utils/flatpak-spawn
(don’t worry if that location isn’t in your path).
Once the add-on is installed, shut down Zen and then create your wrapper script. I placed this file in ~/.var/app/app.zen_browser.zen/data/keepassxc-helper
, but theoretically it can go anywhere in your home directory2. Populate the file with the following contents3:
#!/bin/sh
exec flatpak-spawn --host /usr/bin/keepassxc-proxy "$@"
And then make the file executable (chmod +x /path/to/script
).
Next, we need to give Zen permission to run native executables4. Again, to emphasize: This command breaks one of the features of the flatpak security sandbox! If you are okay with that, you can proceed by running the following command:
flatpak override --user --talk-name=org.freedesktop.Flatpak app.zen_browser.zen
Additionally, you will also need to give Zen access to your home directory (this is necessary to ensure KeePassXC and Zen are using the same configuration files for the native messaging bridge; KeePassXC isn’t sandboxed so it’s going to use your real home directory, not the Zen sandbox home directory).
Note that, if you have any existing Zen profiles, they’re suddenly going to disappear as Zen is going to start looking in ~/.zen/
for profiles instead of ~/.var/app/app.zen_browser.zen/cache/zen/
. If you have profiles you want to preserve, you’ll have to copy those profile directories over to the new location and select them via about:profiles
.
With all that said, to grant these permissions, run the following command:
flatpak override --user --filesystem=home app.zen_browser.zen
Now we’re going to open up KeePassXC and change the settings to point to our proxy script:
- Tools -> Settings -> Browser Integration
- General -> check Firefox
- Advanced -> check “Use a custom proxy location”
- Click Browse
- Select the wrapper script we created
Then exit KeePassXC and restart.5
Finally, launch Zen! If this worked (and I didn’t miss any steps or screw up the instructions…), the KeePassXC-Browser add-on should successfully connect to your native KeePassXC instance.
-
In fact, for a few months now I’d been using Zen via AppImage, however a) there’s currently a bug that causes the AppImage version to crash on my laptop upon awaking from sleep, b) updating the AppImage is different from everything else on my system which is annoying, and c) I can more easily apply the workaround for the light theme bug by setting GTK_THEME to “adwaita” on the flatpak once rather than needing to monkey around with the desktop file after each upgrade. ↩
-
Yes, that means we’ll be granting Zen access to your home directory. More on that later. ↩
-
Yes, I realize the call to
flatpak-spawn
doesn’t include the full path despite the executable not being in the host PATH. Apparently, within the sandbox, this executable is in the PATH, and so the script will run successfully even if a test run on the host doesn’t work. ↩ -
We’re actually going to grant a couple permissions to Zen. Throughout I’m using
flatpak override
but if you prefer a graphical experience, you can also perform these operations using Flatseal. ↩ -
I actually never checked that a restart is strictly required, so feel free to try skipping this step. I do know that upon startup, KeePassXC populates
~/.mozilla/native-messaging-hosts/org.keepassxc.keepassxc_browser.json
6 based on the supplied settings, and we need that file updated to point to our wrapper script before Zen starts up. ↩ -
Yes you’re reading that right. Zen uses
~/.mozilla/
for the native messaging bridges, probably because that’s where native applications expect to drop their bridges. I doubt this is considered a bug, but it was a bit unexpected… ↩
Likes
-
{% for webmention in webmentions %}
-
{{ webmention.content }}
{% endfor %}
No bookmarks were found.
{% endif %}Likes
-
{% for webmention in webmentions %}
-
{% if webmention.author %} {% endif %}
{% endfor %}
-
{% for webmention in webmentions %}
-
{{ webmention.content }}
{% endfor %}
No links were found.
{% endif %}Replies
-
{% for webmention in webmentions %}
-
{% if webmention.author %} {% endif %}{% if webmention.content %} {{ webmention.content }} {% else %} {{ webmention.title }} {% endif %}
{% endfor %}
-
{% for webmention in webmentions %}
- {% endfor %}
-
{% for webmention in webmentions %}
- {% endfor %}
No reposts were found.
{% endif %}-
{% for webmention in webmentions %}
- {% endfor %}
No RSVPs were found.
{% endif %}-
{% for webmention in webmentions %}
-
{% if webmention.author %} {% endif %}{% if webmention.content %} {{ webmention.content }} {% else %} {{ webmention.title }} {% endif %}
{% endfor %}
No webmentions were found.
{% endif %}