|
Some checks failed
Build and push Joplock image / build-and-push (push) Has been cancelled
- add app/proxy/vaultProxyGuard.js: inspects proxied note writes and deletes before forwarding to upstream Joplin Server - covers single PUT /api/items/root:/<id>.md:/content, batch PUT /api/batch_items, single DELETE, and batch DELETE - rejects with 403 when a vault note body lacks the encrypted marker, or when a vault note is deleted via the sync proxy - bodies over 10 MB stream through without inspection (resource blobs) - unauthenticated requests stream through (upstream handles 401) - wire guard into createServer.js proxy entry point; replay buffered body via Readable.from() on allow - 34 new unit tests, all 394 tests passing |
||
|---|---|---|
| .github/workflows | ||
| app | ||
| cm-build | ||
| hljs-build | ||
| playwright-tests | ||
| public | ||
| scripts | ||
| tests | ||
| vendor/turndown-lib | ||
| .dockerignore | ||
| .gitignore | ||
| AGENT_GUIDE.md | ||
| docker-compose.example-full-build.yml | ||
| docker-compose.example-full.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.js | ||
| README.md | ||
| server.js | ||
Joplock
A secure, fast web client for Joplin Server.
Joplock runs as a sidecar alongside an unmodified Joplin Server instance, sharing the same Postgres database, sessions, notes, folders, and resources. It gives you a lightweight browser-based interface to your Joplin notes without modifying Joplin Server itself. Keep using the other Joplin clients too, this won't interfere.
Key Features
- Full Joplin compatibility -- desktop, mobile, CLI, and Joplock all work with the same account and data simultaneously
- Low Resource usage -- minimal memory usage on the client, fast and responsive
- Security-first design -- no private data stored on the client; sessions are cleaned up on logout; per-user settings and admin controls for user management
- User creation from Joplock UI -- create and modify users directly from Joplock settings page
- Full database backup and restore -- create and restore complete Postgres backups for both Joplin and Joplock data
- Multi-factor authentication -- optional TOTP-based MFA on top of standard Joplin sessions
- Fast search -- searches titles and note bodies directly in Postgres; optional live-as-you-type search
- Near-instant autosave -- debounced saves with conflict detection, hash-based deduplication, and an undo ring buffer with full note history snapshots
- PWA support -- installable as a home screen app on mobile and desktop with splash screens, offline indicator, and service worker shell
- Server-side rendering -- SSR with htmx for minimal client-side JavaScript; CodeMirror editor for markdown, rich preview mode with WYSIWYG editing
Runtime Model
Joplock:
- reads Joplin data directly from the shared Postgres database
- validates the same
sessionIdcookie used by Joplin Server - writes notes, folders, and resources through stock Joplin Server APIs
That keeps desktop, mobile, CLI, and Joplock compatible with the same account and data.
Requirements
- docker
- an existng Joplin Server instance, or run the fullstack option
Environment
All configuration is done directly in the compose files via inline environment variables with comments. No .env file is needed -- just edit the values in docker-compose.yml or docker-compose.example-full.yml before starting.
Backup and recovery configuration:
JOPLOCK_BACKUP_DIRenables server-side full database backupsJOPLOCK_BACKUP_COMPRESSIONcontrols thepg_dumpcompression method, for examplezstd:19orgzip:9JOPLOCK_BACKUP_COMPRESSION_LEVEL=0-9controlspg_dumpcompression for backup filesJOPLOCK_RECOVERY_ENABLED=trueenables the break-glass recovery page at/recoveryJOPLOCK_RECOVERY_PASSWORDprotects that recovery page
Important:
- Backups are only durable if
JOPLOCK_BACKUP_DIRis mounted to persistent storage. - Default backup compression is
zstd:19, which is usually smaller thangzip:9. JOPLOCK_BACKUP_COMPRESSIONtakes precedence overJOPLOCK_BACKUP_COMPRESSION_LEVEL.- Higher compression produces smaller backup files but may take longer to create.
- Recovery mode is for backup and restore only, not regular note usage.
- Restore replaces the entire shared Postgres database, including Joplock-owned tables.
Docker
Published container image:
ghcr.io/abort-retry-ignore/joplock:latest
Sidecar Install
Use this when you already have Joplin Server and Postgres running elsewhere. Edit the environment values in docker-compose.yml to point at your existing setup, or copy into your existing compose. Then:
docker compose up -d
This pulls the pre-built image from GitHub Container Registry. To build from source instead:
docker compose -f docker-compose-build.yml up -d --build
On Linux, the compose files map host.docker.internal to the host gateway so Joplock can reach host services by default.
Backup And Restore
Normal workflow:
- Sign in as the configured Joplock admin.
- Open
Settings -> Admin -> Backup & Restore. - Create a backup or restore an existing server-side backup.
Break-glass workflow when normal Joplin login is unavailable:
- Enable
JOPLOCK_RECOVERY_ENABLED=trueand setJOPLOCK_RECOVERY_PASSWORD. - Open
/recovery. - Sign in with the recovery password.
- Create or restore full database backups from there.
Before restoring:
- Stop or quiesce Joplin Server if possible.
- Stop active sync clients.
- Expect the entire shared Postgres database to be replaced.
Full Example Stack
Use this as a reference/demo stack with Postgres, Joplin Server, and Joplock together. Edit the values in docker-compose.example-full.yml as needed, then:
docker compose -f docker-compose.example-full.yml up -d
The full example uses the public joplin/server:latest image. Joplock is exposed on http://localhost:5444 by default. Joplin Server is internal-only unless you add a port mapping.
The full example is meant as a working reference compose file. Adjust it for your real deployment.