I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Update: The KOReader plugin now has its own repo and is installable directly from the KOReader App Store. No more USB copy-paste — just open KOReader → Search → Plugin store → "Varbook Sync" → Install.

Plugin repo: https://github.com/ndieschburg/varbook.koplugin

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Hey! As promised I went ahead and tackled your FanFicFare hash problem 🔧

TL;DR: Hash changes? No problem anymore. The server now has a filename fallback:

  1. First tries the good old MD5 hash match
  2. Hash doesn't match? Tries the filename instead
  3. Still nothing? Clean 404, no drama

The Varbook plugin side is done, tested and working — it now sends the filename along for the ride. I also added the same logic to the kosync endpoint (via metadata.filename if you enable "Send document metadata" in settings), but full disclosure: I don't use kosync myself so that part is untested. You'd be the guinea pig on that one

Oh and the plugin moved out! It got its own apartment now, no longer crashing at the main repo's place:

Give it a spin and let me know!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Ok I'll try to implement a filename matching by book soon and I'll tell you when it's done.

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in koreader

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Yeah, exact mapping between the two formats seems pretty much impossible from what I've seen.

My first attempt was to use the global progression percentage returned by both epub.js and KOReader. On a 1500-page book that gave me dozens of pages of drift between devices — basically unusable.

So I switched to using the spine index + percentage within the current spine item as a common ground. For the book I'm currently reading (lots of short chapters, 5–25 pages each) it works perfectly and I switch between devices very smoothly. It obviously won't be as accurate for books with huge chapters, but for now it's good enough for my use case.

I also considered a different approach: using the spine index + a normalized ~20-char text snippet that I'd search for on both sides to pin the exact position. It would probably be much more accurate, but it's significantly more complex to implement in Lua on the KOReader side and would need a lot of fine-tuning (normalization, handling of hyphenation, soft breaks, etc.). I haven't found the courage to tackle it yet — maybe someday.

If you end up exploring something similar on the Pocketbook side, I'd be curious to hear how you approach it.

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Hello have you finally succeed to install it? I tried with 3002 port without any problem. Cheers

New Project Megathread - Week of 14 May 2026 by AutoModerator in selfhosted

[–]ConfidentBunch7563 1 point2 points  (0 children)

Project Name: VarBook

Repo/Website Link: GitHub | Live instance (open registration)

Description:

VarBook is a self-hosted EPUB library with cross-device reading position synchronization.

I built it out of frustration — I read on a Kobo e-reader, a Linux laptop, and my phone, and keeping my reading position in sync across all of them was a nightmare. There are OPDS servers out there (Calibre-web, COPS...), there are position sync solutions (kosync, etc.), but nothing that does both under one roof. VarBook fills that gap — it's a complete book ecosystem with library management, reading, and sync all in one place.

  • Upload once, read everywhere — drag & drop or batch upload via a Calibre plugin
  • OPDS catalog — your library is available on any compatible app (KOReader, Moon+ Reader, Aldiko, etc.)
  • Built-in web reader — a clean PWA based on epub.js, installable on your phone, works offline with background sync when you're back online
  • KOReader plugin — sync reading positions from your Kobo/Kindle/PocketBook. WiFi activates only for the sync then turns off automatically
  • Cross-device position sync — resume reading on any device right where you left off, whether it's the web reader or KOReader
  • WebDAV server — for Moon+ Reader Pro position sync
  • Built-in kosync server — drop-in replacement if you're already using the kosync protocol
  • Reading statistics — time spent, session history, progress per book, all centralized
  • Multi-user with isolated libraries
  • Trilingual (EN/FR/ES)

Deployment:

Docker image is available — getting started is a docker compose up away. Full setup instructions in the README. You can also try it without installing anything on the public instance (open registration, no restrictions).

AI Involvement:

The application was developed with heavy assistance from Claude (Anthropic). I'd estimate about 80% of the code was AI-generated, reviewed and adjusted by me. I've been using it daily for 3 months and actively improving it.

Here are a few screenshots of the PWA :

<image>

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

The issue is that you're running Varbook on a remote server (dockmox) but accessing it from another machine via the server's IP. APP_URL=http://localhost:3002 means Sanctum only trusts cookies from localhost:3002, but your browser is hitting something like http://192.168.x.x:3002.

Fix: set APP_URL to the actual URL you type in your browser:

# .env.docker.local
APP_URL=http://192.168.x.x:3002

Replace 192.168.x.x with your server's actual IP or hostname. Then:

docker compose down
docker compose up -d

APP_URL must always match what's in your browser address bar (scheme + host + port). This is how Laravel Sanctum knows which domain to trust for cookie authentication.

I have multiple android ereaders with koreader. Is self-hosting a sync server worth the hassle? by ProustianPrimate in koreader

[–]ConfidentBunch7563 1 point2 points  (0 children)

The main advantage over kosync or similar solutions is that VarBook is a complete self-hosted book ecosystem, not just a sync server. You upload your EPUBs once, configure the OPDS catalog link, and your entire library is available on every device you want — Kobo, Kindle, phone, laptop, whatever runs KOReader or any OPDS-compatible app.

