How to sync KeepassXC database?

Hi,
I’ve been using KDE for a little while, but I’m not sure how best to get my KeepassXC database to sync to the cloud?
I’m currently using Google Drive but I’m open to alternatives.

KIO seems to download a temporary file in ~/.cache/kioexec/krun/ which doesn’t write back changes. I’ve read that KeepassXC would need to be “KIO-aware” to work otherwise.
Otherwise, when using GNOME, GVfs mounts to /run/user/1000/gvfs and writes changes back to GDrive. If I could continue mount to GVfs in KDE this could be an option.

Thanks in advance.

I’m not sure what you mean. Do you want to sync KeePassXC settings? The passwords are stored in an encrypted kdbx-file that you can place whereever you want and sync it like you would sync any other file.

Hi, I’m not trying to sync the settings, but the kbdx password database file itself.
I have the kbdx file in my Google Drive, but editing it with KeepassXC doesn’t save any changes back to GDrive.

As I mentioned, Dolphin/KIO seem to make a temporary copy when I open the kbdx file, into the /home/user/.cache/kioexec/krun folder. KeepassXC also opens the file from this location on launch, so if I edit the file on another device the changes don’t sync. I have to reopen the file from GDrive, which makes another temporary cached copy.
I can copy and upload files into Google Drive using Dolphin and most other applications though.

That seems odd. I have my database within a Nextcloud synced folder and it gets synced on every save. I don’t even have the ~/.cache/kioexec folder. Doesn’t Google recognize that the file has changed when you save it?

My understanding is that KIO (contrarily to GVFS) does not really mount the remote as a local filesystem but provides some sort of abstraction. This has advantages but also limitations. In both cases though, you are accessing the file directly on the cloud storage.

What I would suggest is that you sync the file locally, i.e. keep a local copy of your Keepass synchronised with an actual cloud sync tool. Not sure it’s possible with Google Drive (maybe through rclone), surely it is with Dropbox, MEGA or a Nextcloud provider.

2 Likes

(This is a bit old, but I’ve stumbled into here during a different search, and happened to spend a decent bit of time checking this problem out in the past).

Cloud sync isn’t ideal, though for reasons (my personal server runs Nginx, and that’s not great with WebDAV) that’s what I’m using right now - specifically with Syncthing. I’ll probably look into getting WebDAV running again at some point, because I’m lazy.

TL;DR: if you can, use a WebDAV share that supports the file locking extensions. Put it in your fstab, but as noauto. Then add a user service a bit like this:

[Unit]
Description=Mount WebDAV Service
After=network-online.target
Wants=network-online.target
PartOf=graphical-session.target

[Service]
Type=oneshot
ExecStart=bash -c 'for i in {1..15}; do if ping -c 1 <davserver>; then mount /home/<user>/Mounts/<something>; break; else sleep 1; fi; done'
ExecStop=umount /home/<user>/Mounts/<something>
RemainAfterExit=true

[Install]
WantedBy=graphical-session-pre.target

(You might want a different Target and PartOf - this is to make the mount come up/down with the graphical session, because that’s what I want.

But you want something that supports locks - so that two clients accessing and writing to the database at the same time are less likely to step on each other’s fingers. There’s a degree to which Keepass implementations try to avoid this, but it’s limited - for example, at least on iOS you don’t have good guarantees of the latency between change on system A, and your cloud app updating it on your phone.

Some apps, e.g. KeePassium (an iOS client) and KeePass 2 (the OG and arguably the “reference” implementation) support WebDAV directly, including locking extensions. This works fine for KeepassXC as well, because you can mount a WebDAV share directly on pretty much any OS - and treat it just like a filesystem in a way that’s more meaningful than for most cloud sync solutions.

Rant

I wish KeepassXC used, like, Hashicorp Vault] or similar as a backend. KeePass was great when it started, and a single file does seem simple to handle, but concurrency messes this up really badly, and I’ve had that become a problem in practice quite a bit - like it’s not at all uncommon for me to add or change a password on one machine, and use it on another immediately. Especially when the other is a phone. Things get extra messy if I try to also change it on the other machine. The delays are just enough to make it pretty bad with any cloud sync.

1 Like

That is a very thorough answer, @modzero . Thanks! I don’t share the ideas in the rant section but all the rest. I’ve been using Keepass(…) for like 20 years now and not once had any problems with it. Simplicity is my friend, I guess.

For the purpose of sharing the kdbx file across your devices I would suggest using Synchthing

I have a similar setup with OneDrive, using kio-fuse to mount the onedrive:/personal-account URL at the $XDG_RUNTIME_DIR/onedrive folder, which can then be accessed from any application.

$HOME/.config/systemd/user/onedrive-mount.service

[Unit]
Description=Mount onedrive at %t/onedrive
After=plasma-workspace.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=%h/.local/bin/mount-onedrive
ExecStop=%h/.local/bin/umount-onedrive

[Install]
WantedBy=graphical-session.target

$HOME/.local/bin/mount-onedrive

#!/bin/python3

from pathlib import Path
from dbus.bus import BusConnection
import time

time.sleep(7)

bus = BusConnection()
fuse = bus.get_object('org.kde.KIOFuse', '/org/kde/KIOFuse')
mount_path = Path(str(fuse.mountUrl('onedrive:/personal-account')))
symlink_path = Path(os.getenv('XDG_RUNTIME_DIR')) / 'onedrive'
symlink_path.symlink_to(mount_path)
print("Mounted onedrive")

$HOME/.local/bin/umount-onedrive

#!/bin/python3

from pathlib import Path
import subprocess

symlink_path = Path(os.getenv('XDG_RUNTIME_DIR')) / 'onedrive'
mount_path = symlink_path.resolve().parent.parent
subprocess.run(["fusermount", "-u", str(mount_path)])
symlink_path.unlink()

Then run on a shell:

chmod u+x ~/.local/bin/mount-onedrive ~/.local/bin/umount-onedrive
systemctl --user daemon-reload
systemctl --user enable onedrive-mount.service

Then on the application, navigate to /run/user/$UID/onedrive and get your file there. What is weird is that kio-fuse doesn’t let you mount a top-level directory.

It ends up being a lot of configuration. Perhaps the use case of automatically mounting a KIO URL should be better supported?