r/Saudi_Homelab

Image 1 — The Ultimate Guide for EPUB & Audiobooks Self-Hosting
Image 2 — The Ultimate Guide for EPUB & Audiobooks Self-Hosting
Image 3 — The Ultimate Guide for EPUB & Audiobooks Self-Hosting
Image 4 — The Ultimate Guide for EPUB & Audiobooks Self-Hosting
Image 5 — The Ultimate Guide for EPUB & Audiobooks Self-Hosting
▲ 995 r/Saudi_Homelab+3 crossposts

The Ultimate Guide for EPUB & Audiobooks Self-Hosting

Hey y’all! I’ll keep updating this until I’m satisfied with it. :)

Why did I create this post?

Well, I kinda spent a whole week setting up my self-hosted reading stack, and I thought this might save people some time and be a good starting point for anyone looking into building something similar.

What is this, and what’s the workflow?!

First: Server-side

This guide will take you through a full self-hosted reading stack using:

  1. BookOrbit https://github.com/bookorbit/bookorbit
  2. BookBridge https://github.com/cporcellijr/bookbridge
  3. Storyteller https://storyteller-platform.dev/docs/installation/self-hosting
  4. Audiobookshelf (ABS) https://github.com/advplyr/audiobookshelf
  5. Double Commander https://github.com/linuxserver/docker-doublecommander

Second: Client-side

This will guide you through:

  1. Installing KOReader on your Kindle/Kobo
  2. iOS/android phone/tablet apps: BookOrbit, Storyteller, and Prologue
  3. Read-aloud books
  4. Apple Watch

How everything fits together

                         SELF-HOSTED READING STACK
                         =========================

                                YOUR BOOK
                         EPUB + AUDIOBOOK/M4B
                                  |
                                  |
                                  v
                    +---------------------------+
                    |         BOOKORBIT         |
                    |                           |
                    | Main library / metadata   |
                    | EPUBs + M4B + Read-Aloud  |
                    | Web reader / player       |
                    +---------------------------+
                        |          |          |
                        |          |          |
              EPUB + M4B|          |          | BookOrbit library
                        |          |          |
                        v          |          v
              +----------------+   |   +--------------------+
              |  STORYTELLER   |   |   |   DOUBLE COMMANDER |
              |                |   |   |                    |
              | Creates synced |   |   | Creates hardlinks  |
              | Read-Aloud EPUB|   |   | without duplicating|
              +----------------+   |   | the actual data    |
                        |           |   +--------------------+
                        |           |              |
                        |           |              | Hardlink
                        |           |              v
                        |           |     +-------------------+
                        |           |     |  AUDIOBOOKSHELF   |
                        |           |     |       (ABS)       |
                        |           |     |                   |
                        |           |     | Audiobook library |
                        |           |     | M4B conversion    |
                        |           |     +-------------------+
                        |           |              |
                        |           |              |
                        +-----------+--------------+
                                    |
                                    v
                         +----------------------+
                         |      BOOKBRIDGE      |
                         |                      |
                         | Syncs reading/listen |
                         | progress between     |
                         | different formats    |
                         +----------------------+


                              CLIENT DEVICES
                              ==============

        +------------------+       +-------------------------+
        | Kindle / Kobo    |       | iPhone / iPad           |
        |                  |       |                         |
        | KOReader         |       | BookOrbit App           |
        | BookOrbit Plugin |       | Storyteller App          |
        +--------+---------+       | Prologue -> ABS          |
                 |                 +------------+------------+
                 |                              |
                 +--------------+---------------+
                                |
                                v
                 Read the same library everywhere
                 with progress/highlights syncing
                 where supported.

Workflow

BookOrbit

BookOrbit will be your main library manager.

This is where I keep my EPUBs, audiobooks, and Read-Aloud books. It can fetch metadata and covers when needed, and it can automatically process files dropped into its Book Dock folder.

It can also act as a web reader and audiobook player.

Install the BookOrbit app on your iPhone/iPad and you can read books, listen to audiobooks, and use Read-Aloud books directly from your phone.

Install the BookOrbit plugin on your Kindle/Kobo running KOReader and you can browse your library directly from your e-reader, download books, and sync things like reading progress, highlights, annotations, and reading stats back to your BookOrbit server.

Pretty cool! ...

Warning! as i was informed by people in this thread that the dev of bookorbit had previously developed an app called booklore and that app was mainly AI slob with no one steering so i just want people to know! ill still continue using bookorbit as no other bookmanager yet have all the features of bookorbit! to know more booklore

