kp-sync
kp-sync synchronizes one KeePass database across trusted copies such as a
local hub, Google Drive, pendrives, remote sshfs sessions, and kp-access.
It uses a version history and verified merges rather than file modification
times. KeePassXC should be started through kp-sync run so saves are
observed and synchronized.
Install and configure
kp-sync runs on Linux with Python 3.11 or later. Install it from PyPI,
preferably with pipx (or python -m pip install kp-sync in a virtual
environment); add the keepassxc extra for optional password retrieval
from a running KeePassXC:
pipx install kp-sync # or: pipx install 'kp-sync[keepassxc]'
It drives existing tools, which the system provides: keepassxc-cli
(verifying and merging), rclone (cloud copies), zenity or kdialog
(desktop questions and progress), and for remote sessions sshfs,
sftp-server and bwrap. kp-sync doctor uses the keyctl command
from keyutils. udevmon 0.7.0 or
later, installed as its own tool (pipx install --system-site-packages udevmon), triggers synchronization when a key drive is plugged in. Full documentation:
https://kp-sync.readthedocs.io/.
Create ~/.config/kp-sync/config.toml, or use --profile NAME to load
~/.config/kp-sync/NAME.toml. See man 5 kp-sync-config for all options.
Ready-made profiles (cloud, Dropbox, pendrives, folders, the rcd
transport, every option) and udevmon actions are in
examples/.
Install and check the user-level daemon integration with:
kp-sync service install daemon --desktop
kp-sync service enable daemon --now
kp-sync doctor
service install daemon writes unit files without enabling or starting them;
--desktop also writes menu/autostart entries. doctor can
probe configured external endpoints, so use these commands only for a profile
whose activation and endpoints you intend to check.
Launch KeePassXC and synchronize through the normal workflow:
kp-sync run --raise-existing --app keepassxc
kp-sync status
kp-sync sync
An already-running single instance is raised immediately without pre-sync.
New instances pre-sync and launch through the daemon; drive-triggered up
still synchronizes normally.
The daemon and its private runtime state use $XDG_RUNTIME_DIR; the package
does not install or activate production units as part of installation.
Status and session history
kp-sync status shows cached synchronization history without probing
endpoints. It groups persistent copies and sessions separately, reports
recorded synchronization ages, and labels live, unfinished and
historical/unknown sessions. A status name never changes a copy's technical
identity. Optional drive aliases are display-only:
[drives.aliases]
"SERIAL:FS_UUID" = "Daily backup"
Text status uses hash prefixes of at least 12 characters, extended when
needed to distinguish recorded versions. kp-sync status --long displays
full hashes; --json always preserves full hashes.
kp-sync retire-session previews historical session identities from
available baseline history without changing it. The preview may contact
configured history stores. To retire one legacy identity, pass the exact
same identity to --identity and --confirm; the command rechecks local
session and staging evidence and reports local versus shared publication.
It does not delete database copies. Do not treat a missing remote session
or an unavailable store as evidence that its changes were synchronized.
Maintenance
Configured writable pendrives keep synchronization history and retained
bases in kp-sync/, even while Google Drive is online. This is required for
offline startup after a reboot, when runtime history and the hub are gone.
A drive from an older installation needs one successful sync with recognized
history available first. Do not remove its state.json or retained bases
manually; unknown copies still require normal reconciliation.
kp-sync cleanup # preview stores and runtime cache
kp-sync cleanup --store cloud # preview one baseline endpoint
kp-sync cleanup --runtime --apply # clean only the local base cache
kp-sync cleanup --store cloud --apply --confirm-writers-paused
kp-sync service status daemon
kp-sync service restart daemon
kp-sync --profile kp-test service restart daemon
Before shared cleanup, pause every other writer using the shared history for the entire operation, including other hosts/profiles. The confirmation flag asserts this precondition; it does not pause those writers for you. Cleanup deletes only recognized base files absent from all available history, without downloading database contents or changing history. Disconnected copies and retained ancestors remain protected. Pending decisions, recovery progress and unavailable history block application. Preview/apply return JSON with candidate bytes, protected/deleted files, blockers and partial errors. Apply requires one explicit store or runtime scope, bypasses automatic batching and works with unchanged history. Google Drive cannot atomically lock history and deletion: do not apply shared cleanup while other writers may run.
Daemon service controls support start, stop, restart and status.
They manage installed default/profile units, verify startup through the
control socket, and do not install units. Stop leaves socket/path/timer
activation enabled, so a later trigger may start the daemon again.
Existing service start|stop|status ssh-session|access-owner NAME commands
are unchanged. Custom configuration paths without an installed profile
mapping are rejected rather than controlling the wrong daemon.
kp-sync service enable daemon # enable configured installed triggers
kp-sync service enable daemon --now # also start those triggers
kp-sync service disable daemon # disable, without stopping
kp-sync service disable daemon --now # stop triggers, then daemon gracefully
kp-sync service uninstall daemon # also remove profile unit files
kp-sync service uninstall daemon --desktop # also remove its desktop entries
Enable does not install or rewrite files; use service install daemon first.
Status shows each trigger's active/enabled state. Disable is not a permanent
block: explicit requests, desktop/udev launchers and fallback startup can
still start the daemon. Uninstall preserves shared templates, other profiles,
configuration, databases and recovery data. It refuses modified/unsafe files
and leaves drop-ins/vendor units untouched; desktop removal also refuses
entries owned by another profile. Stop issuing requests during uninstall.
Optional KeePassXC password retrieval
The keepassxc extra adds browser-protocol retrieval without depending on
ssspwd. Install .[keepassxc] in the environment running kp-sync, then
opt in per profile:
[credentials.keepassxc]
url = "https://kp-sync-default.invalid"
Create one entry with that URL and the database password in an unlocked KeePassXC database, with browser integration enabled. The URL is a lookup identifier, not contacted over the network. Choose a unique hostname per profile. First interactive use asks KeePassXC to associate; name the connection for kp-sync and approve or deny entry access normally.
When a sync actually needs credentials, it tries KeePassXC before the manual password cache and existing prompt. Browser passwords are validated and kept only for that operation, never cached in the keyring. The key file is still required. Multiple matches warn and fall back without selecting one. Locked/missing KeePassXC also falls back; kp-sync never requests unlocking. Silent polls skip browser retrieval to avoid dialogs. Keep the entry updated when changing the master password.
Private pairing metadata persists under
$XDG_STATE_HOME/kp-sync/ (default ~/.local/state/kp-sync/), isolated by
configured host and profile and pinned to the selected database identity.
Selecting another database falls back instead of silently re-pairing.
kp-sync forget clears manual caches only. Use
kp-sync keepassxc-disconnect to remove local pairing, and revoke the
connection in KeePassXC to remove its authorization there. The next
interactive use can ask to pair again. A cached manual password remains
usable until expiry/forget even if KeePassXC is subsequently locked.
Named remote services
Named SSH sessions and kp-access-owner processes can run independently of
the terminal that starts them. Define them in the configuration:
[sessions]
enabled = true
[ssh_sessions.office]
target = "user@remote-host:~/kp"
mode = "rw"
[access_owners.windows]
command = ["/path/to/venv/bin/kp-access-owner", "--config", "/path/to/owner.toml"]
Each command is an argument array and is run directly, without a shell.
Use an absolute executable path when it is not available in the systemd user
manager's PATH.
Manage either service with the same interface. These commands open or close
live remote access; do not use them as configuration-only checks.
kp-sync service start ssh-session office
kp-sync service status ssh-session office
kp-sync service stop ssh-session office
kp-sync service start access-owner windows
kp-sync service status access-owner windows
kp-sync service stop access-owner windows
The SSH session mounts the staged database at its configured remote path and
keeps its restricted SSH access and synchronization lease until stopped.
Stopping it revokes the session key, performs the post-sync, and removes
staging only when synchronization completes safely. The owner process runs
in its own transient systemd user service. Both services survive terminal
closure, but are not configured to survive user logout or reboot. Logs go to
the systemd user journal; use the unit name printed by start with
journalctl --user -u UNIT. For access-owner services, the child must stay
in the foreground and its stdout/stderr are discarded; only kp-sync
lifecycle messages and errors are logged.
Shell completion
For Bash, kp-sync completion install --alias kps writes kp-sync's
argcomplete registration and a completion for the alias
(alias kps='kp-sync --profile HOST', defined in ~/.bashrc) into
bash-completion's per-user directory
(~/.local/share/bash-completion/completions/), which bash-completion
loads on demand. --alias is repeatable and optional; --dry-run shows
what would change. It needs no profile and contacts nothing. Run it
again after upgrading argcomplete; the alias file is
examples/bash-completion/kps with the
alias name filled in.
By hand, the same files are
register-python-argcomplete kp-sync (the helper lives next to
kp-sync in its environment's bin directory, which may not be on
PATH) and a copy of the example. Alternatively, add the applicable
registration command to your shell startup file:
# Bash
eval "$(register-python-argcomplete kp-sync)"
# Zsh
eval "$(register-python-argcomplete --shell zsh kp-sync)"
# Fish
register-python-argcomplete --shell fish kp-sync | source
The completion parser includes commands, options, service types, and names from the active configuration.
Progress window
For desktop synchronization, the delayed Zenity window identifies the active
profile and configured database path. Hiding it does not stop synchronization.
Set [ui].progress = false to disable it.
Documentation
- HTML guides and API reference:
docs/, built with Sphinx and Napoleon. Install optional tools in a separate environment withpython -m pip install -e '.[docs,dev]'; runpython tools/docs.py buildorpython tools/docs.py serve. The preview binds to127.0.0.1:8000; Ctrl-C stops it. Generated HTML lives in ignoreddocs/_build/html/. Builds are offline/read-only with respect to endpoints, profiles and credentials; they fail on warnings. docs/contributing.rstdescribes PEP 257 Google-style docstrings, formatting, isolated tests, and warning-free documentation validation.docs/api.rstidentifies the provisional 0.x Python integration surface; internal modules do not become supported APIs just by being documented.man 1 kp-syncdescribes commands and exit statuses.man 5 kp-sync-configdescribes configuration syntax and options.DESIGN.mdindexes the authoritative architecture and safety chapters underdesign/, with safety references and task-specific reading guides.PLAN.mdrecords implementation status and acceptance work.
License
kp-sync is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; see LICENSE for details. The same license applies to every earlier version of kp-sync, including all tagged releases, each of which contains the license file.
Copyright (C) 2026 Juan Domingo Martín.
Metadata
Release files for kp-sync 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| kp_sync-0.6.0.tar.gz | 534.5 kB | With provenance | Details for kp_sync-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| kp_sync-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for kp_sync-0.6.0-py3-none-any.whl |
Total release size: 849.7 kB
Release files / kp_sync-0.6.0.tar.gz
| Download URL | kp_sync-0.6.0.tar.gz |
|---|---|
| Size | 534.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0b6110eccce70640f784de06537f02f1dba62f285bc23bf7ade119425924c344
|
|
BLAKE2b-256 checksum How to use checksums |
f91b3cedab066535560c20288f6f17458bc13604da5756cf9480cb67c22548a4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logRelease files / kp_sync-0.6.0-py3-none-any.whl
| Download URL | kp_sync-0.6.0-py3-none-any.whl |
|---|---|
| Size | 315.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b69c332ee399c08ddeeb2eadb6eeea1a0dc2e1778c7327b4c7eb4c9516b5fe9f
|
|
BLAKE2b-256 checksum How to use checksums |
6b975ea3a31a7b4ecd257971464b14eb91e68822d532310705f86f308faa200d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logSecurity for kp-sync 0.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for kp_sync-0.6.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.