Zero-knowledge encrypted message sharing — for the times "just send it in an email" isn't good enough.
OpenKeepr lets you create a one-time, self-destructing message (a password, an API key, a recovery phrase) and share it via a single short link. The content is encrypted in your browser before it ever leaves your device; the server cannot read it, and neither can the operator.
Status: v1.1.0 — production-ready, but inspect the code and your own deployment before trusting it with real secrets. Security feedback welcome — see
SECURITY.md.
- Zero-knowledge AES-256-GCM encryption (key in URL fragment, never transmitted)
- Optional recipient e-mail allow-list with 6-digit verification codes
- Auto-expire after N hours/days (hard cap: 30 days)
- Auto-expire after N opens
- Markdown messages with live preview
- Dark / light / system-auto theme
- 6 languages out of the box: English, Dutch, French, German, Spanish, Italian
- Fully offline assets — no CDN
- REST API with scoped API keys, rate limiting and Markdown docs at
/docs/api - Admin dashboard with audit log, feedback inbox, 2FA, maintenance mode
- User feedback form (with optional GitHub redirect)
- SQLite by default — single file, easy backups
brew install pyenv
pyenv install 3.12.10The repo pins 3.12.10 via .python-version, so pyenv will auto-select it inside this directory.
macOS 26+ note: older Python patches (≤ 3.12.5) fail to build because Homebrew's
tcl-tkis now version 9 and breaks the_tkinterC extension. OpenKeepr doesn't use tkinter, but pyenv aborts anyway. Either install 3.12.6 or newer (recommended —3.12.10does the trick), or temporarilybrew unlink tcl-tkbefore building an older Python andbrew link tcl-tkafterwards.
cd /path/to/openkeepr
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txtThe venv lives in .venv/ and is git-ignored. To leave it: deactivate.
cp .env.example .env
# Generate three strong secrets:
python -c "import secrets;print(secrets.token_urlsafe(64))" # SECRET_KEY
python -c "import secrets;print(secrets.token_urlsafe(64))" # RECIPIENT_HASH_SECRET
python -c "import secrets;print(secrets.token_urlsafe(64))" # SERVER_ENCRYPTION_KEY
# Paste each into .envflask --app run.py db upgradepython scripts/fetch_assets.pyThis downloads pinned, integrity-checked copies into app/static/vendor/. Re-run when you want to update versions (edit scripts/fetch_assets.py to bump).
python run.py
# → http://127.0.0.1:5000On first boot, OpenKeepr will print the initial admin password to the console once. Save it, then log in at /admin and turn on 2FA immediately.
See deploy/README.md for a step-by-step guide using:
- gunicorn (WSGI)
- systemd (process supervision)
- nginx (TLS termination + reverse proxy)
- Let's Encrypt (certificates)
- fail2ban (brute-force protection)
A bootstrap script is provided at scripts/install_vps.sh.
All runtime configuration is via environment variables. See .env.example for the full list with comments.
OpenKeepr exposes a REST API at /api/v1. Documentation lives at docs/api.md and is rendered at /docs/api in the running app. Generate an API key from your account settings.
Source language is English. Translations for nl, fr, de, es, it live in app/translations/<lang>/LC_MESSAGES/messages.po.
You do not need to run anything manually after changing strings:
- On every app start, source strings are re-extracted and merged into the
.pofiles (ifAUTO_COMPILE_TRANSLATIONS=true). - The
.mofiles are recompiled automatically when their.pois newer.
Want to add or update a translation by hand? Edit the .po file and restart. That's it.
All CSS, JS, fonts and icons are served from app/static/vendor/. No CDN is contacted at runtime. To update versions, edit scripts/fetch_assets.py (the manifest at the top of the file is the source of truth) and re-run it.
See SECURITY.md for our threat model and reporting policy. Notably:
- The server cannot read message content.
- Database leaks do not expose plaintext.
- 2FA is supported (and required for admin).
- Bug reports / feature requests: open an issue on GitHub, or use the in-app "Send feedback" form.
- Security issues: see
SECURITY.md— do not open a public issue.