Self-Host Calibre-Web for Your eBook Library
Deploy Calibre-Web with Docker, import your Calibre library, configure send-to-Kindle email delivery, and set up an OPDS catalog for KOReader.
Before you start
- ▸Docker Engine and Docker Compose plugin installed and working
- ▸A non-root user with membership in the docker group
- ▸An existing Calibre library folder (containing metadata.db) or Calibre desktop to create one
- ▸A dedicated email address with SMTP access (and an App Password if using Gmail) for Send-to-Kindle
Calibre-Web gives you a polished browser interface over a standard Calibre library, with user management, OPDS support for e-readers like KOReader, and a send-to-Kindle pipeline. Running it in Docker keeps dependencies clean and makes upgrades trivial. This guide walks through a production-ready deployment: persistent storage, reverse proxy headers, library import, Kindle delivery, and OPDS configuration.
Prerequisites and Directory Layout
You need Docker and Docker Compose installed, a non-root user in the docker group, and an existing Calibre library directory (the folder containing metadata.db). If you are starting fresh, Calibre desktop can create an empty library that Calibre-Web can then manage.
Create a clean directory structure before writing any config:
mkdir -p ~/calibre-web/{config,books}
# If you already have a library, note its absolute path — do NOT copy it yet
Docker Compose File
The linuxserver/calibre-web image is the most actively maintained option. It bakes in the optional Calibre binaries needed for format conversion and send-to-Kindle.
cat > ~/calibre-web/docker-compose.yml << 'EOF'
services:
calibre-web:
image: lscr.io/linuxserver/calibre-web:latest
container_name: calibre-web
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- DOCKER_MODS=linuxserver/mods:universal-calibre # adds full Calibre binaries
volumes:
- ./config:/config
- /path/to/your/calibre/library:/books
ports:
- "8083:8083"
restart: unless-stopped
EOF
Replace /path/to/your/calibre/library with the real absolute path. Replace PUID/PGID with the output of id -u and id -g for your user — this prevents permission mismatches on the mounted volumes.
Starting the Container
cd ~/calibre-web
docker compose up -d
docker compose logs -f calibre-web
The first start pulls the image and, if you included the Calibre mod, downloads the Calibre AppImage — allow 2–5 minutes. You will see Server starting... in the logs when it is ready. Press Ctrl-C to detach from logs; the container keeps running.
Initial Web Setup
Open http://<server-ip>:8083 in a browser. Default credentials are admin / admin123.
- On the first-run wizard, set the Location of Calibre database to
/books— the container path, not the host path. - Click Save. Calibre-Web reads
metadata.dband populates the library immediately. - Go to Admin → Edit Profile and change the admin password before doing anything else.
Importing Your Calibre Library
Calibre-Web does not duplicate your files; it reads the same metadata.db that Calibre desktop uses. The import is the volume mount you already set up. A few important rules:
- Do not run Calibre desktop and allow Calibre-Web to write to the library simultaneously — they will corrupt
metadata.db. Choose one active writer at a time, or enable Calibre's built-in Content Server as the write path and point Calibre-Web at a read-only copy. - To add books through the web interface, go to Admin → Edit Basic Configuration → Feature Configuration and enable Allow Upload. Uploaded files are placed into the library folder and registered in
metadata.db. - Cover images are served from the library's existing cover files; no extra configuration is required.
Configuring Send-to-Kindle
Calibre-Web can email books directly to a Kindle address using Amazon's Send-to-Kindle delivery. The universal-calibre Docker mod is required for format conversion (e.g., EPUB → MOBI/AZW3).
Step 1 — Create a sending email account
Use a dedicated Gmail or SMTP account. For Gmail, create an App Password under your Google Account security settings (requires 2-Step Verification). Do not use your main account password.
Step 2 — Configure SMTP in Calibre-Web
Go to Admin → Edit Basic Configuration → E-mail Server Settings and fill in:
- SMTP Hostname:
smtp.gmail.com - SMTP Port:
587 - Encryption: STARTTLS
- SMTP Login / Password: your sending address and App Password
- From e-mail: the same sending address
Step 3 — Approve the sender address on Amazon
Log in to Amazon's Manage Your Content and Devices, go to Preferences → Personal Document Settings, and add your sending address to the Approved Personal Document E-mail List. Also note your Kindle delivery address (e.g., [email protected]).
Step 4 — Set the Kindle address per user
Each user sets their own Kindle address under Admin → Manage Users → (edit user) → Kindle E-mail. Once set, any book page shows a Send to Kindle button that triggers conversion and delivery.
Enabling OPDS for KOReader
OPDS (Open Publication Distribution System) exposes your library as a catalog feed that apps like KOReader, Lithium, and Moon+ Reader can browse and download from directly.
Enable OPDS in Calibre-Web
Go to Admin → Edit Basic Configuration → Feature Configuration and toggle Enable OPDS Catalog on. Save.
Connect KOReader
- In KOReader, open the top menu and go to Search → OPDS Catalog.
- Tap the + icon to add a catalog. Set the URL to:
http://<server-ip>:8083/opds - Enter your Calibre-Web username and password when prompted.
- Browse, download, and open books directly — KOReader remembers reading progress on device.
If Calibre-Web sits behind a reverse proxy with HTTPS (strongly recommended for any non-LAN access), use https:// and your domain instead. Make sure the proxy passes X-Forwarded-Proto and X-Forwarded-For headers; the linuxserver image respects these out of the box.
Putting Calibre-Web Behind a Reverse Proxy
Exposing port 8083 directly is fine on a LAN. For external access, put it behind Caddy or nginx with TLS. A minimal Caddy block:
cat /etc/caddy/Caddyfile
# books.example.com {
# reverse_proxy localhost:8083
# }
Caddy handles TLS via Let's Encrypt automatically. For nginx, ensure you pass the necessary headers:
location / {
proxy_pass http://127.0.0.1:8083;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Upgrading
cd ~/calibre-web
docker compose pull
docker compose up -d
Configuration and library data live in the mounted volumes, so upgrades are non-destructive. Check the release notes before major version jumps.
Verification
- Library loads: browse to
http://<server-ip>:8083and confirm books appear with covers. - OPDS works: curl the feed — you should get an Atom XML response:
curl -u admin:yourpassword http://<server-ip>:8083/opds - Send-to-Kindle: click Send to Kindle on any book and watch Admin → Task List for a successful conversion and send job.
- Container restarts cleanly:
docker compose restart calibre-web && docker compose ps— status should readUp.
Troubleshooting
"No books found" after library path is set
Confirm the container path (/books) actually contains metadata.db at the root level, not inside a subdirectory. Run docker exec calibre-web ls /books to verify. Also check that PUID/PGID match the file owner on the host with ls -ln /path/to/library.
Send-to-Kindle job fails with conversion error
The universal-calibre mod must be present. Confirm with docker exec calibre-web which ebook-convert. If it returns nothing, remove the container (docker compose down), verify the DOCKER_MODS env line is in your compose file, and bring it back up. First start will re-download the mod.
OPDS returns 401 even with correct credentials
Some OPDS clients send credentials only after receiving a 401 challenge. This is normal. If it loops, check that the user account has the Allow OPDS Access permission enabled under Admin → Manage Users.
Permission denied writing to /books
The container user (PUID/PGID) does not have write access to the host directory. On the host, run sudo chown -R 1000:1000 /path/to/library, adjusting the UID/GID to match your values. Restart the container afterward.
Frequently asked questions
- Can I use my existing Calibre desktop library without copying files?
- Yes. Calibre-Web reads the same metadata.db that Calibre desktop writes. Just mount the existing library directory into the container at /books. Avoid running both Calibre desktop and Calibre-Web in write mode against the same database simultaneously to prevent corruption.
- Why do I need the universal-calibre Docker mod?
- The base Calibre-Web image only ships the Python web app. The mod adds the full Calibre suite (including ebook-convert), which is required for on-the-fly format conversion — for example, converting EPUB to AZW3 before sending to a Kindle address.
- Does OPDS support search and filtering in KOReader?
- Yes. Calibre-Web's OPDS endpoint supports browsing by title, author, series, tags, and shelves, and responds to OpenSearch queries. KOReader can search the catalog directly from the OPDS browser pane.
- How do I restrict users to only certain books or shelves?
- Calibre-Web has per-user permission flags including download, upload, edit, and admin rights, plus the ability to restrict a user to a specific virtual library (defined by a Calibre search expression) via Admin → Manage Users.
- Is it safe to expose Calibre-Web directly to the internet?
- Not on plain HTTP and not without changing the default password. At minimum, put it behind a TLS-terminating reverse proxy and use a strong password. For higher security, add HTTP Basic Auth at the proxy level or restrict access to a VPN, since Calibre-Web's session handling is not hardened for adversarial exposure.
Related guides
Configure Prometheus Alertmanager
Configure Prometheus Alertmanager with routing trees, receivers, inhibition rules, grouping, Go templates, and PagerDuty/Slack on-call integrations.
Build an Intranet Server on Linux
Set up a complete small-office intranet on one Linux box: Nginx web server, dnsmasq local DNS, Samba file sharing, and a Wiki.js team wiki.
Build an nftables Firewall Script
Build a complete nftables firewall from scratch: tables, chains, sets, default-deny input policy, service allowlisting, and persistent systemd configuration.
Caddy as a Reverse Proxy
Set up Caddy as a reverse proxy with automatic HTTPS, load balancing, WebSocket passthrough, reusable snippets, and header control — no certbot required.