# 130 — `grimmory` Self-hosted digital library (eBooks, comics, audiobooks). Community fork/successor of Booklore, with smart shelves, metadata enrichment, Kobo/KOReader sync, OPDS, and a built-in EPUB/PDF reader. Migrated from [apps (105)](105-apps.md) on 2026-06-29. ## At a glance - **Hostname:** `grimmory` - **IP:** `192.168.8.247` - **Host:** **strong** (migrated from hubris 2026-07-05) - **Privilege:** privileged (UID = host UID for `/mnt/library` media GID) - **Resources:** 1 core / 2 GiB RAM / 16 GiB rootfs (Debian 13) - **Mounts:** `/mnt/media_local` ↔ `/mnt/library` - **Public hostname:** `books.hubris.network` ## Service / port map | Service | Listen | Notes | |---------|--------|-------| | Grimmory | `192.168.8.247:6060` | Docker Compose at `/opt/grimmory/` | | MariaDB | internal only | Sidecar in the same compose stack | ## Compose Located at `/opt/grimmory/docker-compose.yml`. Key points: - Image: `ghcr.io/grimmory-tools/grimmory:latest` - Books library: `/mnt/library/books` → `/books` (read-write; media GID 10000 via `GROUP_ID=10000`) - Bookdrop (watched folder for auto-import): `/opt/grimmory/bookdrop` → `/bookdrop` - App data (covers, DB config): `/opt/grimmory/data` → `/app/data` - MariaDB config: `/opt/grimmory/mariadb/config` → `/config` (linuxserver/mariadb image) - `extra_hosts: auth.hubris.network:192.168.8.175` — routes Authentik OIDC discovery to Caddy from inside the container - `FORCE_DISABLE_OIDC=false` — OIDC stays enabled; provider configured via Grimmory admin UI Credentials live in `/opt/grimmory/.env` (untracked): - `DATABASE_PASSWORD` / `MYSQL_PASSWORD` — MariaDB Grimmory user password - `MYSQL_ROOT_PASSWORD` — MariaDB root password ## Authentik OIDC Uses Confidential client (client secret stored in Grimmory's DB — migrated from Booklore). The OIDC config carried over in the database dump; no manual re-entry needed. - **Authentik provider:** `Provider for Grimmory` (renamed from `Provider for Booklore` on migration) - **Client ID:** `L1u0eFsNhbKgiIvvFeIr2mvZdbtFyzidCq2h6thL` - **Client type:** Confidential (client secret in `oidc_provider_details` in MariaDB `app_settings`) - **Redirect URI:** `https://books.hubris.network/oauth2-callback` - **Scopes:** openid, profile, email, offline_access - **Back-channel logout:** `http://192.168.8.247:6060/api/v1/auth/oidc/backchannel-logout` - **Application slug:** `booklore` → Issuer URI: `https://auth.hubris.network/application/o/booklore/` ## Media permissions LXC is privileged → in-container UID = host UID. Docker container gets media GID via `GROUP_ID=10000` env var (Grimmory/linuxserver pattern). The `/mnt/library/books` subtree is owned `:media` mode `2775` (setgid). See [media-permissions](../infrastructure/media-permissions.md). ## Related - [apps (105)](105-apps.md) — previous host (Booklore) - [Caddy (121)](121-caddy.md) — `books.hubris.network → 192.168.8.247:6060` - [Authentik (124)](106-auth-outpost.md) — OIDC provider `Grimmory` - [DNS (107)](107-dns.md) — `books.hubris.network → 192.168.8.175` (unchanged from Booklore) - [Media permissions](../infrastructure/media-permissions.md) ## Changelog ### 2026-06-29 — provisioned; Booklore migrated LXC 130 created (Debian 13, privileged, `192.168.8.213`). Docker installed. Grimmory compose deployed at `/opt/grimmory/`. MariaDB dump from Booklore (LXC 105) restored — schema-compatible since Grimmory is a direct fork. Caddy `books.hubris.network` backend updated from `192.168.8.205:6060` to `192.168.8.213:6060`. Authentik provider updated: Booklore → Grimmory, Confidential → Public (PKCE). Booklore stack removed from Portainer on LXC 105.