↓ Skip to main content
  1. Posts/
  2. Self-Hosting/

BookLore: A Self-Hosted Library and Reader for Your Book Collection

··1567 words·8 mins· loading · loading · ·
Stilicho2011
Author
Stilicho2011
Writing about homelab, self-hosting, automation and open-source solutions
Table of Contents
Self-Hosting - This article is part of a series.
Part : This Article

If you enjoyed this article, you can support the author by becoming a sponsor on Boosty.

Warning

Unfortunately this article is no longer relevant, since the developer couldn’t handle the criticism and deleted the repository. A similar self-hosted reader and library worth checking out instead is Grimmory, a fork built on the same codebase.

BookLore - a self-hosted library and web reader for your book collection
#

If you have a large collection of ebooks, sooner or later you run into a problem - how do you conveniently store, sort, and read these books. Simply keeping files in folders quickly turns into chaos: it’s hard to find the book you want, there are no covers, no descriptions, and there’s no way to track your reading progress.

That’s exactly the problem dedicated library management apps solve. One such solution is BookLore - a modern, open-source web application that lets you build your own server for storing and reading ebooks.

BookLore is a great fit for:

  • a home server
  • a NAS
  • homelab infrastructure
  • a personal or family library

The app runs in a browser, so you can access your library from a computer, tablet, or smartphone.


What is BookLore
#

BookLore is a Digital Library Server that lets you:

  • store books in one place
  • automatically fetch metadata
  • organize your library by author and genre
  • read books right in the browser
  • track reading progress
  • create book collections
  • support multiple users

Essentially, BookLore turns your server into a personal book-reading service, similar to Kindle Library or Google Books, but fully under your own control.


How BookLore differs from other solutions
#

There are several popular library management apps out there:

  • Calibre-Web
  • Kavita
  • Audiobookshelf

However, BookLore has a number of distinctive features that make it an interesting option for a home server.

Modern interface
#

BookLore offers a modern, minimalist web interface.

Interface advantages:

  • convenient navigation
  • book cards with covers
  • fast library search
  • responsive design
  • dark theme support

The interface works great both on a computer and on mobile devices.

I fully understand that interface design is subjective, but the look is still pleasant.


Automatic metadata fetching
#

After adding books, BookLore can automatically fetch:

  • book title
  • author
  • description
  • cover
  • genres

This lets you quickly get your library in order even if you have hundreds or thousands of books, though naturally there can be issues with Russian-language editions.


Built-in ebook reader
#

One of BookLore’s main advantages is its built-in web reader.

Popular formats are supported:

  • EPUB
  • PDF
  • CBZ (comics)

This means you can read books right in the browser, without downloading them to your device.


Multi-user support
#

BookLore supports multi-user operation.

Each user can:

  • have their own reading progress
  • add books to favorites
  • create collections
  • make bookmarks

This makes the app convenient for a family library or a small community.


Simple installation via Docker
#

BookLore installs easily using Docker, making it an ideal solution for:

  • Proxmox
  • Docker servers
  • NAS
  • a home homelab

Installation takes just a few minutes.


Installing BookLore with Docker Compose
#

The easiest way to deploy BookLore is with Docker Compose.

Step 1. Create a working directory
#

Let’s create a folder for the app:

mkdir booklore
cd booklore

We’ll need two files: docker-compose.yml and an environment variables file.

Step 2. Docker Compose and environment variables
#

docker-compose.yml

