Files
keeporg/README.md
T
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

83 lines
3.3 KiB
Markdown

# 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
```sh
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
```sh
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:
```bash
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](packaging/docker/compose.yaml).
## Documentation
- [docs/HANDOVER.md](docs/HANDOVER.md) — architecture, the decisions behind
it, operations, and what is left to do.
- [docs/PROTOCOL.md](docs/PROTOCOL.md) — the HTTP API.
- [android/README.md](android/README.md) — the Android module.