grimmory
[!NOTE] Grimmory is an independent community fork of Booklore.
Grimmory is a self-hosted digital library for people who take their reading seriously.
| Feature | Description |
|---|---|
| Smart Shelves | Custom and dynamic shelves with rule-based filtering, tagging, and full-text search |
| Metadata Lookup | Covers, descriptions, reviews, and ratings pulled from Google Books, Open Library, and Amazon, all editable |
| Built-in Reader | Read PDFs, EPUBs, and comics in the browser with annotations, highlights, and reading progress tracking |
| Device Sync | Connect a Kobo, use any OPDS-compatible app, or sync progress with KOReader |
| Multi-User | Separate shelves, progress, and preferences per user with local or OIDC authentication |
| BookDrop | Drop files into a watched folder and Grimmory detects, enriches, and queues them for import automatically |
| One-Click Sharing | Send any book to a Kindle, an email address, or another user directly from the interface |
Supported Formats
| Category | Formats |
|---|---|
| eBooks | EPUB, MOBI, AZW, AZW3, FB2 |
| Documents | |
| Comics | CBZ, CBR, CB7 |
| Audiobooks | M4B, M4A, MP3, OPUS |
Quick Start
[!TIP] For OIDC setup, advanced configuration, or upgrade guides, see the full documentation.
Requirements: Docker and Docker Compose.
Image Repositories
| Registry | Image |
|---|---|
| Docker Hub | grimmory/grimmory |
| GitHub Container Registry | ghcr.io/grimmory-tools/grimmory |
Step 1: Environment Configuration
Create a .env file:
# Application
APP_USER_ID=1000
APP_GROUP_ID=1000
TZ=Etc/UTC
# Database
DATABASE_URL=jdbc:mariadb://mariadb:3306/grimmory
DB_USER=grimmory
DB_PASSWORD=ChangeMe_Grimmory_2025!
# Optional: enable API docs + export OpenAPI JSON (defaults to false)
API_DOCS_ENABLED=false
# Storage: LOCAL (default) or NETWORK (disables file operations; see Network Storage section)
DISK_TYPE=LOCAL
# MariaDB
DB_USER_ID=1000
DB_GROUP_ID=1000
MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
MYSQL_DATABASE=grimmory
Step 2: Docker Compose
Stable images are published from semantic-release tags on main as vX.Y.Z plus latest. Nightly images are built from develop and tagged nightly.
[!NOTE] Migrating from an existing Booklore container? You can keep your current service name,
container_name, database name and user, ports, and mounted volumes the same. Replace only theimage:line withgrimmory/grimmory:<tag>orghcr.io/grimmory-tools/grimmory:<tag>.
services:
booklore:
image: grimmory/grimmory:v2.2.1
Create a docker-compose.yml or copy and adapt deploy/compose/docker-compose.yml:
services:
grimmory:
image: grimmory/grimmory:latest
# Convenience tag:
# image: grimmory/grimmory:<release-version>
# Alternative: ghcr.io/grimmory-tools/grimmory:<release-version>
# To build from source instead: comment out 'image' and uncomment below
# build: .
container_name: grimmory
environment:
- USER_ID=${APP_USER_ID}
- GROUP_ID=${APP_GROUP_ID}
- TZ=${TZ}
- DATABASE_URL=${DATABASE_URL}
- DATABASE_USERNAME=${DB_USER}
- DATABASE_PASSWORD=${DB_PASSWORD}
- API_DOCS_ENABLED=${API_DOCS_ENABLED}
- DISK_TYPE=${DISK_TYPE}
depends_on:
mariadb:
condition: service_healthy
ports:
- "6060:6060"
volumes:
- ./data:/app/data
- ./books:/books
- ./bookdrop:/bookdrop
healthcheck:
test: wget -q -O - http://localhost:6060/api/v1/healthcheck
interval: 60s
retries: 5
start_period: 60s
timeout: 10s
restart: unless-stopped
mariadb:
image: lscr.io/linuxserver/mariadb:11.4.5
container_name: mariadb
environment:
- PUID=${DB_USER_ID}
- PGID=${DB_GROUP_ID}
- TZ=${TZ}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- ./mariadb/config:/config
restart: unless-stopped
healthcheck:
test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
interval: 5s
timeout: 5s
retries: 10
Step 3: Launch
docker compose up -d
Open http://localhost:6060, create your admin account, and start building your library.
Additional deployment examples:
- Docker Compose:
deploy/compose/docker-compose.yml - Helm:
deploy/helm/grimmory/Chart.yaml - Podman Quadlet:
deploy/podman/quadlet/README.md
Developer Surfaces
Contributor workflow, PR policy, and release semantics live in CONTRIBUTING.md.
General purpose development guidelines live in DEVELOPMENT.md. Component-specific implementation guidance lives in:
The root Justfile is the primary local command surface and mirrors the folder-local booklore-api/Justfile and frontend/Justfile entrypoints.
just # Show root + api + ui recipes
just test # Run backend and frontend tests
just api test # Run backend tests only
just ui dev # Start the frontend dev server
API Reference Docs
When enabled via API_DOCS_ENABLED, API reference documentation is available as both an openapi.json and as publicly accessible docs. The endpoints are:
- API reference docs are available at
http://localhost:6060/api/docs - OpenAPI JSON is available at
http://localhost:6060/api/openapi.json
BookDrop
Drop book files into a watched folder. Grimmory picks them up, pulls metadata, and queues them for your review.
graph LR
A[Drop Files] --> B[Auto-Detect]
B --> C[Extract Metadata]
C --> D[Review and Import]
| Step | What Happens |
|---|---|
| 1. Watch | Grimmory monitors the BookDrop folder continuously |
| 2. Detect | New files are picked up and parsed automatically |
| 3. Enrich | Metadata is fetched from Google Books and Open Library |
| 4. Import | You review, adjust if needed, and add to your library |
Mount the volume in docker-compose.yml:
volumes:
- ./bookdrop:/bookdrop
Network Storage
Set DISK_TYPE=NETWORK in your .env to run Grimmory against a network-mounted file system (NFS, SMB, etc.).
In this mode, direct file operations (delete, move, rename from the UI) are disabled to avoid destructive changes on shared mounts.
All other features — reading, metadata, sync — remain fully functional.
Community and Support
| Channel | |
|---|---|
| Report a bug | Open an issue |
| Request a feature | Open an issue |
| Contribute | Contributing Guide |
| Join the discussion | Discord Server |
[!WARNING] Before opening a pull request, open an issue first and get maintainer approval. Pull requests without a linked issue, without screenshots or video proof, or without pasted test output will be closed. All code must follow the project backend and frontend conventions. AI-assisted contributions are welcome, but you must run, test, and understand every line you submit. See the Contributing Guide for full details.
License
Distributed under the terms of the AGPL-3.0 License.
