Skip to content

BookLore

Deploy BookLore on Kubernetes using the official ghcr.io/booklore-app/booklore container image. A self-hosted eBook library management application with metadata fetching, OPDS support, and a modern web-based reader for managing your personal digital book collection.

Back up MariaDB and every enabled storage domain

BookLore stores relational state in MariaDB and uses separate filesystem domains: /app/data for application data, settings, and caches; /books for the physical library; and optional /bookdrop for imports. A recoverable snapshot must keep MariaDB and these volumes consistent.

Chart References

Key Features

  • MariaDB bundled – HelmForge MariaDB subchart handles the database automatically
  • External database – connect to an existing MariaDB/MySQL instance instead
  • Triple PVC architecture – /app/data (metadata), /books (library files), /bookdrop (imports)
  • OIDC guardrail – force-disable upstream OIDC while it is configured through the BookLore interface
  • Remote/proxy auth – header-based authentication for reverse proxy setups
  • NetworkPolicy – egress constrained to kube-system (DNS) and MariaDB only
  • Gateway API – optional HTTPRoute support for clusters using Gateway API
  • External Secrets – optional ExternalSecret items for secrets management
  • HPA guardrails – validation prevents multi-replica scaling with ReadWriteOnce storage

Architecture

The Service targets the Deployment’s named http port. app.port configures the actual BOOKLORE_PORT listener and all health probes; service.port remains an independent Kubernetes-facing port. BookLore connects to the bundled or external MariaDB service and mounts separate data, books, and optional BookDrop volumes.

The official health endpoint is /api/v1/healthcheck. The default Recreate strategy prevents overlapping mounts during upgrades that use ReadWriteOnce storage.

Installation

HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install booklore helmforge/booklore -f values.yaml

OCI registry:

helm install booklore oci://ghcr.io/helmforgedev/helm/booklore -f values.yaml

Deployment Examples

# values.yaml -- BookLore basic setup with bundled MariaDB
# MariaDB subchart handles the database automatically.
persistence:
  data:
    enabled: true
    size: 5Gi

  books:
    enabled: true
    size: 50Gi
# values.yaml -- Production BookLore with TLS, tuning, and BookDrop
app:
  rootLogLevel: WARN
  logLevel: INFO

persistence:
  data:
    enabled: true
    size: 10Gi
    storageClass: longhorn

  books:
    enabled: true
    size: 200Gi
    storageClass: longhorn

  bookdrop:
    enabled: true
    size: 10Gi
    storageClass: longhorn

resources:
  requests:
    memory: 512Mi
    cpu: 250m
  limits:
    memory: 1Gi
    cpu: '1'

ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: booklore.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: booklore-tls
      hosts:
        - booklore.example.com

mariadb:
  standalone:
    persistence:
      enabled: true
      size: 5Gi
      storageClass: longhorn
    resources:
      requests:
        memory: 256Mi
        cpu: 100m
      limits:
        memory: 512Mi
        cpu: 500m
# values.yaml -- BookLore with external MariaDB/MySQL
mariadb:
  enabled: false

database:
  external:
    host: mariadb.example.com
    port: '3306'
    name: booklore
    username: booklore
    existingSecret: booklore-db-credentials
    existingSecretPasswordKey: password

persistence:
  data:
    enabled: true
    size: 5Gi
  books:
    enabled: true
    size: 100Gi
# values.yaml -- BookLore with Ingress exposure
ingress:
  enabled: true
  ingressClassName: traefik
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: booklore.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: booklore-tls
      hosts:
        - booklore.example.com
# values.yaml -- BookLore with Gateway API HTTPRoute
gatewayAPI:
  enabled: true
  httpRoutes:
    - name: booklore
      parentRefs:
        - name: main-gateway
          namespace: gateway-system
      hostnames:
        - booklore.example.com
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          backendRefs:
            - name: booklore
              port: 6060

Configuration Reference

Application Settings

Parameter Description Default
app.port HTTP port inside the container 6060
app.rootLogLevel Root log level INFO
app.logLevel BookLore-specific log level INFO
app.allowedOrigins CORS allowed origins "*"
app.diskType LOCAL or read-safe NETWORK mode LOCAL
app.env Additional environment variables []
app.envFrom Additional envFrom sources []

Image Configuration

Parameter Description Default
image.repository Container image repository ghcr.io/booklore-app/booklore
image.tag Image tag (pinned) v2.3.1
image.pullPolicy Image pull policy IfNotPresent

