# Koodo Reader: a cross-platform ebook manager that syncs through your own cloud accounts

> Koodo Reader is an AGPL-3.0 ebook reader and library manager for Windows, macOS, Linux, Android, iOS and the browser. Its distinguishing choice is that sync runs over storage you already own, and its distinguishing cost is that the server side is a separate, barely documented Go component.

**koodo-reader/koodo-reader** — A modern ebook manager and reader with sync and backup capacities for Windows, macOS, Linux, Android, iOS and Web

- Repository: https://github.com/koodo-reader/koodo-reader
- Website: https://koodoreader.com
- Stars: 28,328 · Forks: 2,117
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/koodo-reader-koodo-reader

## The library problem Koodo Reader picks a side on

Most readers treat the file as the unit of work. You open a book, you close it, the annotation lives inside the file or vanishes. Koodo Reader treats the library as the unit of work: books, reading progress, bookmarks, notes and highlights are one dataset that has to exist on every device you read on. That reframing explains almost every feature in the README, from library snapshots and version control to one-click export of notes in CSV, Markdown, HTML, TXT and PDF.

The target user is someone with a few hundred DRM-free files, at least two devices, and an existing cloud account. The README lists OneDrive, Google Drive, Dropbox, iCloud, MEGA, pCloud, Yandex Disk, Box, FTP, SFTP, WebDAV, SMB and Object Storage as sync and backup targets. That is an unusual list: it includes protocols a self-hoster can run at home, not just consumer file hosts. The trade-off is that you configure and debug the storage yourself. There is no Koodo-operated account holding your library, which the README frames as privacy-first design with no tracking services and no proactive uploading of reading data.

Format coverage is broad rather than deep. EPUB, PDF, DRM-free MOBI and AZW3, TXT, FB2, CBR, CBZ, CBT, CB7, MD, DOCX, HTML, XML, XHTML, MHTML and HTM are all listed. The DRM-free qualifier is the one to read carefully: there is no mention of Adobe DRM or Kindle DRM handling anywhere in the README.

## How the reader, the sync layer and the optional server fit together

The dependency list in package.json is the clearest description of the architecture. better-sqlite3 handles the local store, localforage covers browser persistence, and jszip, yauzl, tar-stream and js-untar unpack the archive-based comic formats. Format conversion is delegated to libraries rather than written in-house: mammoth for DOCX, marked for Markdown, mhtml2html for MHTML, and @mozilla/readability for extracting readable content from web pages. js-mdict handles local MDX dictionary lookup, and the OCR engines named in the README are Paddle and Tesseract.

Sync is not a single protocol but a set of adapters. The same dependency list contains @aws-sdk/client-s3, basic-ftp, ssh2-sftp-client, webdav and megajs. That means each backend is a separate code path with its own authentication and error behaviour, and a failure on WebDAV tells you nothing about whether SMB works. When a sync problem appears, the useful question is which adapter is in play, not whether sync is broken.

The server side is genuinely separate. The Dockerfile copies a pre-compiled Go binary, httpserver, into the image alongside a Caddy web server. Caddy serves the built React app on port 80; the Go binary exposes port 8080 and, per the Dockerfile comment, a KOReader sync server on port 7200. The repository has an httpserver/ directory and a docker-compose-secret.yml alongside the main compose file. Nothing in the README documents the Go server's endpoints, so treat it as a black box whose only documented surface is its environment variables.

## Installing Koodo Reader on desktop, and a first import

The README points desktop, Android and iOS users at the download page, and offers package-manager routes for the desktop builds. On Windows with Scoop, the bucket has to be added before the package name resolves:

```bash
scoop bucket add extras
scoop install extras/koodo-reader
```

Winget, Homebrew, Flathub and Snap are the other documented one-liners, and each names a different package identifier, so copy the one for your platform rather than assuming they match:

```bash
winget install AppByTroye.KoodoReader
brew install --cask koodo-reader
flatpak install flathub io.github.troyeguo.koodo-reader
sudo snap install koodo-reader
```

If you would rather not install anything, the README links a hosted web build, and the browser extension is a separate download for saving pages into the library.

For a first real use, start with a single EPUB rather than a whole shelf. The README describes batch import, but importing one file first tells you whether the reader renders your books the way you expect before you commit a directory. After the file appears in the list, open it and change one display setting: font size, line spacing, margins or background colour are all adjustable, and single-column, two-column and continuous scrolling layouts are available. Then add a highlight and a note, and export notes once to CSV or Markdown to confirm the export path writes a file you can open elsewhere. That sequence exercises import, rendering, annotation and export without touching sync, so if something fails you know which layer it was.

