Komga


Komga Komga is a comic and eBook catalog and viewer. It'll help you organize and index your eBooks and comics. It currently supports the following formats:

Product: Komga
Install Type: Manifest Files
Container Image: Github

Installation Details

While there are no official Kubernetes instrustions for Komga, we can adapt the Komga Docker Install Instructions to guide us in creating the appropriate manifests.

Now let's create the files we'll need to configure Komga in Kubernetes

The following manifest files assume you will want to install this to a namespace named media, an nginx ingress named nginx, and Cert Manager configured to use the ACME provider Let's Encrypt. Please adjust for your particular needs.

00-media-namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: media
  labels:
    name: media

01-config.yaml

This will define the environment variables for your Komga installation. You should consult the Komga Configuration Docs for configuration options. I configure some general settings, but there are additional settings like LDAP support that can also be configured.

I am currently using Authentik for Single Sign On and using the Komga Documentation I configured a ConfigMap for an applicatin.yml file that will be mounted as a volume. If you do not want this functionality you can simply remove the komga-application-yml ConfigMap

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: komga-configs
  namespace: media
data:
  TZ: America/New_York
  JAVA_TOOL_OPTIONS: -Xmx4g
  KOMGA_OAUTH2_ACCOUNT_CREATION: "true"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: komga-application-yml
  namespace: media
data:
  application.yml: |-
    spring:
      security:
        oauth2:
          client:
            registration:
              authentik:
                provider: authentik # this must match the provider below
                client-id: YourClientID
                client-secret: YourSuperSecretSecret
                client-name: My SSO
                scope: openid,email
                authorization-grant-type: authorization_code
                # the placeholders in {} will be replaced automatically, you don't need to change this line
                redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}"
            provider:
              authentik: # this must match the provider above
                user-name-attribute: sub
                # either set the issuer-uri, in which case the app will lookup the configuration for you automatically
                issuer-uri: https://your-authentik/application/o/komga/
                # or set all of the following
                # authorization-uri: http://localhost:8085/auth/realms/komgatest/protocol/openid-connect/auth
                # token-uri: http://localhost:8085/auth/realms/komgatest/protocol/openid-connect/token
                # jwk-set-uri: http://localhost:8085/auth/realms/komgatest/protocol/openid-connect/certs
                # user-info-uri: http://localhost:8085/auth/realms/komgatest/protocol/openid-connect/userinfo

02-storage.yaml

Even though I'm using an NFS share on a NAS to store my media, Komga will need some local storage for it's own use. I defined a 250 MB config volume using Longhorn for this volume.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  namespace: media
  name: komga-config
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 250Mi

03-deploy.yaml

The Deployment brings together the configuration and storage with the container image.

If you opted to not configure OIDC, then do not define it below. In addition I'm using an existing Persistent Volume Claim named media. You will probably need to alter this for your needs. Be sure to adjust the appropriate volume and volumeMount definitions from the YAML below. I also defined resources since I set Java to use 4Gi of memory in the ConfigMap I reflect that here. You can omit if needed.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: komga
  namespace: media
  labels:
    app: komga
    app.kubernetes.io/name: komga
spec:
  replicas: 1
  selector:
    matchLabels:
      app: komga
  template:
    metadata:
      labels:
        app: komga
        app.kubernetes.io/name: komga
    spec:
      securityContext:
        runAsUser: 1000
        runAsGroup: 2000
        fsGroup: 3000
      volumes:
      - name: komga-config
        persistentVolumeClaim:
           claimName: komga-config
      - name: media
        persistentVolumeClaim:
          claimName: media
      - name: attributes-yml
        configMap: 
          name: komga-application-yml
          optional: true
      containers:
        - name: komga
          image: ghcr.io/gotson/komga:latest
          imagePullPolicy: Always
          resources:
            requests:
              cpu: 10m
              memory: 1Gi
            limits:
              cpu: 500m
              memory: 4608Mi
          volumeMounts:
          - name: komga-config
            mountPath: /config
          - name: media
            mountPath: /media
          - name: attributes-yml
            mountPath: /config/application.yml
            subPath: application.yml
          envFrom:
            - configMapRef:
                name: komga-configs

04-service.yaml

The service will help expose the pod for use. I leverage ClusterIP with an Ingress, but you could use a LoadBalancer type (with something like MetalLB to expose Komga on an IP outside of your cluster directly.

---
kind: Service
apiVersion: v1
metadata:
  name: komga-service
  namespace: media
  labels:
    app: komga
    app.kubernetes.io/name: komga
spec:
  selector:
    app: komga
  ports:
  - protocol: TCP
    port: 25600
    targetPort: 25600
  type: ClusterIP

05-ingress.yaml

An Ingress is one way to expose your services and can allow you to use Cert Manager to create TLS certificates for your site as well. In the annotations: {} section

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: komga-sokolik-info
  namespace: media
  annotations:
    cert-manager.io/cluster-issuer: 'letsencrypt'
spec:
  ingressClassName: nginx
  rules:
    - host: your.external.domain
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: komga-service
              port:
                number: 25600
  tls:
    - hosts:
        - your.external.domain
      secretName: books-ext-tls

build-komga.sh

Now that we have prepared our manifests we need to deploy them to the cluster with kubectl. I create shell scripts for all my deployments so I can quickly redeploy if I make any adjustments. The below script does assume you have configured kubectl properly already.

#!/bin/bash

kubectl apply -f 00-media-namespace.yaml \
              -f 01-config.yaml \
              -f 02-storage.yaml \
              -f 03-deploy.yaml \
              -f 04-service.yaml \
              -f 05-ingress.yaml

We can deploy the manifests for Komga to the Kubernetes cluster by executing the following:

chmod 755 build-komga.sh
./build-komga.sh

I keep all my manifests, scripts, and helm charts in a private git repository for version control and archival storage While it is certainly not required to deploy Komga, it has made my life a little easier.