Building my own eBook library

Recently, in my efforts to increase how much I read, I recognized a need to level up my eBook game by introducing:

  1. A place to store and organize all my eBooks.
  2. A way to sync reading progress in KOReader across devices.

I didn’t want to rely on Dropbox/Google Drive, buy another subscription or change my field-tested reader app. Instead, I built my own private setup on a cheap VPS.

Here’s how you can do it too. I took some inspiration from Selfhosted eBook Library post, so you might also want to check it out.


The Goal

  • calibre-web → web library for ebooks, including OPDS feed
  • KOReader Sync Server → sync reading progress between devices
  • Nginx + Let’s Encrypt → free SSL certificates and reverse proxy
  • Cheap VPS (mine costs 1€/month + 10€ activation)

Step 1. Install Docker & Docker Compose

On your VPS (I use Ubuntu 24.04) install docker and docker-compose. Test if it works fine:

docker --version
docker-compose --version

⚠️ If you use docker-compose in version 1.29.2, you might experience some issues with ContainerConfig on the restart. I suggest updating the tool.


Step 2. Set Up Docker Compose

Create a docker-compose.yml file, with a configuration similar to:

version: "3.3"

services:
  calibre-web:
    image: linuxserver/calibre-web
    container_name: calibre-web
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Warsaw
      - DOCKER_MODS=linuxserver/mods:universal-calibre
    volumes:
      - ./calibre-web/config:/config
      - ./calibre-web/books:/books
    ports:
      - 8080:8083
    restart: unless-stopped

  koreader-sync:
    image: koreader/kosync:latest
    container_name: koreader-sync
    volumes:
      - ./koreader-sync/data:/var/lib/redis
      - ./koreader-sync/logs/app:/app/koreader-sync-server/logs
      - ./koreader-sync/logs/redis:/var/log/redis
    ports:
      - 17200:17200
    restart: unless-stopped

Start the containers:

docker-compose up -d

Check that the services are running:

docker ps

Step 3. Configure Nginx Reverse Proxy

I was thinking about using Cloudflare Tunnel, I ended up using Nginx as a reverse proxy because it allowed me to keep my domain in the current service. Assuming you create two subdomains for new services:

  • books.domain.com
  • sync.domain.com

Install Nginx:

sudo apt install -y nginx

Create new site configurations (2 of them, one for books, one for sync):

sudo vim /etc/nginx/sites-available/{books,sync}.domain.com

Example configurations (2 separate configuration files) :

server {
    listen 80;
    server_name {books, sync}.domain.com;

    location / {
        proxy_pass http://localhost:{for books: 8080, for sync: 17200};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the sites:

sudo ln -s /etc/nginx/sites-available/{books,sync}.domain.com/etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 4. Secure with Let’s Encrypt

Install Certbot:

sudo apt install -y certbot python3-certbot-nginx

Request certificates:

sudo certbot --nginx -d books.domain.com -d sync.domain.com

Step 5. Test the Setup

For Calibre-Web:

curl -v http://books.domain.com

For KOReader Sync:

curl -k -H "Accept: application/vnd.koreader.v1+json" https://sync.domain.com/healthcheck

Expected JSON response: {"state":"OK"}


Step 6. KOReader configuration

OPDS Catalog

  1. Open KOReader
  2. Tap on the top and then 🔍 icon
  3. On the bottom, tap OPDS catalog
  4. Now, tap on the hamburger icon on the top left corner
  5. Then Add catalog
  6. Fill the details as below
Don’t forget about trailing /. admin/admin123 are default calibre-web credentials.

7. Enjoy the access to your private library of books!

KOReader Sync Server

  1. Open a random book in KOReader
  2. Tap on the top and then 🛠️ icon
  3. Click on Progress sync
  4. Then tap on Custom sync server
  5. Type in the full address: https://sync.domain.com/
  6. Click ok, and then Register/Login button below
  7. Enter your username and password, then tap Register
  8. Repeat this on other devices, but instead of Register, tap Log in.
  9. Configure your sync settings using Periodically sync ever # pages option
  10. When all is configured correctly, when you read book on one device and open the same book on other device, you’ll see a dialog like this:

Step 6. Benefits & Lessons Learned

  • Secure HTTPS via reverse proxy; apps run plain HTTP internally.
  • Cheap & private: only pay for VPS, all data stays under your control.
  • Docker makes management easy: restart, update, or wipe containers without losing data.
  • Let’s Encrypt auto-renews certificates; no manual intervention needed.
  • KOReader progress sync + ebook library is fully functional across devices.

Now you have a fully self-hosted, cheap, and secure ebook library!

Leave a Reply

Discover more from wzieba

Subscribe now to keep reading and get access to the full archive.

Continue reading