A bug-fix build of Calibre-Web-Automated (CWA). Same data layout, same configuration, same UI. The differences are listed in CHANGES-vs-upstream.md and per release on the Releases page.
Built on Calibre-Web-Automated by @crocodilestick, which is built on Calibre-Web by @janeczku and contributors, which is built on Calibre by @kovidgoyal. Original PR authors are credited by handle on every backport — see full Credits at the bottom.
- image: crocodilestick/calibre-web-automated:latest
+ image: ghcr.io/new-usemame/calibre-web-nextgen:latestdocker compose pull && docker compose up -dLibrary, settings, users, OAuth tokens, and KOReader sync state are preserved. Switching back is the reverse one-line change.
- Bug? File it here.
- Feature idea? Open a request. Anything goes, no checklist required — even half-formed ideas are welcome and help prioritize what to look at next.
- New here? See Quick start below.
- Why this fork exists
- What's included
- Quick start
- Full Docker Compose setup
- First run
- Migrating
- Pair with Shelfmark
- Common configurations
- Troubleshooting
- Differences from upstream
- Contributing
- Credits
CWA has an open PR queue with community-submitted bug fixes that aren't in the latest published image. This build picks the safe ones, ships them in regular releases, and adds fresh fixes for high-impact bugs that don't have an upstream PR yet. Scope is bug fixes; feature work is out of scope.
The data format and configuration are byte-compatible with upstream, so swapping images is reversible and migrations aren't needed in either direction.
Everything CWA has, plus the patches in CHANGES-vs-upstream.md. A representative slice of fixes that are in this build but not in crocodilestick/calibre-web-automated:latest:
- Cover saves from Hardcover, Google Books, iTunes, and Open Library (was returning "not a valid image" since 4.0.6).
- Metadata search and the book-delete button on Safari.
- Generate Kobo Auth Token (was returning a blank page).
- Kobo bookmark sync no longer crashes when the client omits
Location. - Auth check added to 14 admin routes (
cwa_logs,convert,epub_fixer, and others) that previously didn't require admin. - Cover-enforcer shell-injection on filenames containing quotes.
- Reverse proxy: user-profile saves honor the path prefix.
- Docker healthcheck follows the
/ → /login302 instead of failing on it. .cbrand.cbzuse IANA-registered mimetypes in OPDS feeds.- Higher-resolution covers from Google Books, Amazon, and an iTunes-backed fallback for high-DPI e-readers (Libra Color, etc.).
- Translation PRs merged: ja, fr, cs, hu, zh_Hans, zh_Hant, and others.
Requirements: Docker and Docker Compose.
-
Make a folder for your library:
mkdir -p ~/calibre-web/{config,library,ingest} cd ~/calibre-web
-
Save this as
docker-compose.yml:services: calibre-web: image: ghcr.io/new-usemame/calibre-web-nextgen:latest container_name: calibre-web environment: - PUID=1000 - PGID=1000 - TZ=America/New_York # change to your timezone volumes: - ./config:/config # settings, user db, logs - ./library:/calibre-library # books live here - ./ingest:/cwa-book-ingest # drop new books here to import ports: - 8083:8083 restart: unless-stopped
-
Start it:
docker compose up -d
-
Open
http://localhost:8083, log in withadmin/admin123, change the password.
Drop an .epub into ./ingest/ and it will appear in your library within a few seconds.
Files in your library and ingest folders should be owned by your
PUID:PGIDuser (1000 by default), not root. If you've copied books in as root, run once:sudo chown -R 1000:1000 ~/calibre-web.
A more complete compose file, with each option documented:
services:
calibre-web:
image: ghcr.io/new-usemame/calibre-web-nextgen:latest
container_name: calibre-web
environment:
# Match your host user/group so files in your library
# are writable from both the container and the host.
- PUID=1000
- PGID=1000
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- TZ=America/New_York
# Override the in-container port if you need to.
# If set below 1024, also uncomment cap_add below.
- CWA_PORT_OVERRIDE=8083
# Set this if your /config or /calibre-library volumes are
# on an NFS or SMB share. See "Network shares" below.
- NETWORK_SHARE_MODE=false
# If you sit behind multiple proxies (e.g. Cloudflare Tunnel
# then nginx then CWA), set this to the total proxy count so
# session protection sees the right client IP. Default 1.
- TRUSTED_PROXY_COUNT=1
# Optional: Hardcover API token for the Hardcover metadata
# provider. Free; sign up at https://hardcover.app/account/api
# - HARDCOVER_TOKEN=eyJhbGciOiJIUzI1NiI...
volumes:
# Settings, user database, logs. Empty folder for new installs;
# for existing CWA users, point at your existing /config.
- /path/to/config:/config
# Your Calibre library. New install? Use an empty folder and
# CWA will set one up. Existing user? Point at the folder
# containing your metadata.db.
- /path/to/library:/calibre-library
# Drop new books here to import them. WARNING: files in this
# folder are DELETED after processing. Don't point this at a
# folder you also use as long-term storage.
- /path/to/ingest:/cwa-book-ingest
# Optional: bind your existing Calibre plugins folder
# - /path/to/calibre-plugins:/config/.config/calibre/plugins
ports:
- 8083:8083
# Uncomment if CWA_PORT_OVERRIDE is below 1024.
# cap_add:
# - NET_BIND_SERVICE
restart: unless-stopped| Volume | What it is | Notes |
|---|---|---|
/config |
App settings, user accounts, OAuth tokens, KOReader sync state, logs | Empty folder for new installs. Carries over from CWA verbatim. |
/calibre-library |
Books and Calibre's metadata.db |
If empty, CWA creates a fresh library. If multiple metadata.db files exist inside, CWA picks the largest. |
/cwa-book-ingest |
Drop zone for new books | Files here are deleted after processing. Don't park books here long-term. |
Don't nest the binds. All three should be separate top-level folders. Putting
ingestinsidelibraryproduces recursive ingest behavior.
- Open the UI at
http://your-host:8083. - Log in with
admin/admin123. - Change the admin password (Profile → Account).
- Go to Admin → Edit Basic Configuration → Feature Configuration and enable Allow Uploads. Without this, the metadata-fetch and cover-from-URL features can't write to your library.
- Drop a book into your ingest folder. It should appear in the library within a few seconds.
The Admin → Settings panel has many optional toggles (auto-convert formats, automatic backups, EPUB fixer, KOReader sync, OAuth, etc.). The upstream wiki is the source of truth for those; this fork doesn't change them.
One line. Stop the container, swap the image, start it.
- image: crocodilestick/calibre-web-automated:latest
+ image: ghcr.io/new-usemame/calibre-web-nextgen:latestdocker compose pull && docker compose up -dSettings, users, OAuth tokens, and KOReader sync state are preserved. The data format is identical, so reverting is the reverse one-line change.
- Stop your existing Calibre-Web container.
- In the new compose file, point
/configat the same/configfolder you used for Calibre-Web. - Whatever you bound as
/booksin Calibre-Web should be bound as/calibre-libraryhere. - Pick an empty folder for
/cwa-book-ingest(it's CWA-specific; no equivalent in stock CW). - Start the container.
Users, settings, and shelves carry over. The first launch takes a few extra seconds while CWA registers itself with the existing app database.
Shelfmark by @calibrain is a self-hosted book search and request interface. Users search across torrent, usenet, IRC, and direct sources from a single UI; Shelfmark hands the download to your client of choice and drops the finished file straight into the CWA ingest folder, where this build picks it up automatically. Multi-user requests are built in, so you can share an instance with household readers and approve their picks.
Add it alongside calibre-web in the same compose file:
shelfmark:
image: ghcr.io/calibrain/shelfmark:latest
container_name: shelfmark
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- SEARCH_MODE=universal
# Point Shelfmark at CWA's app.db (read-only mount below) so users
# log in to Shelfmark with their existing CWA credentials.
- CWA_DB_PATH=/auth/cw-config/app.db
# Optional: shows a "Library" button in Shelfmark's header that
# links back to this CWA instance.
- CALIBRE_WEB_URL=http://your-host:8083
volumes:
- /path/to/shelfmark-config:/config
# Read-only mount of your CWA config dir for the auth integration.
- /path/to/cwa-config:/auth/cw-config:ro
# Shelfmark's destination folder = CWA's ingest folder.
# Downloads land here and this build ingests them on the next watch tick.
- /path/to/cwa-ingest:/books
# If you use a torrent or usenet client, mount its downloads dir
# at the same path you mounted in the client itself, so Shelfmark
# can locate the completed file.
- /path/to/downloads:/downloads
ports:
- 8084:8084
restart: unless-stoppedAfter Shelfmark starts, open it and pick Settings → Security → Authentication Method → Calibre-Web Database, then Sync from Calibre-Web to import users. The Shelfmark docs cover Prowlarr, qBittorrent, SABnzbd, and IRC source setup.
Shelfmark went into maintenance-only status in May 2026; the v1.3.0 build is stable and the integration with CWA is settled, but new feature work upstream has paused. If you want to pin for reproducibility, use
ghcr.io/calibrain/shelfmark:v1.3.0instead of:latest.
If /config or /calibre-library lives on a network share, set:
- NETWORK_SHARE_MODE=trueThis:
- 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:PGIDafter 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(replaceabcif you've customized the user).
Behind multiple proxies (e.g. Cloudflare Tunnel then nginx then CWA), set the proxy count:
- TRUSTED_PROXY_COUNT=2Without 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 is a free metadata provider. To enable it:
-
Sign up at https://hardcover.app and grab an API token at https://hardcover.app/account/api.
-
Add to your compose env:
- HARDCOVER_TOKEN=eyJhbGciOiJIUzI1NiI...Or paste it into Admin → Edit Basic Configuration → Hardcover API Key in the UI.
-
Restart the container.
Hardcover then appears in the Fetch Metadata modal.
CWA has built-in KOReader progress sync; no separate kosync server is needed.
- In KOReader, install the CWA plugin: visit
http://your-cwa:8083/kosyncfor download and install instructions. - Point the plugin at
http://your-cwa:8083and log in with your CWA username and password. - Read on any device. Progress syncs back to CWA, and from there to Kobo if Kobo sync is enabled.
Matching filenames across devices (OPDS downloads). If you download books to KOReader over OPDS and sync progress by filename across several e-readers, turn on Use server filenames in KOReader's OPDS catalog settings (the checkbox when you add or edit the catalog). By default KOReader names a downloaded file Author - Title.epub from the catalog entry, which differs from the on-disk library name Title - Author.epub and forces a manual rename. CWA already sends the library name in the download's Content-Disposition header; with Use server filenames on, KOReader uses that name, so the file matches your library and your other devices without renaming.
Read your CWA library on a Kobo e-reader, with reading progress syncing both ways. Sync runs against your own server, so your library never leaves your network.
- In Admin → Edit Basic Configuration, turn on Enable Kobo sync.
- Open your user page (Admin → Users → your user, or your own profile) and click Create/View next to Kobo Sync Token. The dialog shows the exact
api_endpoint=line for your account. - Plug the Kobo into a computer over USB and open
.kobo/Kobo/Kobo eReader.confin a text editor. Add or replace theapi_endpoint=line with the one from the dialog, save, and eject the device cleanly. - On the Kobo, sync. Books on your Kobo Sync shelves appear on the device, and progress flows back to CWA.
To confirm the device is reaching your server, watch the logs while you sync — you should see requests to /kobo/<token>/v1/...:
docker logs -f calibre-web 2>&1 | grep /kobo/Behind a reverse proxy (nginx, Nginx Proxy Manager, Caddy, Cloudflare Tunnel)
Kobo devices sync over HTTPS, so the api_endpoint has to be your public https:// address. Put a proxy with a valid certificate in front and point it at the container's plain HTTP port:
- Proxy target is
http://<container-host>:8083. The proxy terminates TLS on 443; the connection from the proxy to CWA stays HTTP. WebSocket support is not needed for Kobo sync. - Generate the token while visiting CWA through the HTTPS address, so the
api_endpoint=line the dialog shows already carries your public hostname. - If you stack proxies (for example Cloudflare Tunnel in front of nginx), set
TRUSTED_PROXY_COUNTto the number of proxies.
nginx buffer sizes (important for Kobo sync)
Kobo's /v1/library/sync response carries large headers (auth, sync tokens, library state). Nginx's default proxy_buffer_size (4 KB) and proxy_buffers (8 × 4 KB) are too small; the response is silently dropped before it reaches the device, and the Kobo shows "Sync failed, please try again" with no error in the CWA log. The nginx error log shows upstream sent too big header while reading response header from upstream. Add these to the location / block proxying CWA:
proxy_buffer_size 32k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;(Larger libraries may need 128k / 4 256k / 256k.) Reload nginx after the change. On Synology DSM, the built-in reverse-proxy GUI doesn't expose these directives — drop a custom config at /etc/nginx/conf.d/http.calibre_web.conf that mirrors the DSM entry plus the buffer lines, then disable the DSM entry. DSM rewrites nginx.conf on reboot, so a Task Scheduler boot-event job that runs nginx -s reload reapplies the custom file. Nginx Proxy Manager users: add the three lines under the proxy host's Advanced tab.
See examples/nginx-reverse-proxy.conf for a complete reference snippet.
If you keep a Kobo account signed in
Signing into a Kobo account, or doing a factory reset, can rewrite the api_endpoint= line back to Kobo's own server, which sends sync to Kobo instead of your library. After signing in, re-check the conf line over USB and set it back if it changed. Many sideloaded setups sign out of the Kobo account so the device stops resetting the endpoint.
To keep the Kobo Store and your library working at the same time, turn on Proxy unknown requests to Kobo Store in Admin → Edit Basic Configuration. With it off (the default), any request CWA doesn't recognize gets an empty response — fine for a sideload-only device, but store features won't load.
Fixed in v4.0.13 and later. If you're still seeing it after upgrading, you probably have root:root-owned book directories from a pre-fix install. Run once:
docker exec calibre-web chown -R abc:abc /calibre-libraryFixed in v4.0.14 and later. Upgrade the image.
Almost always one of these:
- The device isn't reaching your server. The
api_endpoint=line in.kobo/Kobo/Kobo eReader.confmust point at your CWA address (notstoreapi.kobo.com), and that address must be reachable over HTTPS. See Kobo sync. - A Kobo account is signed in and Proxy unknown requests to Kobo Store is off, so the device's store calls get an empty response mid-sync. Turn that setting on, or sign out of the Kobo account on the device.
- Behind a reverse proxy, the proxy can't reach the container. Confirm the proxy target is
http://<host>:8083and that the certificate is valid. - nginx is silently dropping the sync response because its default buffers are too small for Kobo's library-sync headers. The CWA log shows the request arriving but nothing else; the nginx error log shows
upstream sent too big header. Addproxy_buffer_size 32k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k;to the proxy location. See the nginx buffer sizes note in the Kobo sync section.
If your library is on a network share, set NETWORK_SHARE_MODE=true (see above). On local disk, this usually means a previous container shutdown was unclean: restart Docker, then the container.
Set TRUSTED_PROXY_COUNT to match your proxy depth. See Reverse proxy.
Three common causes:
- Files owned by root. Make sure ingest files are owned by your
PUID:PGIDuser. - Watcher missed them. Click the Refresh Library button on the navbar; it does a one-shot scan.
- Format isn't allowed. Check Admin → CWA Settings → Ingest for your allowed formats.
The defaults are admin / admin123 (lowercase). If you've already changed the password and forgotten it: stop the container, delete config/app.db, and restart. This resets the database. User accounts are lost; the library itself is untouched.
Check the issue tracker or open a new issue. Useful information:
- The version:
docker exec calibre-web cat /app/CWA_STABLE_RELEASE - Recent logs:
docker logs calibre-web 2>&1 | tail -50 - What you did and what you expected to happen
| Behavior | Upstream CWA :latest |
This build |
|---|---|---|
| Cover saves from Hardcover/Google Books/iTunes/Open Library | Returns "not a valid image" | Saves and persists |
| Generate Kobo Auth Token | Blank page | Works |
| Safari metadata search | Silent 400 | Works |
| Safari book-delete button | Broken since the Feb-4 commit | Works |
Kobo bookmark sync with missing Location |
Crashes | Tolerates |
/kobo_auth/generate_auth_token IDOR |
Open (any user can mint another user's token) | Closed |
| Reverse-proxy user-profile updates | Drops path prefix | Honors getPath() |
Docker healthcheck on / → /login 302 |
Trips on curl -f |
Uses dedicated endpoint with service health checks |
.cbr / .cbz OPDS mimetypes |
Non-IANA | IANA-compliant |
| Cover resolution on high-DPI readers | Often 290×475 (Hardcover thumbnail) | 1000×1500+ via booster |
Admin routes (cwa_logs, convert, epub_fixer, …) |
14 unauthenticated | All require admin |
| Translations: ja, fr, cs, hu, zh_Hans, zh_Hant | Open in PRs | Merged |
Backports are conservative. Anything that touches auth, schema, or dependencies gets a manual review before merging.
The interface ships with the locales below. Completion is auto-refreshed on every push to main by scripts/generate_translation_status.py; to contribute a translation, edit the .po file under cps/translations/ for your language and open a PR.
| Language | Completion | Strings | Fuzzy |
|---|---|---|---|
| English (source) | 100% | source | — |
Hungarian (hu) |
███████████████████░ 93% |
1615/1744 | 75 |
German (de) |
██████████████████░░ 89% |
1545/1744 | 97 |
French (fr) |
██████████████████░░ 88% |
1542/1744 | 94 |
Japanese (ja) |
██████████████████░░ 88% |
1542/1744 | 220 |
Spanish (es) |
██████████████████░░ 88% |
1541/1744 | 261 |
Slovenian (sl) |
█████████████████░░░ 87% |
1512/1744 | 295 |
Russian (ru) |
██████████████░░░░░░ 72% |
1259/1744 | 444 |
Dutch (nl) |
██████████████░░░░░░ 71% |
1241/1744 | 268 |
Italian (it) |
██████████████░░░░░░ 69% |
1203/1744 | 245 |
Polish (pl) |
██████████████░░░░░░ 69% |
1203/1744 | 250 |
Portuguese (Brazil) (pt_BR) |
██████████████░░░░░░ 69% |
1203/1744 | 377 |
Korean (ko) |
██████████████░░░░░░ 69% |
1197/1744 | 245 |
Chinese (Simplified, China) (zh_Hans_CN) |
█████████████░░░░░░░ 67% |
1169/1744 | 328 |
Arabic (ar) |
████████████░░░░░░░░ 61% |
1058/1744 | 265 |
Portuguese (pt) |
████████████░░░░░░░░ 60% |
1046/1744 | 343 |
Slovak (sk) |
████████████░░░░░░░░ 60% |
1047/1744 | 295 |
Indonesian (id) |
████████████░░░░░░░░ 59% |
1026/1744 | 345 |
Galician (gl) |
████████████░░░░░░░░ 59% |
1024/1744 | 344 |
Chinese (Traditional, Taiwan) (zh_Hant_TW) |
███████████░░░░░░░░░ 56% |
983/1744 | 363 |
Swedish (sv) |
███████████░░░░░░░░░ 55% |
960/1744 | 373 |
Greek (el) |
██████████░░░░░░░░░░ 51% |
896/1744 | 387 |
Czech (cs) |
██████████░░░░░░░░░░ 50% |
876/1744 | 396 |
Norwegian (no) |
██████████░░░░░░░░░░ 49% |
862/1744 | 431 |
Vietnamese (vi) |
█████████░░░░░░░░░░░ 45% |
781/1744 | 357 |
Finnish (fi) |
█████████░░░░░░░░░░░ 43% |
743/1744 | 386 |
Ukrainian (uk) |
████████░░░░░░░░░░░░ 39% |
676/1744 | 372 |
Turkish (tr) |
████████░░░░░░░░░░░░ 38% |
671/1744 | 381 |
Khmer (km) |
██████░░░░░░░░░░░░░░ 32% |
552/1744 | 343 |
- Bug reports: open a bug issue. Reproduction steps, version tag, and a
docker logssnippet help a lot. - Feature requests: open a feature issue. The bar is low — bug reports get prioritized for code work, but feature requests shape what gets looked at when the bug queue is quiet, and they help upstream see what users actually want. Don't worry about whether it's "in scope"; just file it.
- Pull requests: welcome. The merge bar is "doesn't break anything that currently works." Changes touching auth, schema, or dependencies get a closer review. Backports keep the original author's handle in the commit message.
- CWA PR authors with stalled work upstream: if you'd like your PR shipped here too, open an issue or send the PR our way.
Governance: GOVERNANCE.md. Contributing details: CONTRIBUTING.md.
Built on:
- Calibre-Web-Automated (@crocodilestick and contributors) — the core software this build is based on. Original PR authors are credited by handle in every backport commit.
- Calibre-Web (@janeczku and contributors) — the web UI underneath CWA.
- Calibre (@kovidgoyal) — the library underneath all of it.
Every backported patch is credited to its original author by GitHub handle in the commit message and in CHANGES-vs-upstream.md. To support upstream's continued development, @crocodilestick has a Ko-fi.
License: GPL-3.0-or-later. See LICENSE.