Grimmory: a self-hosted library for ebooks, comics and audiobooks
A self-hosted library for your ebooks, comics, and audiobooks
At a glance
- What is it?
- Grimmory is a Java and Spring Boot application that indexes a folder of books, enriches the metadata, and serves it through a browser reader, OPDS and device sync. It is aimed at readers who want their library on their own hardware, and the main cost is a MariaDB instance and a watched import folder.
- Who is it for?
- Adopt Grimmory if you already run Docker Compose, keep your books in a host directory, and want one interface for EPUB, PDF, CBZ and M4B files with OPDS and KOReader sync. Do not adopt it if you need a managed service, cannot run MariaDB alongside it, or rely on NETWORK storage, since the README states that mode disables file operations.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Grimmory targets: a folder of files that behaves like a library
Most people with a large ebook collection end up with a directory tree and a filename convention. That works until you want to know which books you have not opened, which ones are missing covers, or which ones a second person in the house is allowed to see. Grimmory's answer is to treat a mounted directory as the source of truth and put a database-backed catalogue on top of it. The README describes it as a self-hosted digital library for people who take their reading seriously, and the feature list is written for that reader: custom and dynamic shelves with rule-based filtering, tagging and full-text search; metadata lookup from Google Books, Open Library and Amazon; a browser reader with annotations, highlights and progress tracking.
The intended user is someone comfortable running Docker Compose and a MariaDB container. The repository ships a Helm chart and a Podman Quadlet example under deploy/, so Kubernetes and Podman users are also in scope, but the quick start assumes Compose. If you want a hosted service with an app store client, this is not that. Grimmory is software you run, and the trade is control over your files against the work of keeping a database and a JVM alive.
How the pieces fit: Spring Boot backend, Angular frontend, MariaDB, and three mounted volumes
The stack is a Java backend built on Spring Boot with an Angular frontend, backed by MariaDB. The Compose example wires three host directories into the container: ./data at /app/data, ./books at /books, and ./bookdrop at /bookdrop. Those three paths are the architecture in miniature. /books is the library root, and the README is explicit that all libraries must be created within directories mounted on the host. /app/data holds application state. /bookdrop is the intake.
BookDrop is the mechanism worth understanding before you deploy. The README says you drop files into a watched folder and Grimmory detects, enriches and queues them for import automatically. So the flow is: file lands in /bookdrop, the application notices it, looks up metadata from the configured sources, and places it in a queue rather than importing it silently. That queue is the point of control. Nothing enters the catalogue until the enrichment step has run and the item has been reviewed or accepted.
Metadata lookup pulls covers, descriptions, reviews and ratings from Google Books, Open Library and Amazon, and the README notes all fields are editable. That matters because aggregator metadata is inconsistent across those three sources, and a catalogue that cannot be corrected by hand becomes untrustworthy quickly. The supported format list is broad: EPUB, MOBI, AZW, AZW3 and FB2 for ebooks, PDF for documents, CBZ, CBR and CB7 for comics, and M4B, M4A, MP3 and OPUS for audiobooks. The built-in reader covers PDFs, EPUBs and comics specifically, so audiobooks and the older Kindle formats are library items rather than things you read in the browser.
Getting it running: a .env file, a Compose file, and port 6060
The README requires Docker and Docker Compose and gives a three-step path. Step one is a .env file with application and database settings. The sample sets APP_USER_ID=1000 and APP_GROUP_ID=1000, TZ=Etc/UTC, DATABASE_URL=jdbc:mariadb://mariadb:3306/grimmory, DB_USER=grimmory, and a DB_PASSWORD placeholder. It also exposes API_DOCS_ENABLED, which defaults to false and, when enabled, serves API docs and exports OpenAPI JSON, and DISK_TYPE, which defaults to LOCAL and can be set to NETWORK.
Step two is docker-compose.yml. The image is grimmory/grimmory:latest from Docker Hub, with ghcr.io/grimmory-tools/grimmory as an alternative registry. The service maps 6060:6060, mounts the three volumes, and declares a healthcheck against http://localhost:6060/api/v1/healthcheck every 60 seconds with 5 retries and a 60 second start period. The MariaDB service uses lscr.io/linuxserver/mariadb:11.4.5 and its own healthcheck, and the application depends on it with condition: service_healthy. Step three is docker compose up -d, after which you open http://localhost:6060 and create the admin account.
The README also documents an optional heap dump flag for out-of-memory debugging: adding JDK_JAVA_OPTIONS=-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/data to the grimmory service produces a PID-specific .hprof file in /app/data. The README advises removing the option after collecting the dump because the files can be large and contain sensitive application data. That is a sensible default, and it also tells you the project expects memory problems to be diagnosed by the operator rather than reported automatically.
Multi-user access, OIDC, OPDS and the device sync paths
The multi-user feature gives each account separate shelves, progress and preferences, with local or OIDC authentication. OIDC is the interesting half. It means Grimmory can sit behind an existing identity provider instead of maintaining its own password store, which is the right shape for a household or a small group where accounts already exist elsewhere. The README points to the full documentation for OIDC setup rather than describing it inline, so the exact claim mapping and redirect configuration are not something you can plan from the repository front page alone.
Device sync is handled three ways according to the README: connect a Kobo, use any OPDS-compatible app, or sync progress with KOReader. OPDS is the general escape hatch. Any reader application that speaks the protocol can browse the catalogue without Grimmory building a client for it. Kobo and KOReader get named integrations, which suggests work beyond generic OPDS, but the README does not describe what those integrations do differently. One-click sharing is the fourth exit: sending a book to a Kindle, an email address, or another user from the interface.
The practical consequence is that Grimmory does not try to own the reading experience. The browser reader is there, with annotations and highlights, but the project also assumes you may read elsewhere and sync back. That is a healthier design than a walled garden, and it also means your progress data is only as good as the client that reports it.
Where Grimmory is the wrong tool: NETWORK storage, MariaDB, and the import queue
The clearest limitation is stated in the environment sample itself. DISK_TYPE accepts LOCAL or NETWORK, and the comment on that line says NETWORK disables file operations. If your library lives on a NAS mount or an object store and you expect Grimmory to move, rename or write files there, that mode is not for you. The README does not explain what remains available in NETWORK mode, so anyone whose storage is remote should treat this as an open question to resolve in the documentation before planning a deployment.
The second constraint is the database. Grimmory is not a single binary that reads a folder. It needs MariaDB, and the Compose example runs that as a separate container with its own volume and its own credentials. That is two services to back up, two things to upgrade, and a database that must be healthy before the application starts. For a single user with a few hundred books, a folder-based reader with a local index would be less machinery.
Third, BookDrop is a queue, not a sync. Files you drop are detected, enriched and queued for import, which means the catalogue does not instantly reflect the folder. If you are used to pointing a tool at a directory and seeing everything immediately, the queue is a deliberate extra step. It is the right step for metadata quality and the wrong one if you want zero-touch ingestion.
Alternatives and the actual difference in approach
The obvious comparison is Calibre, and specifically Calibre's content server. Calibre is a desktop application with a local SQLite library that can expose that library over HTTP. Grimmory is a server application with a MariaDB database and a browser frontend, designed from the start to run headless in a container. The difference shows up in the operation model. Calibre expects a person to open the GUI and manage the library; Grimmory expects a Compose file and a web session. Calibre's server is an add-on to a desktop tool. Grimmory's server is the product.
That also means the migration cost runs in one direction. Moving a Calibre library into Grimmory is an import exercise, and the README does not describe a Calibre import path. Anyone with a large existing Calibre library should verify that before switching, because the metadata Grimmory pulls from Google Books, Open Library and Amazon will not reproduce hand-curated series and tag data.
For comic readers, Kavita is the closer comparison in shape: a self-hosted server with a browser reader and OPDS. The README does not offer a feature-by-feature comparison, so the honest position is that both occupy the same slot and the deciding factors are format coverage and device sync. Grimmory lists audiobook formats and Kindle-format ebooks alongside comics, which widens the scope beyond a comics-first server. Whether that breadth is an advantage depends on whether you actually keep M4B files next to CBZ files.
Release cadence, upgrade cost and the AGPL-3.0 licence
The release history in the supplied material shows v3.3.1, v3.3.2 and v3.3.3 within roughly two weeks of each other in August 2026, with a repository push in September 2026. The README explains the tagging scheme: stable images are published from semantic-release tags on main as vX.Y.Z plus latest, and nightly images are built from develop and tagged nightly. The default branch is develop. Anyone running the latest tag is on the stable line; anyone running nightly is tracking develop and should expect breakage between releases.
The upgrade cost is mostly database and container work. Because MariaDB runs as a separate service with its own config volume, an upgrade means pulling a new application image and restarting, while the database persists. The README points to upgrade guides in the full documentation rather than inlining migration steps, so schema changes between major versions are something to check there before pulling. The heap dump option is a reminder that the JVM's memory ceiling is an operational parameter you may need to tune, and the README does not publish recommended heap sizes.
The licence is AGPL-3.0. For self-hosting that is unremarkable. If you modify Grimmory and offer it to others over a network, the AGPL's source-availability condition is the part that differs from permissive licences. This is a description of the licence, not legal advice, and anyone embedding Grimmory in a commercial service should read the licence text and possibly take counsel.
On maintenance, the material supports one concrete observation: the project maintains a Crowdin project for translations and separate DEVELOPMENT.md files for the backend and frontend, with a root Justfile described as the primary local command surface mirroring backend/Justfile and frontend/Justfile. That is a contributor structure, not a user-facing maintenance burden, but it does indicate the project expects ongoing work across two codebases rather than a single script.
Editorial conclusion
Adopt Grimmory if you already run Docker Compose, keep your books in a host directory, and want one interface for EPUB, PDF, CBZ and M4B files with OPDS and KOReader sync. Do not adopt it if you need a managed service, cannot run MariaDB alongside it, or rely on NETWORK storage, since the README states that mode disables file operations. Before committing, verify three things: that every library you create lives under a mounted host directory such as /books, that your MariaDB credentials are changed from the sample values, and that your client speaks OPDS or is a Kobo or KOReader, because those are the device paths the README names.
Community notes