## Self-hosting with Docker, and what the compose file actually exposes

The compose file is short and worth reading before you run it, because the defaults are weak. It maps port 80 and port 8080 to the host, mounts /opt/uploads into the container at /app/uploads, and sets three environment variables with fallback values:

```yaml
services:
  koodo-reader:
    build: .
    container_name: koodo-reader
    restart: unless-stopped
    ports:
      - "80:80"
      - "8080:8080"
    environment:
      - SERVER_USERNAME=${SERVER_USERNAME:-admin}
      - SERVER_PASSWORD=${SERVER_PASSWORD:-securePass123}
      - ENABLE_HTTP_SERVER=false
    volumes:
      - /opt/uploads:/app/uploads
```

The fallback credentials are admin and securePass123, and ENABLE_HTTP_SERVER defaults to false. The Dockerfile sets additional defaults: ENABLE_KOREADER_SERVER=false, ENABLE_KOREADER_REGISTRATION=true, ENABLE_OPDS=false, and SERVER_PASSWORD_FILE=my_secret. Two details matter operationally. First, the Dockerfile exposes port 7200 for KOReader sync but the compose file does not publish it, so KOReader progress sync will not reach the container until you add that mapping. Second, the Dockerfile supports reading the password from a file via SERVER_PASSWORD_FILE, and the repository includes a docker-compose-secret.yml for that pattern. Use it. Putting a password in a compose file that also sets a default is how a reader ends up on an open port.

The build itself is unusual: there is no build stage. The Dockerfile copies a pre-built build/ directory and a pre-compiled httpserver-linux-${TARGETARCH} binary, with a comment stating the React app is built in CI and the Go binary cross-compiled there to avoid QEMU overhead on linux/arm64. That makes the image small and fast to assemble, but it also means building from a source checkout without the CI artifacts will not produce a working image. The README's Docker section is a single link to an external installation guide, so the compose file and Dockerfile are the real documentation.

## Where Koodo Reader is the wrong tool

The clearest limitation is DRM. The README specifies DRM-free Mobipocket and Kindle files, and lists no mechanism for protected content. If your library comes from a store that wraps EPUBs in Adobe DRM, Koodo Reader will not open them, and no amount of configuration changes that.

The second limitation is the server. The Go httpserver is shipped as a binary with environment-variable configuration and no documented API in the README. If you need to script against the library, integrate it into another service, or debug why a sync request failed at the protocol level, you are reading Go source or watching container logs. The README links a document site, but the repository itself does not describe the endpoints.

The third is that sync is only as reliable as the adapter behind it. SMB and SFTP are file protocols, not synchronisation protocols. There is no described conflict-resolution model in the README for the case where two devices edit the same book's notes while offline. Library snapshots and version control are listed as features, which suggests some recovery path exists, but the README does not document rollback or how a snapshot is restored. If you edit annotations on two devices regularly, test that scenario deliberately before trusting it.

Finally, the mobile story is download-only. Android and iOS builds exist, but there is no described app-store-independent update channel beyond the download page, and the browser extension is a separate install. A reader who expects a single account to configure once across six platforms will spend time on each one.

## Koodo Reader versus Calibre, and versus a pure reader

Calibre is the obvious comparison and the approaches differ at the root. Calibre is a desktop library manager whose core is a local database and a conversion pipeline, with a content server bolted on for remote access. Koodo Reader is a reader whose library is designed to be replicated across devices, with conversion delegated to libraries rather than exposed as a pipeline. If your job is converting, deduplicating and fixing metadata across thousands of files, Calibre's tooling has no equivalent here. If your job is reading the same book on a laptop, a phone and a browser with your highlights in the same place, Koodo Reader's sync adapters are the part Calibre does not try to match in the same way.

Against a single-purpose reader such as a plain EPUB viewer, the difference is the annotation layer. A viewer opens a file; Koodo Reader keeps notes, highlights, bookmarks and reading statistics as library data and can push them outward, with the README naming Readwise, Notion, Obsidian and Joplin as sync targets for notes and highlights, plus Anki and Eudic for vocabulary. That export surface is the reason to accept the extra configuration. If you never annotate, you are paying for machinery you will not use.