Persistence

Parameter Description Default
persistence.data.enabled Persist application data and metadata true
persistence.data.size Data PVC size 10Gi
persistence.data.storageClass Storage class for data PVC ""
persistence.data.accessModes Access modes for data PVC ["ReadWriteOnce"]
persistence.books.enabled Persist library books true
persistence.books.size Books PVC size 50Gi
persistence.books.storageClass Storage class for books PVC ""
persistence.books.accessModes Access modes for books PVC ["ReadWriteOnce"]
persistence.bookdrop.enabled Persist BookDrop import folder false
persistence.bookdrop.size BookDrop PVC size 5Gi

Database

Parameter Description Default
mariadb.enabled Use bundled MariaDB subchart true
mariadb.auth.database MariaDB database name booklore
mariadb.auth.username MariaDB user booklore
database.external.host External DB host (when mariadb.enabled=false) ""
database.external.port External DB port "3306"
database.external.name External DB name booklore
database.external.existingSecret Existing Secret for external DB password ""

Authentication

Parameter Description Default
oidc.enabled Deprecated compatibility value; no runtime effect false
oidc.forceDisable Force-disable OIDC configured through BookLore false
remoteAuth.enabled Enable proxy-based authentication headers false
remoteAuth.createNewUsers Create users from remote auth headers true
remoteAuth.headerName Display name header Remote-Name
remoteAuth.headerUser Username header Remote-User
remoteAuth.headerEmail Email header Remote-Email

Networking

Parameter Description Default
service.type Service type ClusterIP
service.port Service port 6060
ingress.enabled Enable Kubernetes Ingress false
ingress.ingressClassName Ingress class traefik
gatewayAPI.enabled Enable Gateway API HTTPRoutes false
gatewayAPI.httpRoutes HTTPRoute definitions (required when enabled) []
networkPolicy.enabled Create NetworkPolicy false
networkPolicy.egress.enabled Restrict egress traffic false
networkPolicy.egress.allowDNS Allow DNS egress to kube-system true
networkPolicy.egress.databaseTo Database egress peers (required for external DB with egress) []

Monitoring and Scaling

Parameter Description Default
monitoring.serviceMonitor.enabled Create ServiceMonitor for Prometheus false
monitoring.serviceMonitor.path Metrics endpoint path (required when enabled) ""
autoscaling.enabled Enable HPA false
autoscaling.minReplicas Minimum replicas 1
autoscaling.maxReplicas Maximum replicas 3
BookLore v2.3.1 does not expose Prometheus metrics

The current upstream image does not include a Prometheus metrics endpoint. Enable monitoring.serviceMonitor only if you build a custom image with micrometer-registry-prometheus or when upstream adds native support. You must set monitoring.serviceMonitor.path to a real Prometheus exposition endpoint.

HPA requires ReadWriteMany storage

Setting replicaCount > 1 or autoscaling with maxReplicas > 1 requires every enabled persistence volume to declare ReadWriteMany. The chart rejects unsafe data, books, and BookDrop combinations before installation. When HPA is enabled, the Deployment omits spec.replicas so Helm upgrades do not reset the replica count. The first upgrade from an older release can reduce the Deployment to one replica before the HPA reconciles. A fresh installation with minReplicas > 1 can also start at one replica until that first reconciliation. Plan for reduced capacity or redundancy during this transition.

Security and production boundaries

  • Service-account token mounting is disabled by default.
  • Database credentials can come from an existing Secret or ExternalSecret; inline passwords remain visible in Helm release state.
  • Restrict app.allowedOrigins to the public HTTPS origin and allow required metadata-provider egress when enabling NetworkPolicy restrictions.
  • app.diskType=NETWORK disables file writes and reorganization for network-attached book storage; it does not make every network filesystem safe or supported.
  • The stock pinned image has no Prometheus endpoint, so ServiceMonitor remains disabled unless an operator supplies a compatible image and path.

Troubleshooting

  • For slow startup, inspect Flyway and MariaDB logs before restarting the pod.
  • For probe failures, verify BOOKLORE_PORT matches app.port and request /api/v1/healthcheck inside the container.
  • For missing books, verify the /books PVC and app.diskType contract.
  • For database failures, verify the JDBC endpoint, username, and Secret key refer to the same MariaDB instance.