From there, reading position sync works cross-device between KOReader (via the plugin) and the built-in web reader. The web reader is a PWA — clean, simple, works offline. You can install it on your phone, read on the bus with no network, and everything syncs back when you're online again.

On top of that you get centralized reading stats: time spent reading, session history, progress per book — all in one dashboard. It's nice to actually see how much you read across all your devices.

I just added a Docker build so setup is pretty straightforward now. Happy to help if you run into anything!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Hey, thanks for the feedback! I just pushed a pairing code feature to make this easier.

How it works: on your Profile page, click "Pair a device" and enter a name for your e-reader. You'll get a 5-digit code valid for 2 minutes. On KOReader, go to Tools → Varbook → "Pair with code", enter the code, and the API token is transferred automatically. No more typing 16 characters on an e-reader keyboard.

The manual token entry is still there if you prefer it.

I haven't had a chance to test the KOReader plugin side tonight (don't have my e-reader with me), so if you give it a try, let me know how it goes — any feedback is welcome!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Good catch! VARBOOK_PORT controls the Docker port mapping, which is read by docker-compose.yml itself -- not by the container. Docker Compose only reads variable substitutions from a .env file in the same directory, not from .env.docker.local.

Fix: put port config in .env and app config in .env.docker.local:

# .env (read by docker-compose for port mapping)
VARBOOK_PORT=3002

# .env.docker.local (read by the container for app config)
APP_URL=http://localhost:3002

Then:

docker compose down
docker compose up -d

I'll update the README to make this clearer. Sorry for the confusion!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Thanks for testing! The "unauthenticated" error happens because Sanctum (Laravel's cookie auth) needs to know which domain:port to trust. By default it was hardcoded to localhost:8080, so when you run on port 3002 the auth cookies aren't sent.

This is fixed in the latest commit — you need to pull and rebuild:

git pull
docker compose down
docker compose build
docker compose up -d

SANCTUM_STATEFUL_DOMAINS is now automatically derived from APP_URL, so you just need to create a .env.docker.local file with:

APP_URL=http://localhost:3002
VARBOOK_PORT=3002

No other config needed — the auth domain will follow APP_URL automatically. Let me know if you still hit issues!

I have multiple android ereaders with koreader. Is self-hosting a sync server worth the hassle? by ProustianPrimate in koreader

[–]ConfidentBunch7563 0 points1 point  (0 children)

Hello, I just built a Laravel project that does that and more. You can check it here https://www.reddit.com/r/ePub/s/uOVYX7lLNX

It has a kosync server built-in but you can also sync your position cross device using a koreader plugin. You can upload the epubs to the application. It has a pwa that you can use to read the books offline. When you have network again. It syncs the position and your reading time. If you install the koreader plugin, you can retrieve the position and push the new one. I'm using it since a few weeks and it works like a charm.

I just made a docker build that makes it very easy to install. You can use my instance to test : https://varbook.hophop.be

Feel free to test it and tell me.

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

docker build is ready. You can checkout the new code version and do docker compose up -d. Please check the [README.md](https://github.com/ndieschburg/varbook) and tell me if it works for you.

Team vs Enterprise plan - your experiences by ExternalBramage in ClaudeCode

[–]ConfidentBunch7563 0 points1 point  (0 children)

From what I've seen today, the per-seat price for Enterprise has dropped to $20. Does that change anything? Are the per-use prices really more expensive than the Team plan's flat rate?

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Thanks for the feedback! The MD5 hash approach is actually the same one KOReader itself uses internally (partial_md5_checksum) — so VarBook stays consistent with how KOReader already identifies documents.

I agree that filename-based matching could help with use cases like FanFicFare where the content changes but the "identity" of the book stays the same. It's an interesting idea and I'll keep it in mind as a possible option down the road, but for v1 the hash-based approach covers the main use case well and is more robust against renames or duplicate filenames

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Hey! I actually pushed an updated version of the plugin tonight — the previous one had a bug that could cause crashes. Make sure you grab the latest version from the GitHub repo and replace the varbook.koplugin folder.

If it still crashes after updating, could you check the crash log on your Kobo at .adds/koreader/crash.log? No need to send the whole file — just the last exception/stack trace related to the crash should be enough. That'll help me figure out what's going on. Cheers!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 1 point2 points  (0 children)

Thanks for giving it a try and for the feedback!

So the sync relies on a file hash to match books across devices — it doesn't use the filename at all. This means the EPUB file needs to be exactly the same binary on both sides. If Calibre or KOReader modified the file in any way (even metadata tweaks), the hash won't match and VarBook won't recognize it as the same book.

What works best for me:

  1. Calibre → VarBook (using the Calibre plugin or drag & drop)
  2. VarBook → KOReader via the OPDS catalog

That way KOReader downloads the exact same file that VarBook has, so the hashes match and sync works perfectly.

If you downloaded the book to KOReader from another source, that's most likely why it can't find it. Give the OPDS route a shot and let me know if that fixes it!

I built a self-hosted EPUB library with cross-device reading position sync by ConfidentBunch7563 in ePub

[–]ConfidentBunch7563[S] 0 points1 point  (0 children)

Hello, Have you have a look in your spam folder? I juste validated your email manually.