The Problem: Scattered E-Books and No Good Way to Access Them
If you’ve been collecting e-books for a while, you know the pain. PDFs on your laptop, EPUBs on an old USB drive, a handful of AZW3 files from Kindle — scattered across devices with no single place to manage them. Cloud services like Google Play Books or Apple Books lock you into their ecosystems. Kindle requires you to buy from Amazon. What you actually want is something simpler: a private library you control, accessible from any browser, on any device.
I hit this exact wall a few years back. I had over 300 technical books — Linux guides, Docker references, programming tutorials — and no clean way to organize or read them outside my main workstation. Calibre-Web on Docker fixed that. It’s now a permanent fixture in my HomeLab alongside Nextcloud and Gitea.
What Calibre-Web Actually Is
Worth taking 60 seconds to understand the architecture before diving into Docker commands.
Calibre is a mature desktop application for managing e-book collections. It stores everything in a folder-based library with a metadata.db SQLite file that tracks books, authors, covers, and metadata.
Calibre-Web is a separate open-source project that reads that same library folder and exposes it through a clean web interface. You get:
- A searchable, filterable book catalog
- In-browser reading (EPUB format via the built-in reader)
- OPDS catalog support — so e-reader apps like KOReader or Moon+ can pull books directly
- User accounts so you can share access with family
- Send-to-Kindle and send-to-email features
- Book format conversion (optional, requires Calibre binary installed)
The key architectural point: Calibre-Web does not store books itself. It reads from your Calibre library folder. Your actual files stay in a plain directory — no proprietary database migrations, no vendor lock-in.
Prerequisites
You need:
- A Linux server or NAS (even a Raspberry Pi 4 with 2GB RAM handles this fine)
- Docker and Docker Compose installed
- An existing Calibre library, or a willingness to create one
No Calibre library yet? Install the Calibre desktop app on your PC and add a few books. It generates a library folder containing metadata.db and author subfolders. Copy that entire folder to your server and you’re ready.
Setting Up the Directory Structure
On your server, create the two folders Calibre-Web needs:
mkdir -p ~/calibre/config
mkdir -p ~/calibre/library
The library folder is where your Calibre library lives — the one with metadata.db. The config folder is where Calibre-Web stores its own settings, user database, and cache.
Already have a Calibre library on your PC? Copy it over:
scp -r /path/to/Calibre\ Library/ user@your-server:~/calibre/library/
Writing the Docker Compose File
Create docker-compose.yml inside ~/calibre/:
version: "3.8"
services:
calibre-web:
image: lscr.io/linuxserver/calibre-web:latest
container_name: calibre-web
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Tokyo
- DOCKER_MODS=linuxserver/mods:universal-calibre # optional: enables format conversion
volumes:
- ./config:/config
- ./library:/books
ports:
- "8083:8083"
restart: unless-stopped
A few things worth explaining here:
PUIDandPGID— set these to match your Linux user ID. Runid -uandid -gto check. Mismatched values are the #1 cause of permission errors on startup.TZ— set your timezone so timestamps display correctly.DOCKER_MODS=linuxserver/mods:universal-calibre— this optional mod installs the full Calibre binary inside the container, enabling format conversion (e.g., EPUB → MOBI). Skip it if you don’t need conversion; it adds 3–5 minutes to the first startup.- The
/booksmount is where Calibre-Web expects to find your library.
Starting the Container
cd ~/calibre
docker compose up -d
Check the logs to confirm it started cleanly:
docker compose logs -f calibre-web
On a typical VPS or home server, it’s listening within 10–15 seconds (longer if you enabled the Calibre mod — see above). Open http://your-server-ip:8083 in your browser.
First-Time Configuration
The first screen asks for your Calibre library path. Enter /books — that’s the container-side mount point from the compose file.
Default login credentials:
- Username:
admin - Password:
admin123
Change the admin password immediately: go to Admin → Edit User → admin and update it before doing anything else.
From the admin panel, you can also:
- Enable or disable new user registration (disable it for a private setup)
- Configure SMTP settings for the send-to-Kindle feature
- Enable Goodreads integration for book metadata lookup
Setting Up the OPDS Catalog for E-Reader Apps
Honestly, this is the feature that makes the whole thing worth it. OPDS (Open Publication Distribution System) is a standard catalog format understood by most e-reader apps. Once configured, KOReader, Aldiko, and Moon+ Reader can browse and download books directly from your Calibre-Web instance — no side-loading, no cables.
In Calibre-Web, go to Admin → Basic Configuration → Feature Configuration and enable Anonymous browsing if you want the OPDS feed accessible without login. Useful for trusted home networks.
Your OPDS feed URL will be:
http://your-server-ip:8083/opds
In KOReader: Search → OPDS catalog → Add catalog, paste the URL, done. Your entire library shows up browsable from your e-reader.
Exposing Calibre-Web Outside Your Home Network
Two practical options here:
Option 1: Reverse Proxy with NGINX or Caddy
Already running a reverse proxy in your HomeLab? Add a block for Calibre-Web. With Caddy, it’s four lines:
books.yourdomain.com {
reverse_proxy localhost:8083
}
Caddy handles HTTPS automatically via Let’s Encrypt. No certificate management needed.
Option 2: Tailscale (Simpler for Beginners)
Running Tailscale already? Your Calibre-Web port is reachable via the Tailscale IP without any port forwarding or DNS configuration. Just hit http://100.x.x.x:8083 from any Tailscale-connected device. This is what I use on the road.
Keeping Your Library Updated
Add new books using the Calibre desktop app as usual. Changes write to metadata.db in the shared folder, and Calibre-Web picks them up automatically. No container restart required — just refresh the browser.
To update the container when a new Calibre-Web version drops:
cd ~/calibre
docker compose pull
docker compose up -d
The linuxserver.io image keeps latest pinned to the current stable release, so these three commands are all you need.
A Few Things I Learned the Hard Way
After running this setup for two years, here are the gotchas to watch for:
- Permission errors on startup: Almost always a PUID/PGID mismatch. Run
idon your server user and confirm the values match the compose file. - metadata.db locked: If Calibre desktop is open on your PC and the library is mounted via NFS to your server, SQLite file locking causes conflicts. Close the desktop app before Calibre-Web tries to write to the database.
- OPDS not showing all books: Some OPDS clients cap results at 30 per page. If your catalog looks incomplete, check the client’s settings for catalog page size.
- Format conversion slow on first run: If you enabled the Calibre mod, the first startup downloads and installs the full Calibre binary — 3–5 minutes is normal. Don’t kill the container thinking it hung.
What You End Up With
Once this is running, you have a private library that:
- Works in any browser — no app install required
- Syncs reading position across devices via OPDS-compatible apps
- Serves books on your local network at full speed
- Stores everything in plain files you own completely
- Costs nothing beyond the server hardware you already have
Setup takes maybe 20 minutes. The OPDS integration with KOReader is what sold me — I read technical documentation on my tablet during commutes and everything stays in one place. Calibre-Web running on a Raspberry Pi 4 idles at under 100MB RAM, so it’s not competing with anything else on your HomeLab.
There’s no good reason to keep your e-book collection scattered across devices and cloud silos. A self-hosted Calibre-Web instance is lightweight, easy to maintain, and gives you full control of your reading library — on your terms.