services:                               # Section describing services (containers)
  booklore:                             # BookLore service name
    image: booklore/booklore:latest     # BookLore Docker image from Docker Hub (latest tag)
    # image: ghcr.io/booklore-app/booklore:latest
    # Alternative image from GitHub Container Registry (commented out)
    container_name: booklore            # Explicit container name in Docker
    environment:                        # Container environment variables
      - USER_ID=${APP_USER_ID}          # UID the container runs as (file permissions)
      - GROUP_ID=${APP_GROUP_ID}        # GID for files and directories
      - TZ=${TZ}                        # Container timezone
      - DATABASE_URL=${DATABASE_URL}    # Connection URL for the MariaDB database
      - DATABASE_USERNAME=${DB_USER}    # Database username
      - DATABASE_PASSWORD=${DB_PASSWORD} # Database user password
      - BOOKLORE_PORT=${BOOKLORE_PORT}  # BookLore's internal port
    depends_on:                         # Service dependencies
      mariadb:                          # Depends on the mariadb service
        condition: service_healthy      # Start only after the DB healthcheck passes
    ports:
      - "${BOOKLORE_PORT}:${BOOKLORE_PORT}"   # Port mapping: host → container (usually not needed when using Traefik)
    volumes:
      - ./data:/app/data                # BookLore application data
      - ./books:/books                  # Directory with the book library
      - ./bookdrop:/bookdrop            # Folder for automatic book import
    healthcheck:                        # Container health check
      test: wget -q -O - http://localhost:${BOOKLORE_PORT}/api/v1/healthcheck
      # HTTP request to BookLore's built-in healthcheck API
      interval: 60s                     # Interval between checks
      retries: 5                        # Number of attempts before marking the container unhealthy
      start_period: 60s                 # Wait time before checks begin
      timeout: 10s                      # Timeout for a single check
    restart: unless-stopped             # Auto-restart the container (except on manual stop)
    networks:
      proxy:                            # Connect to the external proxy network (Traefik)
    labels:                             # Docker labels for Traefik integration
      - "traefik.enable=true"           # Enable Traefik handling for this container
      - "traefik.http.routers.booklore.entrypoints=web" # HTTP entrypoint (port 80)
      - "traefik.http.routers.booklore.rule=Host(`booklore.domain.ru`)" # Route traffic from the booklore.domain.ru domain to this container
      - "traefik.http.middlewares.booklore-https-redirect.redirectscheme.scheme=https" # Middleware to redirect HTTP → HTTPS
      - "traefik.http.routers.booklore.middlewares=booklore-https-redirect" # Apply the redirect middleware to the HTTP route
      - "traefik.http.routers.booklore-secure.entrypoints=websecure" # HTTPS entrypoint (port 443)
      - "traefik.http.routers.booklore-secure.rule=Host(`booklore.domain.ru`)" # HTTPS route for the same domain
      - "traefik.http.routers.booklore-secure.tls=true" # Enable TLS (HTTPS)
      - "traefik.http.routers.booklore-secure.service=booklore"  # Bind the HTTPS router to the booklore service
      - "traefik.http.services.booklore.loadbalancer.server.port=6060" # BookLore's internal port inside the container
      - "traefik.docker.network=proxy" # Tell Traefik which Docker network to find the container in

  mariadb:                              # MariaDB database service
    image: lscr.io/linuxserver/mariadb:11.4.5
    # MariaDB image from LinuxServer.io (stable and convenient)
    container_name: mariadb             # Explicit container name
    environment:                        # MariaDB environment variables
      - PUID=${DB_USER_ID}              # UID of the owner of the DB files
      - PGID=${DB_GROUP_ID}             # GID of the owner of the DB files
      - TZ=${TZ}                        # Timezone
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}       # DB root user password
      - MYSQL_DATABASE=${MYSQL_DATABASE}       # Name of the database created on first run
      - MYSQL_USER=${DB_USER}       # DB user
      - MYSQL_PASSWORD=${DB_PASSWORD}    # DB user password
    volumes:
      - ./mariadb/config:/config        # Directory with MariaDB data and configuration
    restart: unless-stopped             # Auto-restart the container
    healthcheck:                        # DB availability check
      test: [ "CMD", "mariadb-admin", "ping", "-h", "localhost" ]
      interval: 5s                      # Check interval
      timeout: 5s                       # Check timeout
      retries: 10                       # Number of attempts
    networks:
      proxy:                            # Connect to the proxy network (Traefik)