BookBridge

Let’s say you have three versions of the same book:

  • EPUB
  • Audiobook
  • Read-Aloud book

You might read the EPUB on your e-reader, then later want to continue by listening to the audiobook on your phone, then later switch to the Read-Aloud version.

Normally, every time you switch formats you would have to manually find where you left off.

BookBridge solves this.

It aligns the ebook and audiobook so progress can be translated between the different formats.

So you can stop reading on your e-reader, pick up your phone later, start the audiobook, and continue around the same point — and vice versa.

It uses a small local model during the initial processing/alignment of the book, rather than needing to continuously process it while you read.

Storyteller

Storyteller creates a Read-Aloud EPUB.

This is basically an EPUB containing the text of the book together with its audiobook narration. While the narration plays, the corresponding text can be highlighted and followed along with.

These Read-Aloud books are also supported by BookOrbit, so you can store and use them as part of the same library.

Storyteller works with EPUB 3 for this process. If the book you have is EPUB 2, Storyteller can convert it to EPUB 3 first.

It also performs the initial alignment between the EPUB text and audiobook when creating the Read-Aloud edition.

Audiobookshelf

Audiobookshelf (ABS) is another book/audiobook manager.

Honestly, if you are already running BookOrbit, you might not need ABS at all.

I personally keep it in my stack for two main reasons:

  1. It has very good audiobook conversion tools. For example, it can take a folder containing multiple MP3 files and convert them into a single clean M4B audiobook with chapters.
  2. I like some of the dedicated audiobook clients that work with ABS, especially Prologue on iPhone.

Double Commander

We will also run Double Commander, which is basically a file manager for power users.

I mainly use it because it provides an easy GUI for creating hardlinks.

Why is that useful?

We are running two book managers: BookOrbit and Audiobookshelf.

I don’t want to copy the same 1 GB audiobook twice (and those are expensive with all the AI shenanigan):

BookOrbit library -> 1 GB

AND

Audiobookshelf library -> another 1 GB

That would waste storage space.

Instead, we can create a hardlink.

A hardlink is not really a shortcut. Both filenames point to the same underlying file data/inode on the filesystem.

So you can have something like:

/books/bookorbit/Author/Book/Book.m4b

/books/audiobookshelf/Author/Book/Book.m4b

Both appear to be normal files to their respective applications, but the audiobook data is only stored once on disk.

Deleting one hardlink does not delete the actual data as long as another hardlink to that file still exists.

This is extremely useful when multiple self-hosted applications need to see the same large media files.

Docker

I’m going to provide example Docker Compose YAML for all the services mentioned above.

You should edit the paths, user IDs, passwords, domain names, timezone, etc. for your own setup.

Hopefully these examples make getting started easier. Obviously I can’t provide an example for every possible configuration.

My own server runs TrueNAS Community Edition and I use Arcane as my Docker manager, but the examples below are intentionally generic so they can be adapted to other Docker setups.

A few things before we start

You will often see something like:

PUID: 1000
PGID: 1000

or: user: "1000:1000"

 

These control what Linux user/group the container runs as.

You need to change these values to match the user that owns or has permission to access your media directories.

You can normally check your user with:

id

For example:

uid=1000(username) gid=1000(username)

would normally mean:

PUID: 1000
PGID: 1000

for my own setup i use 568 becuase truenas app preset is 568 if you run TN then opt for 568 not 1000

Make sure the containers that need to share/write the same files have compatible permissions.

2. Comments in YAML

Anything after # is a comment.

For example:

TZ: Etc/UTC # Change this to your timezone

Docker Compose ignores everything after the #.

You can use comments to leave yourself notes or temporarily disable lines.

 

3- you may see in some yaml that I use https://book.mydomain.com you will want to do something similar if you wanna read or listen remotely the way I do it in my server I run cloudflare tunnel and nginx reverse proxy and you need to buy a cheap domain like 1$ a year (there are a lot of tutorial in doing something like that and its out the scope of this guide)

 

4- you will see in some example (# use for POSTGRES_PASSWORD # run openssl rand -hex 24) you would wanna run that in terminal or shell to generate random passphrase then copy that and paste it where its needed

For example

openssl rand -hex 24

 

openssl rand -hex 32

HERE WE GO :) :) :)

BookOrbit

-----------------------------------------------------------------------

