Skip to content

Configuration

new-usemame edited this page Jul 9, 2026 · 3 revisions

Common Configurations

Reading-sync setups have their own pages: KOReader Sync and Kobo Sync.


Network shares (NFS, SMB, ZFS)

If /config or /calibre-library lives on a network share, set:

- NETWORK_SHARE_MODE=true

This:

  • Disables SQLite WAL mode (NFS and SMB don't reliably support it; without this you'll see "database is locked").
  • Skips the recursive ownership-fix at startup (slow on NFS, often fails on SMB).
  • Switches the ingest watcher from inotify to polling (network-FS inotify events are unreliable).

Tested and supported. Ingest is a few seconds slower; everything else behaves the same.

If files end up owned by root after a copy: this build chowns files back to your PUID:PGID after each metadata-change cycle, but if you've copied files in as root before upgrading, run once: docker exec calibre-web chown -R abc:abc /calibre-library (replace abc if you've customized the user).


Calibre desktop coexistence

If you want to open the same library in calibre desktop while calibre-web-nextgen is running, set both:

- NETWORK_SHARE_MODE=true
- DESKTOP_COMPAT_MODE=true

By default, calibre-web-nextgen holds a single SQLite connection open for the life of the process. That blocks calibre desktop from opening the library — on calibre 9.9.0 + macOS it crashes without an error dialog. DESKTOP_COMPAT_MODE=true switches to per-request connections so the file lock is released between web requests, letting calibre desktop open the database in the gaps.

Changes you make in calibre desktop (edits, adds, deletes) appear in the web UI on the next page load — no restart needed.

Trade-offs:

  • Each web request pays a small extra overhead to open and close the database connection.
  • If calibre desktop is actively writing when a web request comes in, the request waits up to 60 seconds for the lock. Heavy simultaneous use can slow the web UI.
  • Designed for home-server use where calibre desktop is opened occasionally for bulk edits, not for concurrent heavy use of both.

Calibre plugins (DeDRM and others)

calibre-web-nextgen doesn't ship any Calibre plugins, but it can load ones you install yourself — the same plugin .zip files Calibre desktop uses. This is how you add things like DRM removal (DeDRM, Obok) or .acsm fulfillment (the ACSM Input plugin): you supply the plugins, and they run automatically during ingest, library conversion, and metadata embedding.

  1. Turn the feature on in your compose environment, then restart:

    - CWA_CALIBRE_USER_PLUGINS=true
  2. Copy the plugin .zip files into the plugins folder inside your config volume — from the host that's <your config folder>/.config/calibre/plugins/ (the folder is created automatically once the option is on).

  3. Restart the container again. Each plugin is registered at startup; confirm with:

    docker logs calibre-web 2>&1 | grep "Registered Calibre plugin"
    

Plugins that need keys or an account (DeDRM wants your device keys, ACSM Input wants an Adobe login) keep their settings in files next to the zips. Easiest path: configure the plugin in Calibre desktop on your computer first, then copy its settings files (e.g. plugins/dedrm.json, the plugins/DeACSM/ folder) from your desktop Calibre configuration folder into the same container plugins/ folder and restart.

To add another plugin after the first batch is registered, drop the zip in the same folder and run:

docker exec -e HOME=/config calibre-web /app/calibre/calibre-customize -a "/config/.config/calibre/plugins/<plugin file>.zip"

The feature is off by default because it runs third-party plugin code inside your container — only install plugins you trust, from their official release pages. Which plugins are appropriate to use is your call.


Reverse proxy / Cloudflare Tunnel

Behind multiple proxies (e.g. Cloudflare Tunnel then nginx then CWA), set the proxy count:

- TRUSTED_PROXY_COUNT=2

Without this, CWA may see different client IPs across requests and trigger Session Protection warnings, forcing re-login on every page load. Default is 1.


Hardcover metadata provider

Hardcover is a free metadata provider. To enable it:

  1. Sign up at https://hardcover.app and grab an API token at https://hardcover.app/account/api.

  2. Add to your compose env:

    - HARDCOVER_TOKEN=eyJhbGciOiJIUzI1NiI...

    Or paste it into Admin → Edit Basic Configuration → Hardcover API Key in the UI.

  3. Restart the container.

Hardcover then appears in the Fetch Metadata modal.

If you set the token through the HARDCOVER_TOKEN environment variable, the Hardcover API Key field in the admin UI stays empty — that field only shows a key entered through the UI, and an environment-supplied token is not echoed back into the page. The token still works; Hardcover results appearing in the Fetch Metadata modal confirm it is active.

Clone this wiki locally