The KOReader integration is worth separating from the rest. The README says reading progress syncs with KOReader, and the Dockerfile exposes a KOReader sync server on port 7200. That is narrower than full library sync: it is about keeping your position in a book consistent between Koodo Reader and a KOReader device, which matters if you read on an e-ink device and a phone.

## Licence, maintenance and the cost of upgrading

Koodo Reader is licensed AGPL-3.0. The practical consequence is the network clause: if you modify the code and let users interact with it over a network, the licence's terms reach that deployment in a way a permissive licence would not. Running the Docker image for your own reading is not the scenario that clause targets, but shipping a modified Koodo Reader as a service is. This is a description of the licence, not legal advice; read the LICENSE file in the repository for the actual terms.

The project is not archived, and the last push to the dev branch was on 2026-09-20. Releases have been frequent, with v2.4.4 on 2026-09-03, v2.4.3 on 2026-08-01 and v2.4.2 on 2026-07-20, and package.json carries version 2.4.5, which suggests the next release is already staged. The default branch is dev rather than a stable branch, so a source checkout tracks development rather than a release tag. Pin to a release tag if you are building from source.

Upgrade cost is low for the desktop and mobile builds, which are downloaded artifacts. It is higher for the Docker deployment, because the image depends on pre-built CI artifacts and a pre-compiled Go binary for the target architecture. An upgrade means pulling a new image, and a change in the httpserver binary is not something the README will tell you about. If you self-host, keep the compose file and your environment overrides in version control separately from the image tag so you can see what changed when a sync problem appears after an update. The environment variable surface (SERVER_USERNAME, SERVER_PASSWORD, SERVER_PASSWORD_FILE, ENABLE_HTTP_SERVER, ENABLE_KOREADER_SERVER, ENABLE_KOREADER_REGISTRATION, ENABLE_OPDS) is the contract you are actually depending on.

## Conclusion

Adopt Koodo Reader if you read DRM-free files across several devices and want your library synced through storage you already control, such as WebDAV, SMB or an S3-compatible bucket. Skip it if your books are DRM-protected, since the README lists only DRM-free Mobipocket and Kindle support, or if you need a documented server API, because the Docker setup ships an httpserver binary with no published reference. Verify three things before committing: that your target format opens, that your chosen sync backend accepts the connection, and that the AGPL-3.0 obligations are acceptable for how you intend to distribute anything you build on top.

## FAQ

### What is Koodo Reader?

It is a cross-platform ebook manager and reader available for Windows, macOS, Linux, Android, iOS and the web. It stores books, reading progress, notes and highlights as a library that can be synced and backed up to services such as OneDrive, Google Drive, Dropbox, WebDAV, SMB, FTP, SFTP and Object Storage.

### Does Koodo Reader support PDF?

Yes. PDF is listed among the supported formats alongside EPUB, DRM-free MOBI and AZW3, TXT, FB2, CBR, CBZ, CBT, CB7, MD, DOCX, HTML, XML, XHTML, MHTML and HTM.

### Is Koodo Reader open-source?

Yes, it is licensed AGPL-3.0 and the source is in the koodo-reader/koodo-reader repository. The default branch is dev, and the README includes instructions for building the desktop and web versions with yarn.

### How do I install Koodo Reader?

Desktop, Android and iOS builds are downloaded from the project's download page, and the web version runs at the hosted preview URL. Package managers are also supported: Scoop via the extras bucket, Winget as AppByTroye.KoodoReader, Homebrew as the koodo-reader cask, Flathub as io.github.troyeguo.koodo-reader, and Snap as koodo-reader.

### Is Koodo Reader safe?

The README describes a privacy-first design with no tracking services and no proactive uploading of reading data or personal information, and the sync targets are accounts you configure yourself. The Docker defaults in the repository are weak, though: SERVER_USERNAME falls back to admin and SERVER_PASSWORD to securePass123, so change them and prefer SERVER_PASSWORD_FILE before exposing the container.

### Is Koodo Reader free?

The README presents the project as free to download and use across all the listed platforms, with no paid tier described. The source is published under AGPL-3.0, which governs what you may do with modified versions rather than what you pay.

## Sources

- [koodo-reader/koodo-reader on GitHub](https://github.com/koodo-reader/koodo-reader)
- [License: AGPL-3.0](https://github.com/koodo-reader/koodo-reader/blob/dev/LICENSE)
- [Project website](https://koodoreader.com)
- [README](https://github.com/koodo-reader/koodo-reader/blob/dev/README.md)
- [Releases](https://github.com/koodo-reader/koodo-reader/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/koodo-reader-koodo-reader