services:
  bookorbit:
    image: ghcr.io/bookorbit/bookorbit:latest
    container_name: bookorbit-app
    restart: unless-stopped
    init: true

    ports:
      - "3000:3000"

    environment:
      NODE_ENV: production
      PORT: 3000

      # Public URL through your reverse proxy.
      # Replace with your own domain.
      APP_URL: https://books.example.com
      CLIENT_URL: https://books.example.com

      # PostgreSQL
      POSTGRES_HOST: bookorbit-db
      POSTGRES_PORT: 5432
      POSTGRES_USER: bookorbit

      # Generate with run this in shell/terminal:
      # openssl rand -hex 24
      POSTGRES_PASSWORD: CHANGE_ME_POSTGRES_PASSWORD

      POSTGRES_DB: bookorbit

      # Security
      # Generate with run this in shell/terminal:
      # openssl rand -hex 32
      JWT_SECRET: CHANGE_ME_JWT_SECRET

      # Generate with run this in shell/terminal:
      # openssl rand -hex 16
      SETUP_BOOTSTRAP_TOKEN: CHANGE_ME_BOOTSTRAP_TOKEN

      # Change these to match your media permissions
      PUID: 1000
      PGID: 1000

      # Change to your timezone
      TZ: Etc/UTC

      # Start BookOrbit's library browser here
      LIBRARY_BROWSE_ROOT: /books

      # Automated ingest staging area.
      # Drop files here for BookOrbit to process them.
      BOOK_DOCK_PATH: /data/book-dock

      # Container-aware memory sizing
      NODE_MAX_OLD_SPACE_SIZE: auto

      # Encrypt stored SMTP credentials if configured
      # EMAIL_ENCRYPTION_KEY:

      # Keep normal username/password login enabled
      DISABLE_LOCAL_AUTH: "false"

    depends_on:
      bookorbit-db:
        condition: service_healthy

    volumes:
      # BookOrbit-owned books and audiobooks
      - /mnt/path/to/books/bookorbit:/books

      # BookOrbit application state
      - /mnt/path/to/bookorbit/app:/data

    read_only: true

    tmpfs:
      - /tmp

    cap_drop:
      - ALL

    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - FOWNER
      - SETGID
      - SETUID

    security_opt:
      - no-new-privileges:true

    stop_grace_period: 30s

    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"


  bookorbit-db:
    image: pgvector/pgvector:pg18
    container_name: bookorbit-db
    restart: unless-stopped

    environment:
      POSTGRES_USER: bookorbit

      # MUST match POSTGRES_PASSWORD above
      POSTGRES_PASSWORD: CHANGE_ME_POSTGRES_PASSWORD

      POSTGRES_DB: bookorbit
      PGDATA: /var/lib/postgresql/data/pgdata

    volumes:
      - /mnt/path/to/bookorbit/postgres:/var/lib/postgresql/data

    healthcheck:
      test:
        - CMD-SHELL
        - 'pg_isready -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}"'
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 20s

    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

BookBridge

Change 1000:1000 to the UID/GID used by your media files.

The BookOrbit library is mounted as read-only using :ro.

services:
  bookbridge:
    image: ghcr.io/cporcellijr/bookbridge:latest
    container_name: bookbridge

    user: "1000:1000"

    ports:
      - "5757:5757"

    environment:
      TZ: Etc/UTC
      LOG_LEVEL: INFO

      # Make runtime caches writable by the container user
      HOME: /data
      XDG_CACHE_HOME: /data/.cache
      HF_HOME: /data/huggingface

    volumes:
      # BookBridge application data/cache
      - /mnt/path/to/bookbridge/data:/data

      # Existing BookOrbit library
      - /mnt/path/to/books/bookorbit/books:/books:ro

    restart: unless-stopped

Storyteller

After deploying Storyteller, you need to create a secret key.

You can generate one with:

openssl rand -base64 32

Then place the generated key inside a text file named:

STORYTELLER_SECRET_KEY.txt

For example:

/mnt/path/to/storyteller/STORYTELLER_SECRET_KEY.txt

The Docker Compose configuration can then expose that file to Storyteller as a Docker secret.

