Skip to content

Kindle / KOReader Ebook Sync

Last Updated: 2026-08-03 Status: ✅ Active

Purpose

Delivers the Calibre-Web Automated library to a jailbroken Kindle Paperwhite 4 running KOReader, and keeps reading progress in sync across devices. Calibre-Web Automated (CWA) on Lotus is the single source of truth — what reaches the Kindle, how books are named, and how they are grouped are all controlled server-side. No routine administration happens on the Kindle itself.

Location

Server Lotus — calibre-web-automated container
Library path /mnt/user/data/media/books/library/calibre-library
Ingest folder /mnt/user/data/media/books/import/cwa-book-ingest
Local URL http://192.168.1.80:8083
Device Kindle Paperwhite 4, IoT VLAN, 192.168.20.244

The device

Model Kindle Paperwhite 4 (10th gen), i.MX6 SoloLite, 512 MB RAM
Board ID P001F20911120E92
Firmware 5.18.1 — must never be updated
Jailbreak AdBreak (supports 5.18.1 – 5.18.5.0.1)
Reader KOReader v2026.07.1 (kindlehf build)
Recovery kit /mnt/user/backups/kindle/recovery-kit-20260802/ on Lotus

Never let this Kindle take a firmware update

OTA is blocked by renaming /usr/bin/otaupd and /usr/bin/otav3 to .bck (the renameotabin KUAL extension). An Amazon update would remove the jailbreak and there may be no jailbreak for the newer firmware.

How it works

1. What gets sent — the Magic Shelf

The Kindle syncs from a CWA Magic Shelf (id 17, named Kindle), not the whole library:

{"condition": "AND", "rules": [
  {"id": "tag", "field": "tag", "type": "string",
   "operator": "not_in", "value": ["Cookbooks", "Recipes", "Cooking"]}]}

OPDS feed: http://192.168.1.80:8083/opds/magicshelf/17

To stop a book reaching the Kindle, tag it Cookbooks in CWA. Nothing needs doing on the device. Image-heavy cookbooks are excluded because they are large (100 MB+) and render poorly on a 6" e-ink screen.

Magic Shelf feeds are ordered newest-first, which the sync guard depends on.

2. How it arrives — OPDS sync

KOReader's OPDS plugin writes flat into sync_dir, as Author - Title.ext. It does not create folders. The device library is therefore one flat directory of ~570 files, which is deliberate — see "Why flat" below.

Config lives in /mnt/us/koreader/settings/opds.lua:

Field Value
url .../opds/magicshelf/17
username kindle
sync true
sync_dir /mnt/us/books
sync_max_dl 100
last_download href of the newest already-synced book

Triggering a sync: OPDS catalog → long-press the catalogue → Sync. Never Force sync (see Known Issues).

3. How it is found — metadata and collections

Two independent mechanisms:

Sort by → Series reads series metadata from inside the book files. KOReader's crengine understands both calibre:series (EPUB2) and belongs-to-collection / group-position (EPUB3, which Calibre writes). This is automatic and identical on every device, because the metadata travels inside the file.

Collections (/mnt/us/koreader/settings/collection.lua) provide the hierarchy — one tap to a series rather than scrolling a flat list. Currently 46: Reading Now, To Read, Favourites (pinned, orders 1–3), then 43 series collections generated from CWA series data.

Collections are a snapshot — they do not update themselves and must be regenerated after books are added.

4. Reading progress — KOSync

CWA exposes a KOReader sync endpoint at /kosync, enabled by koreader_sync_enabled = 1 in /config/cwa.db. KOReader's cwasync plugin (third-party, not in stock KOReader) authenticates with HTTP Basic using the same kindle credentials, stored in settings.reader.lua.

auto_sync is on, paired with wifi_enable_action = turn_on so it enables Wi-Fi silently rather than prompting.

Documents are matched by file hash

cwasync identifies a book by partial_md5_checksum — a hash of the file bytes. Rewriting book files (e.g. calibredb embed_metadata) changes every document ID and breaks cross-device progress matching. Do metadata work before building up reading history, or accept the reset.

Accounts

User Role Purpose
kindle 258 (Download + Viewer) Device account — OPDS and KOSync
danclark 479 (full) Admin
admin 384 (Viewer + Delete) Deliberately restricted

