Serve an OPDS 1.1–compliant book catalog from a directory. No database, no Calibre—just point dir2opds at a folder and use any OPDS client to browse and download your books.
- What is OPDS?
- Features
- Quick start
- Installation
- Usage
- Compatible clients
- Documentation
- Contributing
- License
- Acknowledgments
OPDS (Open Publication Distribution System) is a standard for cataloging and distributing digital publications. OPDS clients (ebook readers, apps) can discover, browse, and download books from an OPDS server. dir2opds turns a plain directory tree into such a server.
- OPDS 1.1 compliant — Works with standard ebook readers and OPDS clients
- No database — Reads directly from your filesystem; no Calibre or extra setup
- Flexible layout — Organize by folders; optional metadata from EPUB/PDF
- Search — Optional filename search (OpenSearch)
- Covers — Optional
cover.jpg/folder.jpgas catalog covers - Multiple formats — EPUB, PDF, MOBI, AZW3, and more via configurable MIME types
- Lightweight — Single binary; suitable for headless servers and containers
Using Docker (replace v1.6.0 with the latest release if desired):
docker run -d -p 8080:8080 -v ./books:/books --name dir2opds ghcr.io/dubyte/dir2opds:v1.6.0Then open http://localhost:8080 in an OPDS client or browser.
Using Go:
go install github.com/dubyte/dir2opds@latest
dir2opds -dir /path/to/books -port 8080Tip: For best client compatibility, use folders that contain either only subfolders (navigation) or only book files (acquisition), not mixed.
Choose one of the following.
go install github.com/dubyte/dir2opds@latestDownload binaries for Linux, macOS, Windows, and other platforms from the Releases page.
docker pull ghcr.io/dubyte/dir2opds:v1.6.0docker run \
-d \
-m 256MB \
--restart always \
-p 8080:8080 \
-v ./books:/books \
--name dir2opds \
ghcr.io/dubyte/dir2opds:v1.6.0Use a specific release tag instead of v1.6.0 if needed. Thanks to rockavoldy for the run example.
Pre-built image:
podman pull ghcr.io/dubyte/dir2opds:v1.6.0Build from source:
podman build -t localhost/dir2opds .Run (OPDS on port 8080):
podman run \
-d \
-m 256MB \
--restart always \
-p 8080:8080 \
-v ./books:/books \
--name dir2opds \
ghcr.io/dubyte/dir2opds:v1.6.0Rootless (e.g. non-root user, SELinux): use a bind mount with the Z option and keep the user namespace:
mkdir -p /data/Books
podman run \
-d \
-m 256MB \
--restart always \
--userns=keep-id \
-p 8080:8080 \
-v /data/Books:/books:Z \
--name dir2opds \
ghcr.io/dubyte/dir2opds:v1.6.0Add -debug for request logging, e.g. ... ghcr.io/dubyte/dir2opds:v1.6.0 /dir2opds -debug.
cd && mkdir dir2opds && cd dir2opds
# Replace v1.6.0 and the asset name with the release that matches your system
wget https://github.com/dubyte/dir2opds/releases/download/v1.6.0/dir2opds_1.6.0_linux_armv7.tar.gz
tar xvf dir2opds_1.6.0_linux_armv7.tar.gz
sudo nano /etc/systemd/system/dir2opds.service
# Paste the unit below, then set the full path of your books folder in -dir
sudo systemctl enable --now dir2opds.service/etc/systemd/system/dir2opds.service:
[Unit]
Description=dir2opds
Documentation=https://github.com/dubyte/dir2opds
After=network-online.target
[Service]
User=pi
Restart=on-failure
ExecStart=/home/pi/dir2opds/dir2opds -dir <FULL_PATH_TO_BOOKS> -port 8080
[Install]
WantedBy=multi-user.targetInstallation scripts and configs for FreeBSD, Illumos, and Linux are in the files/ directory.
Requires Go 1.21+. Build for multiple platforms:
make build-allBinaries are written to bin/.
Default: serve ./books on http://0.0.0.0:8080.
dir2opds -dir /path/to/books -port 8080| Flag | Description |
|---|---|
-calibre |
Hide files stored by Calibre |
-debug |
Log requests |
-dir |
Directory with books (default: ./books) |
-extract-metadata |
Extract title/author from EPUB and PDF |
-hide-dot-files |
Hide files whose names start with a dot |
-host |
Listen address (default: 0.0.0.0) |
-mime-map |
Custom MIME types, e.g. .mobi:application/x-mobipocket-ebook,.azw3:application/vnd.amazon.ebook |
-no-cache |
Add response headers to disable client caching |
-port |
Listen port (default: 8080) |
-search |
Enable basic filename search |
-show-covers |
Use cover.jpg or folder.jpg as catalog covers |
-sort |
Sort entries: name, date, or size (default: name) |
These OPDS clients have been tested with dir2opds:
| Client | Platform | Notes |
|---|---|---|
| Moon+ Reader | Android | Tested |
| Cantook | iPhone | Tested |
| KYBook 3 | iOS | Enable Settings → Apps → KyBook 3 → Local Network. Older app may not show the prompt; enable manually. |
Contributions are welcome. Please read CONTRIBUTING.md for license agreements, development setup, and pull request process.
This project is licensed under the GNU General Public License v3.0. See LICENSE for the full text.
- @clach04 — Testing and reporting missing content type for comics.
- @masked-owl — Reporting the HTTP path traversal security issue.
- @mufeedali — Update to push image to ghcr.io.
- @kulak — Add podman support.
- @thenktor - init files and Makefile improvements.
- @rockavoldy — For the docker command example.