services:
  storyteller:
    image: registry.gitlab.com/storyteller-platform/storyteller:latest
    container_name: storyteller
    restart: unless-stopped

    ports:
      - "8001:8001"

    volumes:
      # Storyteller application data/database/transcriptions/cache
      - /mnt/path/to/storyteller/data:/data:rw

      # Writable Next.js cache
      - /mnt/path/to/storyteller/next-cache:/app/.next/standalone/applications/web/.next/cache:rw

      # Existing BookOrbit library containing EPUB + M4B
      - /mnt/path/to/books/bookorbit/books:/library:rw

    environment:
      - STORYTELLER_SECRET_KEY_FILE=/run/secrets/secret_key

      # Change these to match your media permissions
      - PUID=1000
      - PGID=1000

      # Logging level
      - STORYTELLER_LOG_LEVEL=info

    secrets:
      - secret_key


secrets:
  secret_key:
    file: /mnt/path/to/storyteller/STORYTELLER_SECRET_KEY.txt

Audiobookshelf

Notice that the audiobook directory below ends with:

:ro

That means read-only.

Audiobookshelf can read the audiobook files but cannot modify or delete them through this mount.

I do this because my Audiobookshelf library contains hardlinks to the BookOrbit library and I prefer BookOrbit to be the main owner/manager of those files.

Audiobookshelf can still keep its own database, metadata, covers, progress information, etc. inside /config and /metadata.

 

-----------------------------------------------------------------------

services:
  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf

    ports:
      - "13378:80"

    environment:
      TZ: Etc/UTC

    volumes:
      # Audiobookshelf configuration
      - /mnt/path/to/audiobookshelf/config:/config

      # Audiobookshelf metadata
      - /mnt/path/to/audiobookshelf/metadata:/metadata

      # Audiobooks
      # :ro = read-only
      - /mnt/path/to/books/audiobookshelf/audiobooks:/audiobooks:ro

      # Podcasts
      - /mnt/path/to/books/audiobookshelf/podcasts:/podcasts

    user: "1000:1000"

    restart: unless-stopped

Double Commander

Double Commander needs access to the common parent directory containing both libraries so you can easily work between them.

For example:

/mnt/path/to/books/
├── bookorbit/
└── audiobookshelf/

Compose:

 

-----------------------------------------------------------------------

services:
  doublecommander:
    image: lscr.io/linuxserver/doublecommander:latest
    container_name: doublecommander

    environment:
      PUID: "1000"
      PGID: "1000"
      TZ: Etc/UTC

    volumes:
      # Double Commander configuration
      - /mnt/path/to/doublecommander/config:/config

      # Parent directory containing your book libraries
      - /mnt/path/to/books:/books

    ports:
      # Optional additional port depending on your setup:
      # - "3000:3000"

      - "3002:3001"

    shm_size: "1gb"

    restart: unless-stopped

How to create a hardlink in Double Commander

Open your BookOrbit directory in one panel.

For example:

/books/bookorbit/

Open your Audiobookshelf directory in the other panel:

/books/audiobookshelf/

Select the EPUB or audiobook you want to link, then choose:

File -> Create Hard Link

You should immediately see the new file appear in the opposite directory.

The two filenames now point to the same underlying file data, so you have not duplicated the audiobook or ebook.

IMPORTANT

Hardlinks can only be created when both locations are on the same filesystem.

If you use ZFS, this generally means they must also be inside the same ZFS dataset.

For example, this can work:

Dataset: books

books/
├── bookorbit/
└── audiobookshelf/

But if bookorbit and audiobookshelf are two separate ZFS datasets/filesystems, you cannot hardlink a file between them.

Second Part: Client-side

1. Kindle / Kobo + KOReader

KOReader is an amazing open-source reading application.

For Kindle, you generally need to jailbreak the device before installing KOReader.

This is an amazing community resource that makes the Kindle process much easier:

https://kindlemodding.org/jailbreak-wizard.html

Kobo devices have their own KOReader installation methods https://github.com/koreader/koreader/wiki/Installation-on-Kobo-devices. i recommend the manual method https://github-wiki-see.page/m/koreader/koreader/wiki/Installation-on-Kobo-devices

Once KOReader is installed, you can also install/configure the BookOrbit integration and access your self-hosted library from the e-reader.

2. iOS clients

The main apps I use are:

BookOrbit
Storyteller
Prologue

Install them on your iPhone/iPad and connect them to the corresponding services on your server.

My general setup is:

BookOrbit App
      |
      +--> BookOrbit server
      |
      +--> EPUB / Audiobook / Read-Aloud


Storyteller App
      |
      +--> Storyteller server
      |
      +--> Read-Aloud books


Prologue
      |
      +--> Audiobookshelf
      |
      +--> Audiobooks

3. Read-Aloud

Both the BookOrbit app and Storyteller app support the Read-Aloud workflow.

