This directory contains a working, opinionated example for deploying Calibre Web Automated (CWA) to Kubernetes. It includes:
- A
DeploymentandService - Two
PersistentVolumeClaims for configuration and the Calibre library - An ingest directory (hostPath by default) for automatic imports
- Optional Istio Gateway API manifests (HTTPS + redirect)
Adjust storage classes, hostnames, and paths to match your cluster.
- Kubernetes cluster with
kubectlaccess - Namespace (defaults to
mediain several manifests) - Storage provisioners for RWX volumes (e.g., Longhorn, NFS)
- Example uses
longhorn-retainandnfs-clientstorage classes
- Example uses
- Optional: Istio (Gateway API) and cert-manager if using
gateway-istio.yaml- GatewayClass
istioavailable - A
ClusterIssuernamedletsencrypt(or update the annotation) - cert-manager installed with Gateway API support to auto-provision certs. See: cert-manager documentation
- GatewayClass
- Optional: DIUN if you want automated image update notifications (annotation is included in the Deployment)
deployment.yaml: Runscrocodilestick/calibre-web-automated:lateston port8083with a single replica andRecreatestrategy. Mounts:/configfrom PVCcalibre-web-automated-config/calibre-libraryfrom PVCcalibre-library-pvc/cwa-book-ingestfrom a hostPath (edit this to your NAS or use a PVC)- Sets
PUID,PGID, andTZ. Add any other CWA envs you need.
service.yaml: ClusterIP service exposing port8083with selectorapp.service=calibre-web-automated.pvc-config.yaml: RWX claim for CWA config data. Useslonghorn-retain(100Gi) in namespacemedia.pvc-library.yml: RWX claim for the Calibre library. Usesnfs-client(100Gi) in namespacemedia.gateway-istio.yaml(optional): Gateway + HTTPRoutes using Gateway API. Redirects HTTP→HTTPS and terminates TLS for your hostname via cert-manager.
- Configure variables and paths
-
Edit
deployment.yaml:- Set
TZto your timezone and adjustPUID/PGIDto match file ownership on your volumes. - Update the ingest
hostPath(/nas/path/to/import-ebooks) to an existing path on cluster nodes (or convert to PVC — see below). - Optionally add more environment variables.
- Set
-
Edit storage classes in
pvc-*files to match your cluster.
- Create the namespace
kubectl create namespace media- Create PersistentVolumeClaims
kubectl apply -n media -f pvc-config.yaml -f pvc-library.yml- Deploy the app and service
kubectl apply -n media -f deployment.yaml -f service.yaml- (Optional) Expose via Istio Gateway
- Edit
kubernetes/gateway-istio.yaml:- Set your hostname (e.g.,
books.example.com). - Ensure the
cert-manager.io/cluster-issuerannotation references an issuer that exists (e.g.,letsencrypt). - Set
certificateRefs.nameto the name of a TLS secret that cert-manager will create.
- Set your hostname (e.g.,
- Apply it:
kubectl apply -f kubernetes/gateway-istio.yaml- Access the UI
- Port-forward:
kubectl -n media port-forward svc/calibre-web-automated 8083:8083Then open http://localhost:8083
- Or via your Gateway/hostname once DNS and TLS are ready.
/config(PVC:calibre-web-automated-config) holds application configuration and state./calibre-library(PVC:calibre-library-pvc) holds the Calibre library data./cwa-book-ingestis an ingest folder. Files dropped here are imported and then removed after processing. By default this is ahostPathyou must edit; consider switching to a PVC if you prefer.
Note: If you use the Calibre Web Automated Book Downloader, you can mount the same ingest volume into that downloader so finished downloads are written directly into /cwa-book-ingest for automatic import by CWA. Make sure the PVC is Reads Write Many (RWX) so it can be mounted by more than one deployment. See the project: Calibre Web Automated Book Downloader.
Example: switch ingest from hostPath to a PVC
# Replace the hostPath volume in deployment.yaml with:
volumes:
- name: calibre-web-automated-ingest
persistentVolumeClaim:
claimName: calibre-web-automated-ingest
# And create a matching PVC (adjust storageClassName as needed):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: calibre-web-automated-ingest
namespace: media
spec:
accessModes: ["ReadWriteMany"]
storageClassName: nfs-client
resources:
requests:
storage: 50GiNote on RWX: Both example PVCs request ReadWriteMany. Ensure your storage supports RWX (e.g., Longhorn with share manager, or NFS). If not, use ReadWriteOnce or change provisioners accordingly.
service.yamlcreates a ClusterIP on port8083.- For external access you can either:
- Use
port-forwardfor local access/testing, - Configure an Ingress/Gateway (example uses Gateway API with Istio), or
- Change the Service to
NodePortorLoadBalancerif that suits your environment.
- Use
gateway-istio.yamlcreates:- A
Gatewaywith HTTP (80) and HTTPS (443) listeners - An
HTTPRoutethat redirects HTTP→HTTPS - An
HTTPRoutethat routes HTTPS traffic to thecalibre-web-automatedservice on port8083
- A
- TLS termination: The Gateway references a secret via
certificateRefs. You typically manage this secret using cert-manager. A minimal Certificate example:
Note: cert-manager must be deployed with Gateway API support enabled so it can watch Gateway/HTTPRoute resources and provision certificates automatically. Docs: https://cert-manager.io/docs/usage/gateway-api/
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: calibre-web-automated-cert
namespace: media
spec:
secretName: calibre-web-automated-tls # must match certificateRefs.name
dnsNames:
- books.example.com
issuerRef:
kind: ClusterIssuer
name: letsencryptApply this after cert-manager is installed and your issuer exists.
- The Deployment uses
strategy: Recreateandreplicas: 1.- Calibre libraries are file-based; concurrent writers risk corruption. Single replica is recommended.
- Image updates:
imagePullPolicy: Alwaysensures new tags are pulled on rollout.- DIUN annotation (
diun.enable: "true") is present if you run DIUN to monitor for updates.
- PVC Pending:
- Confirm your
storageClassNameexists and supportsReadWriteMany. - Change to an available class or adjust access modes.
- Confirm your
- Permission denied / read-only:
- Ensure
PUID/PGIDmatch ownership of files on the backing storage. - For NFS, verify export permissions (e.g.,
no_root_squashif needed).
- Ensure
- Pod CrashLoopBackOff:
kubectl -n media logs deploy/calibre-web-automatedto inspect errors.
- Gateway returns 404:
- Verify hostname matches the request and
HTTPRouteparentRefssection names. - Check the
GatewayClassexists and isAcceptedby Istio.
- Verify hostname matches the request and
- TLS not provisioning:
- Ensure cert-manager is installed, issuer/ClusterIssuer exists, and a
Certificateresource was created pointing to your DNS name.
- Ensure cert-manager is installed, issuer/ClusterIssuer exists, and a
- Ingest not working / files not removed:
- Confirm the ingest volume path is correct and writable; check CWA settings in the UI.
Delete resources (PVCs may retain data depending on your storage policy):
kubectl delete -n media -f service.yaml -f deployment.yaml
kubectl delete -n media -f pvc-config.yaml -f pvc-library.yml
# If used:
kubectl delete -f gateway-istio.yamlIf your storage class uses a Retain policy, delete PVs or underlying data as appropriate.
- Replace
hostPathfor ingest with a PVC or CSI-backed volume when possible;hostPathties you to a node path. - Keep replicas at 1 unless you fully understand the implications for Calibre’s file-based library.
- Consider resource requests/limits in
deployment.yamlfor more predictable scheduling. - Back up
/configand your library regularly.