Files
keeporg/README.md
T
ReactorcoremeltdownandClaude Opus 5.5 ef6598fa15
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
Set the server's public URL from KEEPORG_EXTERNAL_URL
The image passes neither -config nor -url, so a deployment had no way to
set external_url and the server built invite links, device-approval pages
and the OIDC redirect URI on http://localhost:8765. The variable overrides
the configuration file and -url overrides it. The deployment values set it
to https://keeporg.tiredsysadmin.cc.

Also document every environment variable the server reads, and the
standard proxy and CA variables it honours for OIDC.

Server version 0.8.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:40:09 +01:00

144 lines
6.6 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): a system tray
application that mirrors every assigned database into one directory as a
real file, pushes each save and applies what others push. The same binary
is the command line for administration and for headless machines.
- **Android client**: the same, published to every file picker as a storage
provider.
No FUSE, and the server has no third-party dependencies and no cgo. 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. The desktop client's one dependency is `fyne.io/systray`, for the
tray icon.
## 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 # the tray; `keeporg run` without a desktop
```
`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.
## The tray
Started without a command — from the applications menu, the DMG's
`KeepOrg.app`, or `keeporg-tray.exe` on Windows — the client puts a padlock
in the system tray:
| Item | What it does |
| --- | --- |
| *status line* | signed-in account and whether everything is up to date, or what needs attention |
| **Open Mirror Folder** | the directory holding the `.kdbx` files |
| **Databases ▶** | each database with its state; choosing one opens it in your KeePass application |
| **Sync Now** | reconcile immediately instead of at the next rescan |
| **Sign In… / Sign Out** | sign in by approving a code in the browser (password, second factor or SSO); sign out revokes the session and leaves the files |
| **Open Web Interface** | `/web` on the server, for creating vaults and managing access |
| **Open Config** | the settings file; a saved edit applies at once |
| **Open Log** | the agent's log |
| **Start at Login** | LaunchAgent on macOS, XDG autostart on Linux and BSD, the Run key on Windows |
| **About**, **Quit** | |
Conflicts, merges and failures raise a desktop notification.
## Configuration
`config.json` in the user configuration directory
(`~/.config/keeporg`, `~/Library/Application Support/keeporg`,
`%AppData%\keeporg`) holds every client setting. The first start writes it
in full, and the tray reloads it when it is saved.
| Key | Default | Meaning |
| --- | --- | --- |
| `server_url` | | the server's base URL, as a browser sees it |
| `username`, `token` | | written by signing in |
| `device_label` | host name | this device in the server's session list |
| `mirror_dir` | `~/KeepOrg` | where the `.kdbx` files are kept; `~` is expanded |
| `poll_seconds` | `2` | how often local saves are looked for |
| `request_timeout_seconds` | `60` | the limit on one API request (the event stream is exempt) |
| `ca_file` | | a PEM bundle trusted besides the system roots, for a private CA |
| `log_file` | | the log; empty means `keeporg.log` beside the config for the tray, standard error for `keeporg run` |
| `notifications` | `true` | desktop notifications from the tray |
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: keeporg-tray.exe, keeporg.exe and a Task Scheduler job
make android # unsigned release APK (needs the Android SDK)
make help # every target
```
Running the server in a container:
```bash
head -c 32 /dev/urandom | base64 > master.key
podman secret create keeporg_master_key master.key
podman run -d -p 8765:8765 \
--secret keeporg_master_key \
-e KEEPORG_MASTER_KEY_FILE=/run/secrets/keeporg_master_key \
-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. `KEEPORG_MASTER_KEY` takes the base64 key directly if
your secret store injects variables instead of files. See
[packaging/docker/compose.yaml](packaging/docker/compose.yaml).
Server environment variables:
| Variable | Meaning |
| --- | --- |
| `KEEPORG_MASTER_KEY` | the master key, base64; overrides the other two sources |
| `KEEPORG_MASTER_KEY_FILE` | path to a file holding the master key (base64 or 32 raw bytes); never created, and if it is missing the server runs but cannot create or merge vaults |
| `KEEPORG_EXTERNAL_URL` | the public base URL (`external_url`); `-url` overrides it |
| `KEEPORG_ADMIN_PASSWORD` | the first `admin` password, read only on an empty server and by `-reset-admin` |
Everything else is configured in `server.json` or by flag. The details,
including the standard proxy and CA variables, are in
[docs/HANDOVER.md](docs/HANDOVER.md#environment-variables).
## 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.