I personally prefer the Storyteller app for this.

4. Apple Watch

I’ll add more details about my Apple Watch setup here later as I continue updating this guide.

 

That’s the stack!

The idea is basically:

BookOrbit      = Main book library
BookBridge     = Progress synchronization between formats
Storyteller    = EPUB + audiobook -> Read-Aloud book
Audiobookshelf = Dedicated audiobook tools/clients
DoubleCommander = Easy hardlink management

KOReader       = E-reader client
BookOrbit App  = General mobile reading/listening
Storyteller    = Read-Aloud client
Prologue       = Audiobook client

There are obviously many different ways to build a self-hosted reading setup, but this is the workflow that works for me.

I’ll keep updating the guide as I improve my own stack or find better ways of doing things.

 

--------------------------------------------------------------------------------------------

if you use NGINX ABS require also "Custom Nginx Configuration"

ABS:

-----------

client_max_body_size 10240M;

proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

proxy_redirect http:// https://;

---------

u/Foreignwelcome2 — 13 days ago

افضل تطبيقات Clients Jellyfin

بعد خبره عتيقه سنين مع جيليفن، بحط افضل تطبيقات Clients ممكن تربطها مع مكتبتك على كل نظام تشغيل:

IOS وتطبيقات ابل بشكل عام:
1- Zuno (عظيم جدا وافضل مارأيت، لكن التجربه محدوده بدون اشتراك)
2- Swiftly (جميل وبسيط وواضح وبدون تعقيد)
3- Moonfin (جيد، مجاني، يسمح لك تحمل مع الترجمه الخارجيه)
4- Jellyfin (جيد جدا، لكن مشكلته مايسمح لك تحمل الترجمه الخارجيه اذا حملت شي معين)

Android:
1- Moonfin (جيد، مجاني، يسمح لك تحمل مع الترجمه الخارجيه)
2- Jellyfin (ادائه جيد جدا على الاندرويد، لكن مايدعم تحميل الترجمه الخارجيه)

LG webos:
1- Litefin (ممتاز وخفيف، لكن لازم تحمله عن طريق homebrew)
2- Jellyfin (للاسف ادائه سيئ، على تلفزيونات ال جي، حتى لو كان التلفزيون فئه ممتازه، المشكله بالنظام حق ال جي الزباله)

Android tv (google tv)
1- Wholphin (الافضل على تلفزيونات اندرويد بدون منازع)
2- Moonfin (خيار موجود ولاباس فيه)
3- jellyfin (سيئ وقبيح على تلفزيونات اندرويد)

reddit.com
u/Spirited-Ad3019 — 12 days ago

Zero Trust Network Access Tools (e.g., Tailscale, Twingate) VS. VPNs

حاب اعرف وش الافضل في الاستخدام، من ناحية الامان.

ابغى اتصل بالhomelab تبعي وانا خارج البيت. جربت wireguard vpn وجربت Twingate

مشكلة ال ڤي بي ان، ان لازم افتح بورت من الراوتر. واعمل reverse proxy. ثم اقدر اوصل لhomelab

بالنسبة لTwingate، كان اسهل في الاعدادات وما يحتاج اعمل اللي عملته في ڤي بي ان.

لكن مشكلته انه تبع شركة معينة.

من وجهة نظرك، وش الافضل، وليه؟!

reddit.com
u/Classic-Milk-870078 — 11 days ago

السلام عليكم، عندي فكرة تطبيق جميلة جدًا لكم

ما أريد أي شيء، لكن أتمنى تطوروا التطبيق وتنشروه بين المسلمين.

الفكرة هي "مسبحة" للتسبيح والاستغفار وذكر الله. مش أي تطبيق تسبيح... لأن فيه مئة تطبيق نفسه. فكرة التطبيق والي بيكون يميزه... هو أن نافذة التسبيح أو العلامة الي تضغطها ويرتفع الرقم تكون موجودة على الشاشة في أي تطبيق تدخله مش فقط لما تطلع من التطبيق المخصص لها. وتقدروا تصمموها بكيفكم. وأريد فقط الأجر والثواب. فا تخيل عدد الأجر الي بيجيك فقط من خلال الناس الي تستعمل التطبيق وهي تقرأ في كتاب من خلال الجوال أو تسمع بودكاست أو يوتيوب أو تتصفح تويتر وريديت.

أتمنى لكم التوفيق وشكراً لوقتكم 🤍🫶🏻✨

reddit.com
u/qaisoy — 11 days ago