networks:
  proxy:                                # Define the proxy network
    external: true                      # Network already exists and isn't created by Compose

and the .env variables file

# =========================================================
# 🎯 BookLore - main application settings
# =========================================================
APP_USER_ID=0
# UID of the host user that
# BookLore will run as inside the container.
# Needed for correct volume access permissions.
APP_GROUP_ID=0
# GID of the host group.
# Must match the owner of the data / books / bookdrop directories.
TZ=Europe/Moscow
# Container timezone.
# Used for logs, schedulers, and timestamps.
BOOKLORE_PORT=6060
# Port BookLore listens on inside the container.
# Also used by Traefik as the service's internal port.
# =========================================================
# 🗄️ BookLore connection to the MariaDB database
# =========================================================
DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore
# JDBC connection string for MariaDB:
# - mariadb        → service name in docker-compose
# - 3306           → default MariaDB port
# - booklore       → database name
DB_USER=booklore
# Database user
# BookLore uses to connect to MariaDB.
DB_PASSWORD=ChangeMe_BookLoreApp_2025!
# Database user password.
# ⚠️ MUST be changed in production.
# =========================================================
# 🔧 MariaDB container settings (initialization)
# =========================================================
DB_USER_ID=1000
# UID of the user
# MariaDB writes data to the volume as.
DB_GROUP_ID=1000
# GID of the group for database files.
MYSQL_ROOT_PASSWORD=ChangeMe_MariaDBRoot_2025!
# MariaDB root user password.
# Used only for DB administration.
MYSQL_DATABASE=booklore
# Name of the database that will be
# automatically created on the first run of the MariaDB container.

Initial BookLore setup
#

After the first launch, you need to go through the initial system setup.


Creating the administrator
#

The first time you open the BookLore interface, you’ll be asked to create an administrator account.

You need to provide:

  • a username;
  • a password;
  • an email address (optional).

This user gets full access to the system settings.


Adding a book library
#

The next step is connecting a folder with books.

If you’re using the docker compose example above, the path will be: /books.

After adding the directory, BookLore will begin scanning the library.


Scanning and importing books
#

During scanning, the app automatically:

  • discovers books;
  • extracts metadata;
  • downloads covers;
  • builds the library catalog.

If your library is large, scanning may take some time.


Configuring metadata sources
#

In the settings, you can choose the metadata sources used to look up information about books.

This lets you automatically fetch:

  • descriptions;
  • covers;
  • genres;
  • additional information about the book.

Organizing collections
#

For convenient navigation, you can create book collections.

For example:

  • science fiction;
  • non-fiction;
  • classics;
  • comics;
  • technical books.

Books can be added to collections manually or using tags.


Adding users
#

If several people use the library, you can create additional accounts.

Each user will be able to:

  • read books;
  • save progress;
  • create bookmarks;
  • build their own book lists.

Summary
#

BookLore is a convenient, modern server for managing an ebook library, well suited for a home server or homelab infrastructure.

Key advantages of BookLore:

  • a modern web interface;
  • a built-in ebook reader;
  • automatic metadata fetching;
  • multi-user support;
  • simple installation via Docker.

If you have a large collection of ebooks and want convenient access to it from any device, BookLore is a great solution for organizing your own digital library.

A server like this is easy to deploy on home hardware and gives you a full-fledged alternative to cloud reading services.

Self-Hosting - This article is part of a series.
Part : This Article

Related

Connecting Applications to a Shared PostgreSQL and Learning Basic Maintenance: Part 2

·1929 words·10 mins· loading · loading
The second part of the series on a shared PostgreSQL for a home server. We create a dedicated, minimally privileged user and database in pgAdmin for a specific application, connect Authentik to the shared database instead of its own container, and cover basic maintenance - VACUUM, ANALYZE, REINDEX, and when you actually need to do any of this by hand.