The device password is stored in cleartext in opds.lua and settings.reader.lua — that is KOReader's design, not a choice. This is why the device account is limited to Download + Viewer. A previous test account had admin rights with the password user1; it was deleted 2026-08-03.

Why flat

The nested Calibre layout (Author/Title (id)/file) is fundamentally incompatible with OPDS sync:

  • Sync writes to sync_dir/Author - Title.ext, flat
  • Its duplicate check (lfs.attributes(item.file)) tests that flat path
  • With a nested tree, every book fails that check and is re-downloaded

Folder-per-shelf is also impossible: sync_dir is a single global setting (OPDSBrowser:getCurrentDownloadDir), so every synced catalogue writes to the same directory regardless of source.

With ~570 books, no folder hierarchy is navigable anyway. Discovery is by search + collections, not by browsing.

Device access

USB networking via usbnetlite:

  1. Unplug the cable
  2. KUAL → USBNetLite → * Toggle USBNetwork *
  3. Plug the cable back in → Kindle appears at 192.168.15.244
  4. Host side needs 192.168.15.201/24
Gotcha Detail
SSH keys Go in /mnt/us/usbnetlite/etc/dropbear/authorized_keyshardcoded in the binary, ignores $HOME and -H
No syslog dropbear has syslog compiled out; auth failures never reach /var/log/messages
Interface name USB gadget MAC is random per boot, so the host interface name changes each time — a NetworkManager profile bound to a fixed ifname silently fails
USB identity In usbnet mode it enumerates as 0525:a4a2 Netchip, not Lab126
USB drive mode Requires exiting KOReader. mass_storage_actions is not available on this device, so there is no in-KOReader shortcut

Never enable 'SSH at boot'

Setting /mnt/us/usbnetlite/auto makes the Kindle enter usbnet mode during boot. This leaves the framework unable to launch Kindlets — KUAL shows a blank screen forever — and dropbear does not start either. It disables the very recovery path it is meant to provide. Tried and reverted 2026-08-03.

Data and backup

What Where Backed up
Book library /mnt/user/data/media/books/library (2.4 GB) Array + pre-change snapshot at /mnt/user/backups/kindle/library-pre-embed-20260803
CWA config /mnt/cache/appdata/calibre-web-automated Appdata backup
Kindle config /mnt/us/koreader, /mnt/us/extensions recovery-kit-20260802/device-config/ on Lotus
Jailbreak toolkit AdBreak, hotfix, KUAL, MRPI, KOReader recovery-kit-20260802/toolkit/ on Lotus

Known issues

KOReader sync-cap bug. fillPendingSyncs advances last_download to the newest feed entry even when the download list was truncated at sync_max_dl. Any bulk addition larger than the cap silently loses the overflow, and sync still reports success. Mitigated by raising the cap to 100, not fixed. After a bulk import, always compare device book count against shelf count.

Never use Force sync. It sets sync_force = true, bypassing both the last_download guard and the per-file duplicate check, re-downloading books already present.

Duplicate scan can wedge CWA. duplicate_scan_frequency was after_import, which triggered a full-library scan on every ingest. Importing 60 books deadlocked the web worker and took Calibre-Web down for ~10 minutes. Now set to manual. See Lessons Learned.

Display modes cause apparent hangs. CoverBrowser's first-run defaults set History and Collections to mosaic_image, which extracts a cover thumbnail per book. On 500+ books on a PW4 the device appears frozen for many minutes. All three display modes are now classic/no-images. These are stored separately — changing the file browser setting does not change History or Collections.

Multi-author naming divergence. KOReader names multi-author books using the last <author> element (Kevin J. Anderson - House Atreides), while books seeded from Calibre use all authors. Both conventions exist on the device. Harmless — search matches either — but exact-filename comparison between device and library will produce false mismatches. Compare by title.

Tailscale cannot work on this device. The kernel has CONFIG_TUN unset, so tailscaled can only run -tun userspace-networking, which gives applications no route to 100.x addresses. Inbound SSH over the tailnet would work; outbound (what sync needs) does not.

Partner note

👤 No partner interaction. If the Kindle stops receiving books it is a convenience issue, not a household outage.