root dacfe20494 Add a container image for the server
Why: the server is a single static binary with no dependencies, so its
container should be nothing but that binary. Shipping one also makes the
master key easy to lose, which needed handling rather than documenting.

What:
- Dockerfile: two stages, runtime is scratch plus the binary and a CA bundle
  for reaching an OIDC provider, running as uid 65532. About 9 MB. The build
  stage copies only go.mod, cmd/keeporgd and internal, so client or docs
  changes do not invalidate it.
- The image has no shell, so HEALTHCHECK runs `keeporgd -healthcheck`, a new
  flag that probes /healthz on the configured address and exits non-zero
  with a reason. podman needs --format docker to keep the healthcheck at
  all, which the Makefile passes when it picks podman.
- New -master-key-file flag, so a mounted secret works without a config file.
- The server now checks at startup whether the master key still opens the
  stored vault keys, and says so. Without it, a container restarted without
  its key discovers the problem one failed merge at a time.
- make docker, docker-run and docker-save; a compose example with read_only,
  cap_drop ALL and no-new-privileges.
- The client and the server now version independently, so their Debian
  changelogs are split per package and `make changelog` takes PKG=.
  Server 0.3.0; the clients stay at 0.2.0.

Proved: built with podman and run. The container serves /healthz and /web,
its own healthcheck reports healthy, and a vault created through it was
edited from the same base by keepassxc-cli twice, merged by the server into
version 3, and read back with both entries intact. Restarted without the
master key it warns "1 of 1 stored vault keys do not open with this master
key" and answers a merging push with 409 merge_failed, leaving the vault
untouched; restored, it logs "1 vault keys available for merging" and merges
again. The same key supplied through -master-key-file from a mounted file
works identically. Both .deb packages build with their own changelog, and
make check is clean.
2026-10-30 09:17:12 +01:00
2026-10-30 09:17:12 +01:00
2026-10-30 09:17:12 +01:00
2026-10-30 09:17:12 +01:00
2026-10-30 09:17:12 +01:00

KeepOrg

A synchronization adapter for KeePass. Your databases stay ordinary .kdbx files that KeePassXC, KeePass2 or KeePassDX opens directly; a server keeps them in step between everyone who has access.

When two people save at once, the server can merge both edits: it opens the two copies in memory, folds them together by KeePass's own rules and stores the result. Nothing is lost, and no one has to reconcile two files by hand.

Merging means decrypting, so a merge vault's password is kept on the server, encrypted under a master key held outside the data directory. That makes the server part of your trust boundary. Vaults on any other conflict strategy keep their key off the server entirely, exactly as before.

  • Server (keeporgd, Linux): hosts many KDBX databases, controls access with a tree of user groups, accepts registrations by invite link or OIDC, merges concurrent edits, and pushes updates to connected clients. Its web page at /web is for creating a vault and setting its password.
  • Desktop client (keeporg, Linux, macOS, Windows, BSD): mirrors every assigned database into one directory as a real file, pushes each save and applies what others push.
  • Android client: the same, published to every file picker as a storage provider.

No third-party dependencies, no cgo, no FUSE. The KDBX 4 codec, including ChaCha20, BLAKE2b and Argon2, is part of the repository and is tested against both the relevant RFCs and a real KeePassXC.

Quick start

make check                 # gofmt, vet, tests
make all                   # keeporgd and keeporg for this host

# a server for trying it out, on 127.0.0.1:8765
KEEPORG_ADMIN_PASSWORD=dev-password-1 make run-server

# in another shell
build/linux-arm64/keeporg login -server http://127.0.0.1:8765 -user admin
build/linux-arm64/keeporg groups
build/linux-arm64/keeporg vault -create "Team Vault" -group <group-id>
build/linux-arm64/keeporg run

Team Vault.kdbx appears in ~/KeepOrg; open it in KeePassXC with the vault password you just set. Every save is pushed, and a save that races with a colleague's is merged rather than refused.

Or open http://127.0.0.1:8765/web and create the vault from the browser.

Packaging

make deb        # Debian packages for the client and the server
make docker     # server container image, scratch-based, about 9 MB
make dmg        # macOS disk image with an /Applications symlink (on macOS)
make windows    # Windows zip with a Task Scheduler job
make android    # unsigned release APK (needs the Android SDK)
make help       # every target

Running the server in a container:

podman run -d -p 8765:8765 \
  -e KEEPORG_MASTER_KEY="$(head -c 32 /dev/urandom | base64)" \
  -e KEEPORG_ADMIN_PASSWORD=change-me \
  -v keeporg-data:/var/lib/keeporg \
  keeporgd:latest -addr :8765 -data /var/lib/keeporg -url https://keeporg.example.com

Keep that master key: it unwraps the vault keys, and without it the server can no longer merge. See packaging/docker/compose.yaml.

Documentation

S
Description
No description provided
Readme
902 KiB
Languages
Go 87.4%
Kotlin 8.3%
Makefile 1.8%
Shell 1.3%
Go Template 0.6%
Other 0.6%