Jelajahi Sumber

Add upstream plex chart

Waqar Ahmed 4 tahun lalu
induk
melakukan
753e183b60

+ 24 - 0
test/plex/.helmignore

@@ -0,0 +1,24 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
+# OWNERS file for Kubernetes
+OWNERS

+ 15 - 0
test/plex/Chart.yaml

@@ -0,0 +1,15 @@
+apiVersion: v2
+appVersion: 1.20.2.3402
+description: Plex Media Server
+name: plex
+version: 2.1.0
+keywords:
+  - plex
+home: https://plex.tv/
+icon: https://www.plex.tv/wp-content/uploads/2018/01/pmp-icon-1.png
+sources:
+  - https://github.com/k8s-at-home/charts/tree/master/charts/plex
+  - https://hub.docker.com/r/plexinc/pms-docker/
+maintainers:
+  - name: billimek
+    email: jeff@billimek.com

+ 4 - 0
test/plex/OWNERS

@@ -0,0 +1,4 @@
+approvers:
+- billimek
+reviewers:
+- billimek

+ 48 - 0
test/plex/README.md

@@ -0,0 +1,48 @@
+# Plex Media Server helm chart
+
+This is an opinionated helm chart for Plex Media Center based on the [official container image](https://hub.docker.com/r/plexinc/pms-docker/).
+
+This chart is 'forked' from the excellent [munnerz/kube-plex](https://github.com/munnerz/kube-plex) repo in order to allow for more timely updates and publishing to a helm registry.  **NOTE:** This chart is not compatible as an upgrade from the `kube-plex` chart.
+
+## TL;DR
+
+```shell
+helm repo add k8s-at-home https://k8s-at-home.com/charts/
+helm install k8s-at-home/plex
+```
+
+## Installing the Chart
+
+To install the chart with the release name `plex`:
+
+```console
+helm install plex k8s-at-home/plex
+```
+
+## Uninstalling the Chart
+
+To uninstall/delete the `plex` deployment:
+
+```console
+helm delete plex
+```
+
+The command removes all the Kubernetes components associated with the chart and deletes the release.
+
+## Configuration
+
+Read through the [values.yaml](https://github.com/k8s-at-home/charts/blob/master/charts/plex/values.yaml) file. It has several commented out suggested values.
+
+Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
+
+```console
+helm install plex \
+  --set timezone="America/New York" \
+    k8s-at-home/plex
+```
+
+Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,
+
+```console
+helm install plex -f values.yaml k8s-at-home/plex
+```

+ 64 - 0
test/plex/configs/41-plex-preferences

@@ -0,0 +1,64 @@
+#!/usr/bin/with-contenv bash
+
+# This file is based off of the official 40-plex-first-run
+# Here: https://github.com/plexinc/pms-docker/blob/master/root/etc/cont-init.d/40-plex-first-run
+# It should live in /etc/cont-init.d/
+
+# If we are debugging, enable trace
+if [ "${DEBUG,,}" = "true" ]; then
+  set -x
+fi
+
+function getPref {
+  local key="$1"
+
+  xmlstarlet sel -T -t -m "/Preferences" -v "@${key}" -n "${prefFile}"
+}
+
+function setPref {
+  local key="$1"
+  local value="$2"
+
+  count="$(xmlstarlet sel -t -v "count(/Preferences/@${key})" "${prefFile}")"
+  count=$(($count + 0))
+  if [[ $count > 0 ]]; then
+    xmlstarlet ed --inplace --update "/Preferences/@${key}" -v "${value}" "${prefFile}"
+  else
+    xmlstarlet ed --inplace --insert "/Preferences"  --type attr -n "${key}" -v "${value}" "${prefFile}"
+  fi
+}
+
+home="$(echo ~plex)"
+pmsApplicationSupportDir="${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR:-${home}/Library/Application Support}"
+prefFile="${pmsApplicationSupportDir}/Plex Media Server/Preferences.xml"
+
+if [ ! -z "${ADVERTISE_IP}" ]; then
+  setPref "customConnections" "${ADVERTISE_IP}"
+fi
+
+if [ ! -z "${ALLOWED_NETWORKS}" ]; then
+  setPref "allowedNetworks" "${ALLOWED_NETWORKS}"
+fi
+
+# Set transcoder temp if not yet set
+if [ -z "$(getPref "TranscoderTempDirectory")" ]; then
+  setPref "TranscoderTempDirectory" "/transcode"
+fi
+
+# Parse list of all exported variables that start with PLEX_PREFERENCE_
+# The format of which is PLEX_PREFERENCE_<SOMETHING>="Key=Value"
+# Where Key is the EXACT key to use in the Plex Preference file
+# And Value is the EXACT value to use in the Plex Preference file for that key.
+# Please note it looks like many of the key's are camelCase in some fashion.
+# Additionally there are likely some preferences where environment variable injection
+# doesn't really work for.
+for var in "${!PLEX_PREFERENCE_@}"; do
+  value=${!var}
+  PreferenceValue=${value#*=}
+  PreferenceKey=${value%=*}
+  setPref $PreferenceKey $PreferenceValue
+done
+
+# touch /.firstRunComplete
+# echo "Plex Media Server first run setup complete"
+echo "Plex Media Server preferences update run complete"

+ 53 - 0
test/plex/configs/42-pkcs-mangler

@@ -0,0 +1,53 @@
+#!/usr/bin/with-contenv bash
+
+# This file contains part of the official PLEX 40-plex-first-run
+# Here: https://github.com/plexinc/pms-docker/blob/master/root/etc/cont-init.d/40-plex-first-run
+# It should live in /etc/cont-init.d/
+
+# If we are debugging, enable trace
+if [ "${DEBUG,,}" = "true" ]; then
+  set -x
+fi
+
+function setPref {
+  local key="$1"
+  local value="$2"
+
+  count="$(xmlstarlet sel -t -v "count(/Preferences/@${key})" "${prefFile}")"
+  count=$(($count + 0))
+  if [[ $count > 0 ]]; then
+    xmlstarlet ed --inplace --update "/Preferences/@${key}" -v "${value}" "${prefFile}"
+  else
+    xmlstarlet ed --inplace --insert "/Preferences"  --type attr -n "${key}" -v "${value}" "${prefFile}"
+  fi
+}
+
+home="$(echo ~plex)"
+pmsApplicationSupportDir="${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR:-${home}/Library/Application Support}"
+prefFile="${pmsApplicationSupportDir}/Plex Media Server/Preferences.xml"
+
+# If PKCSMANGLER__PFXINCONTAINERPATH is set, then assume we want to move the PFX Cert to that location
+if [ ! -z "${PKCSMANGLER_PFXINCONTAINERPATH}" ]; then
+  # If it ends up a problem, we may need to set some kind of "don't replace existing PFX cert"
+  cp -f /shared/cert.pfx "${PKCSMANGLER_PFXINCONTAINERPATH}"
+  # If PKCSMANGLER__CUSTOMCERTDOMAIN is set, then assume we want to set the PLEX Preference customCertificatePath because we enabled setting PLEX Preferences
+  if [ ! -z "${PKCSMANGLER_CUSTOMCERTDOMAIN}" ]; then
+    setPref "customCertificatePath" "${PKCSMANGLER_PFXINCONTAINERPATH}"
+  fi
+fi
+
+# If PKCSMANGLER_PFXPASSWORD is set, then assume we want to set the PLEX Preference customCertificateKey
+if [ ! -z "${PKCSMANGLER_PFXPASSWORD}" ]; then
+  setPref "customCertificateKey" "${PKCSMANGLER_PFXPASSWORD}"
+fi
+
+# If PKCSMANGLER__CUSTOMCERTDOMAIN is set, then assume we want to set the PLEX Preference customCertificateDomain
+if [ ! -z "${PKCSMANGLER_CUSTOMCERTDOMAIN}" ]; then
+  PreferenceValue=${PKCSMANGLER_CUSTOMCERTDOMAIN#*=}
+  PreferenceKey=${PKCSMANGLER_CUSTOMCERTDOMAIN%=*}
+  setPref $PreferenceKey $PreferenceValue
+fi
+
+# touch /.firstRunComplete
+# echo "Plex Media Server first run setup complete"
+echo "PKCS Mangler run complete"

+ 19 - 0
test/plex/templates/NOTES.txt

@@ -0,0 +1,19 @@
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}
+{{- end }}
+{{- else if contains "NodePort" .Values.serviceTCP.type }}
+  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "plex.fullname" . }})
+  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+  echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.serviceTCP.type }}
+     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+           You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "plex.fullname" . }}'
+  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "plex.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+  echo http://$SERVICE_IP:{{ .Values.serviceTCP.port }}
+{{- else if contains "ClusterIP" .Values.serviceTCP.type }}
+  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "plex.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+  echo "Visit http://127.0.0.1:8080 to use your application"
+  kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80
+{{- end }}

+ 81 - 0
test/plex/templates/_helpers.tpl

@@ -0,0 +1,81 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "plex.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "plex.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "plex.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "plex.labels" -}}
+helm.sh/chart: {{ include "plex.chart" . }}
+{{ include "plex.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+Selector labels
+*/}}
+{{- define "plex.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "plex.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end -}}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "plex.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create -}}
+    {{ default (include "plex.fullname" .) .Values.serviceAccount.name }}
+{{- else -}}
+    {{ default "default" .Values.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+abstract: |
+  Joins a list of values into a comma separated string
+values: |
+  test:
+    - foo
+    - bar
+usage: |
+  {{ include "joinListWithComma" .Values.test }}
+return: |
+  foo,bar
+*/}}
+
+{{- define "joinListWithComma" -}}
+{{- $local := dict "first" true -}}
+{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}}
+{{- end -}}

+ 42 - 0
test/plex/templates/configmap.yaml

@@ -0,0 +1,42 @@
+{{- if .Values.plexPreferences.enabled -}}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Values.plexPreferences.configmap.name }}
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+{{- if .Values.plexPreferences.configmap.labels }}
+{{ toYaml .Values.plexPreferences.configmap.labels | indent 4 }}
+{{- end }}
+{{- with .Values.plexPreferences.configmap.annotations }}
+  annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+
+data:
+# At some point figure out how to use a value/Variable here to be able to specify
+# a different file or something.
+{{ (tpl (.Files.Glob "configs/41-plex-preferences").AsConfig . ) | indent 2 }}
+{{- end -}}
+
+{{- if .Values.certificate.pkcsMangler.enabled }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ .Values.certificate.pkcsMangler.configmap.name }}
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+{{- if .Values.certificate.pkcsMangler.configmap.labels }}
+{{ toYaml .Values.certificate.pkcsMangler.configmap.labels | indent 4 }}
+{{- end }}
+{{- with .Values.certificate.pkcsMangler.configmap.annotations }}
+  annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+
+data:
+# At some point figure out how to use a value/Variable here to be able to specify
+# a different file or something.
+{{ (tpl (.Files.Glob "configs/42-pkcs-mangler").AsConfig . ) | indent 2 }}
+{{- end -}}

+ 357 - 0
test/plex/templates/deployment.yaml

@@ -0,0 +1,357 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "plex.fullname" . }}
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+  {{- if .Values.deploymentAnnotations }}
+  annotations:
+    {{- range $key, $value := .Values.deploymentAnnotations }}
+    {{ $key }}: {{ $value | quote }}
+    {{- end }}
+  {{- end }}
+spec:
+  replicas: 1
+  revisionHistoryLimit: 3
+  strategy:
+    type: {{ .Values.strategyType }}
+  selector:
+    matchLabels:
+      {{- include "plex.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      labels:
+        {{- include "plex.selectorLabels" . | nindent 8 }}
+      {{- if .Values.podAnnotations }}
+      annotations:
+        {{- range $key, $value := .Values.podAnnotations }}
+        {{ $key }}: {{ $value | quote }}
+        {{- end }}
+      {{- end }}
+    spec:
+    {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- if .Values.hostNetwork }}
+      hostNetwork: {{ .Values.hostNetwork }}
+      dnsPolicy: ClusterFirstWithHostNet
+    {{- end }}
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+  {{- if .Values.certificate.pkcsMangler.enabled }}
+      initContainers:
+      # This is ugly, but it does work to create a pks file that will work with PLEX from the tls.crt and tls.key that cert-manager normally creates
+      {{- if .Values.certificate.pkcsMangler.enabled }}
+      - name: pkcsmangler-init-container
+        image: "{{ .Values.certificate.pkcsMangler.image.repository }}:{{ .Values.certificate.pkcsMangler.image.tag }}"
+        imagePullPolicy: Always
+        command: ["/bin/sh"]
+        args: ["-c", "openssl pkcs12 -export -passout pass:$(PKCSMANGLER_PFXPASSWORD) -out /shared/cert.pfx -inkey {{ .Values.certificate.pkcsMangler.certificateSecret.volume.mountPath }}/{{ .Values.certificate.pkcsMangler.certificateSecret.keyName }} -in {{ .Values.certificate.pkcsMangler.certificateSecret.volume.mountPath }}/{{ .Values.certificate.pkcsMangler.certificateSecret.crtName }}; chmod 0444 /shared/cert.pfx"]
+        env:
+          - name: "PKCSMANGLER_PFXPASSWORD"
+            valueFrom:
+              secretKeyRef:
+                name: {{ .Values.certificate.pkcsMangler.pfxPassword.secretName }}
+                key: {{ .Values.certificate.pkcsMangler.pfxPassword.passwordKey }}
+        volumeMounts:
+        - name: shared
+          mountPath: /shared
+        - name: {{ .Values.certificate.pkcsMangler.certificateSecret.volume.name }}
+          mountPath: {{ .Values.certificate.pkcsMangler.certificateSecret.volume.mountPath }}
+      {{- end }}
+  {{- end }}
+      containers:
+      {{- if .Values.logging.promtail.enabled }}
+        - name: {{ .Chart.Name }}-promtail
+          image: "{{ .Values.logging.promtail.image.repository }}:{{ .Values.logging.promtail.image.tag }}"
+          imagePullPolicy: {{ .Values.logging.promtail.image.pullPolicy }}
+          args:
+          - -config.file=/etc/promtail/promtail.yaml
+          volumeMounts:
+          - name: promtail-config
+            mountPath: /etc/promtail/promtail.yaml
+            subPath: promtail.yaml
+            readOnly: true
+          - name: shared-logs
+            mountPath: /plex-logs
+      {{- end }}
+        - name: {{ .Chart.Name }}
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          ports:
+          - name: pms
+            protocol: TCP
+            containerPort: 32400
+          - name: plex-dlna
+            protocol: TCP
+            containerPort: 32469
+          - name: plex-dlna-udp
+            protocol: UDP
+            containerPort: 1900
+          - name: plex-gdm1
+            protocol: UDP
+            containerPort: 32410
+          - name: plex-gdm2
+            protocol: UDP
+            containerPort: 32412
+          - name: plex-gdm3
+            protocol: UDP
+            containerPort: 32413
+          - name: plex-gdm4
+            protocol: UDP
+            containerPort: 32414
+          env:
+          - name: TZ
+            value: "{{ .Values.timezone }}"
+          # TODO: move this to a secret?
+          - name: PLEX_CLAIM
+            value: "{{ .Values.claimToken }}"
+          # plex env vars
+          - name: PMS_INTERNAL_ADDRESS
+            value: http://{{ template "plex.fullname" . }}:32400
+          - name: PMS_IMAGE
+            value: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+          - name: KUBE_NAMESPACE
+            valueFrom:
+              fieldRef:
+                fieldPath: metadata.namespace
+          - name: TRANSCODE_PVC
+  {{- if .Values.persistence.transcode.claimName }}
+            value: "{{ .Values.persistence.transcode.claimName }}"
+  {{- else }}
+            value: "{{ template "plex.fullname" . }}-transcode"
+  {{- end }}
+  {{- if .Values.persistence.data.enabled }}
+          - name: DATA_PVC
+    {{- if .Values.persistence.data.claimName }}
+            value: "{{ .Values.persistence.data.claimName }}"
+    {{- else }}
+            value: "{{ template "plex.fullname" . }}-data"
+    {{- end }}
+  {{- end }}
+          - name: CONFIG_PVC
+  {{- if .Values.persistence.config.claimName }}
+            value: "{{ .Values.persistence.config.claimName }}"
+  {{- else }}
+            value: "{{ template "plex.fullname" . }}-config"
+  {{- end }}
+  {{- if .Values.proxy.enabled }}
+    {{- if .Values.proxy.http }}
+          - name: "HTTP_PROXY"
+            value: "{{.Values.proxy.http}}"
+    {{- end }}
+    {{- if .Values.proxy.https }}
+          - name: "HTTPS_PROXY"
+            value: "{{.Values.proxy.https}}"
+    {{- end }}
+    {{- if .Values.proxy.noproxy }}
+          - name: "NO_PROXY"
+            value: "{{.Values.proxy.noproxy}}"
+    {{- end }}
+  {{- end }}
+  {{- if .Values.advertiseIp }}
+          - name: "ADVERTISE_IP"
+            value: "{{.Values.advertiseIp}}"
+{{- end }}
+{{- if .Values.changeConfigDirOwnership }}
+          - name: "CHANGE_CONFIG_DIR_OWNERSHIP"
+            value: "{{.Values.changeConfigDirOwnership}}"
+{{- end }}
+{{- if .Values.allowedNetworks }}
+          - name: "ALLOWED_NETWORKS"
+            value: "{{include "joinListWithComma" .Values.allowedNetworks}}"
+{{- end }}
+{{- if .Values.plexUid }}
+          - name: "PLEX_UID"
+            value: "{{.Values.plexUid}}"
+{{- end }}
+{{- if .Values.plexGid }}
+          - name: "PLEX_GID"
+            value: "{{.Values.plexGid}}"
+{{- end }}
+# Extra ENV Values supplied by user
+{{- range $key, $value := .Values.extraEnv }}
+          - name: {{ $key }}
+            value: {{ $value }}
+{{- end }}
+# This is part of pkcsMangler
+{{- if .Values.certificate.pkcsMangler.enabled }}
+          - name: "PKCSMANGLER_PFXINCONTAINERPATH"
+            value: "{{.Values.certificate.pkcsMangler.pfxInContainerPath}}"
+{{- if .Values.certificate.pkcsMangler.setPlexPreferences.enabled }}
+          - name: "PKCSMANGLER_PFXPASSWORD"
+            valueFrom:
+              secretKeyRef:
+                name: {{ .Values.certificate.pkcsMangler.pfxPassword.secretName }}
+                key: {{ .Values.certificate.pkcsMangler.pfxPassword.passwordKey }}
+          - name: "PKCSMANGLER_CUSTOMCERTDOMAIN"
+            value: "customCertificateDomain={{.Values.certificate.pkcsMangler.setPlexPreferences.customCertificateDomain}}"
+{{- end }}
+{{- end }}
+          readinessProbe:
+            httpGet:
+              path: /identity
+              port: 32400
+            failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
+            periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
+          livenessProbe:
+            httpGet:
+              path: /identity
+              port: 32400
+            failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
+            periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
+          startupProbe:
+            httpGet:
+              path: /identity
+              port: 32400
+            initialDelaySeconds: {{ .Values.probes.startup.initialDelaySeconds }}
+            failureThreshold: {{ .Values.probes.startup.failureThreshold }}
+            periodSeconds: {{ .Values.probes.startup.periodSeconds }}
+          volumeMounts:
+          {{- if .Values.persistence.data.enabled }}
+          - name: data
+            mountPath: /data
+          {{- if .Values.persistence.data.subPath }}
+            subPath: {{ .Values.persistence.data.subPath }}
+          {{ end }}
+          {{ end }}
+          - name: config
+            mountPath: /config
+          {{- if .Values.persistence.config.subPath }}
+            subPath: {{ .Values.persistence.config.subPath }}
+          {{ end }}
+          - name: transcode
+            mountPath: /transcode
+          {{- if .Values.persistence.transcode.subPath }}
+            subPath: {{ .Values.persistence.transcode.subPath }}
+          {{ end }}
+          {{-  range .Values.persistence.extraData }}
+          - mountPath: "/data-{{ .name }}"
+          {{- if .subPath }}
+            subPath: {{ .subPath }}
+          {{ end }}
+            name: "extradata-{{ .name }}"
+          {{- end }}
+          {{-  range .Values.persistence.extraMounts }}
+          {{- if .mountPath }}
+          - mountPath: /{{ .mountPath }}
+          {{- else }}
+          - mountPath: /{{ .name }}
+          {{- end }}
+          {{- if .subPath }}
+            subPath: {{ .subPath }}
+          {{ end }}
+            name: {{ .name }}
+          {{- end }}
+          - name: shared
+            mountPath: /shared
+          - name: shared-logs
+            mountPath: "/config/Library/Application Support/Plex Media Server/Logs"
+          {{- if .Values.plexPreferences.enabled }}
+          - name: {{ .Values.plexPreferences.volume.name }}
+            mountPath: {{ .Values.plexPreferences.volume.mountPath }}
+            subPath: {{ .Values.plexPreferences.volume.subPath }}
+          {{- end }}
+          {{- if .Values.certificate.pkcsMangler.enabled }}
+          - name: {{ .Values.certificate.pkcsMangler.volume.name }}
+            mountPath: {{ .Values.certificate.pkcsMangler.volume.mountPath }}
+            subPath: {{ .Values.certificate.pkcsMangler.volume.subPath }}
+          {{- end }}
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+##### VOLUMES START #####
+      volumes:
+{{- if .Values.persistence.data.enabled }}
+      - name: data
+        persistentVolumeClaim:
+  {{- if .Values.persistence.data.claimName }}
+          claimName: "{{ .Values.persistence.data.claimName }}"
+  {{- else }}
+          claimName: "{{ template "plex.fullname" . }}-data"
+  {{- end }}
+{{- end }}
+      - name: config
+        persistentVolumeClaim:
+{{- if .Values.persistence.config.claimName }}
+          claimName: "{{ .Values.persistence.config.claimName }}"
+{{- else }}
+          claimName: "{{ template "plex.fullname" . }}-config"
+{{- end }}
+      - name: transcode
+{{- if .Values.persistence.transcode.enabled }}
+        persistentVolumeClaim:
+{{- if .Values.persistence.transcode.claimName }}
+          claimName: "{{ .Values.persistence.transcode.claimName }}"
+{{- else }}
+          claimName: "{{ template "plex.fullname" . }}-transcode"
+{{- end }}
+{{- else }}
+{{- if .Values.persistence.transcode.emptyDir.medium }}
+        emptyDir:
+          medium: "{{ .Values.persistence.transcode.emptyDir.medium }}"
+{{- else }}
+        emptyDir: {}
+{{- end }}
+{{- end }}
+{{-  range .Values.persistence.extraData }}
+      - name: "extradata-{{ .name }}"
+        persistentVolumeClaim:
+{{- if .claimName }}
+          claimName: "{{ .claimName }}"
+{{- else }}
+          claimName: "extradata-{{ .name }}"
+{{- end }}
+{{- end }}
+{{- range .Values.persistence.extraMounts }}
+  {{- if .claimName }}
+      - name: {{ .name }}
+        persistentVolumeClaim:
+          claimName: {{ .claimName }}
+  {{- end }}        
+{{- end }}
+      - name: shared
+        emptyDir: {}
+      - name: shared-logs
+        emptyDir: {}
+      {{- if .Values.plexPreferences.enabled }}
+      - name: {{ .Values.plexPreferences.volume.name }}
+        configMap:
+          name: {{ .Values.plexPreferences.configmap.name }}
+          defaultMode: {{ .Values.plexPreferences.volume.defaultMode }}
+      {{- end }}
+      {{- if .Values.certificate.pkcsMangler.enabled }}
+      - name: {{ .Values.certificate.pkcsMangler.volume.name }}
+        configMap:
+          name: {{ .Values.certificate.pkcsMangler.configmap.name }}
+          defaultMode: {{ .Values.certificate.pkcsMangler.volume.defaultMode }}
+      - name: {{ .Values.certificate.pkcsMangler.certificateSecret.volume.name }}
+        secret:
+          secretName: {{ .Values.certificate.pkcsMangler.certificateSecret.name }}
+      {{- end }}
+      {{- if .Values.logging.promtail.enabled }}
+      - name: promtail-config
+        projected:
+          defaultMode: 0444
+          sources:
+          - configMap:
+              name: {{ template "plex.fullname" . }}-promtail
+              items:
+                - key: promtail.yaml
+                  path: promtail.yaml
+      {{- end }}
+##### VOLUMES END #####
+    {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}

+ 40 - 0
test/plex/templates/ingress.yaml

@@ -0,0 +1,40 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "plex.fullname" . -}}
+{{- $svcPort := .Values.serviceTCP.port -}}
+{{- $ingressPath := .Values.ingress.path -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+  name: {{ $fullName }}
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+  {{- with .Values.ingress.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+{{- if .Values.ingress.tls }}
+  tls:
+  {{- range .Values.ingress.tls }}
+    - hosts:
+      {{- range .hosts }}
+        - {{ . | quote }}
+      {{- end }}
+      secretName: {{ .secretName }}
+  {{- end }}
+{{- end }}
+  rules:
+  {{- range .Values.ingress.hosts }}
+    - host: {{ . | quote }}
+      http:
+        paths:
+          - path: {{ $ingressPath }}
+            backend:
+              serviceName: {{ $fullName }}-tcp
+              servicePort: {{ $svcPort }}
+  {{- end }}
+{{- end }}

+ 36 - 0
test/plex/templates/promtail-configmap.yaml

@@ -0,0 +1,36 @@
+{{- if .Values.logging.promtail.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ template "plex.fullname" . }}-promtail
+  namespace: {{ .Release.Namespace }}
+  labels:
+    app.kubernetes.io/name: {{ include "plex.name" . }}
+    helm.sh/chart: {{ include "plex.chart" . }}
+    app.kubernetes.io/instance: {{ .Release.Name }}
+    app.kubernetes.io/managed-by: {{ .Release.Service }}
+data:
+  promtail.yaml: |
+    server:
+      http_listen_port: 9080
+      grpc_listen_port: 0
+    positions:
+      filename: /tmp/positions.yaml
+    clients:
+    - url: {{ .Values.logging.promtail.loki.url }}
+    scrape_configs:
+    - job_name: plex-logs
+      static_configs:
+      - targets:
+          - localhost
+        labels:
+          job: plex-logs
+          __path__: "/plex-logs/*.log"
+    - job_name: plex-plugin-logs
+      static_configs:
+      - targets:
+          - localhost
+        labels:
+          job: plex-plugin-logs
+          __path__: "/plex-logs/PMS Plugin Logs/*.log"
+{{- end }}

+ 18 - 0
test/plex/templates/secrets.yaml

@@ -0,0 +1,18 @@
+{{- if .Values.certificate.pkcsMangler.enabled -}}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ .Values.certificate.pkcsMangler.pfxPassword.secretName }}
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+{{- if .Values.certificate.pkcsMangler.pfxPassword.labels }}
+{{ toYaml .Values.certificate.pkcsMangler.pfxPassword.labels | indent 4 }}
+{{- end }}
+{{- with .Values.certificate.pkcsMangler.pfxPassword.annotations }}
+  annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+type: Opaque
+stringData:
+  {{ .Values.certificate.pkcsMangler.pfxPassword.passwordKey }}: {{ .Values.certificate.pkcsMangler.pfxPassword.value }}
+{{- end -}}

+ 57 - 0
test/plex/templates/service-tcp.yaml

@@ -0,0 +1,57 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "plex.fullname" . }}-tcp
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+{{- if .Values.serviceTCP.labels }}
+{{ toYaml .Values.serviceTCP.labels | indent 4 }}
+{{- end }}
+{{- with .Values.serviceTCP.annotations }}
+  annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+spec:
+{{- if (or (eq .Values.serviceTCP.type "ClusterIP") (empty .Values.serviceTCP.type)) }}
+  type: ClusterIP
+  {{- if .Values.serviceTCP.clusterIP }}
+  clusterIP: {{ .Values.serviceTCP.clusterIP }}
+  {{end}}
+{{- else if eq .Values.serviceTCP.type "LoadBalancer" }}
+  type: {{ .Values.serviceTCP.type }}
+  {{- if .Values.serviceTCP.loadBalancerIP }}
+  loadBalancerIP: {{ .Values.serviceTCP.loadBalancerIP }}
+  {{- end }}
+  {{- if .Values.serviceTCP.loadBalancerSourceRanges }}
+  loadBalancerSourceRanges:
+{{ toYaml .Values.serviceTCP.loadBalancerSourceRanges | indent 4 }}
+  {{- end -}}
+{{- else }}
+  type: {{ .Values.serviceTCP.type }}
+{{- end }}
+{{- if .Values.serviceTCP.externalIPs }}
+  externalIPs:
+{{ toYaml .Values.serviceTCP.externalIPs | indent 4 }}
+{{- end }}
+  {{- if .Values.serviceTCP.externalTrafficPolicy }}
+  externalTrafficPolicy: {{ .Values.serviceTCP.externalTrafficPolicy }}
+  {{- end }}
+  ports:
+    - name: pms
+      port: {{ .Values.serviceTCP.port }}
+      protocol: TCP
+      targetPort: pms
+{{ if (and (eq .Values.serviceTCP.type "NodePort") (not (empty .Values.serviceTCP.nodePort))) }}
+      nodePort: {{.Values.serviceTCP.nodePort}}
+{{ end }}
+    - name: http
+      port: 80
+      targetPort: pms
+    - name: https
+      port: 443
+      targetPort: pms
+    - name: plex-dlna
+      port: 1900
+      targetPort: plex-dlna
+  selector:
+    {{- include "plex.selectorLabels" . | nindent 4 }}

+ 61 - 0
test/plex/templates/service-udp.yaml

@@ -0,0 +1,61 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "plex.fullname" . }}-udp
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+{{- if .Values.serviceUDP.labels }}
+{{ toYaml .Values.serviceUDP.labels | indent 4 }}
+{{- end }}
+{{- with .Values.serviceUDP.annotations }}
+  annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+spec:
+{{- if (or (eq .Values.serviceUDP.type "ClusterIP") (empty .Values.serviceUDP.type)) }}
+  type: ClusterIP
+  {{- if .Values.serviceUDP.clusterIP }}
+  clusterIP: {{ .Values.serviceUDP.clusterIP }}
+  {{end}}
+{{- else if eq .Values.serviceUDP.type "LoadBalancer" }}
+  type: {{ .Values.serviceUDP.type }}
+  {{- if .Values.serviceUDP.loadBalancerIP }}
+  loadBalancerIP: {{ .Values.serviceUDP.loadBalancerIP }}
+  {{- end }}
+  {{- if .Values.serviceUDP.loadBalancerSourceRanges }}
+  loadBalancerSourceRanges:
+{{ toYaml .Values.serviceUDP.loadBalancerSourceRanges | indent 4 }}
+  {{- end -}}
+{{- else }}
+  type: {{ .Values.serviceUDP.type }}
+{{- end }}
+{{- if .Values.serviceUDP.externalIPs }}
+  externalIPs:
+{{ toYaml .Values.serviceUDP.externalIPs | indent 4 }}
+{{- end }}
+  {{- if .Values.serviceUDP.externalTrafficPolicy }}
+  externalTrafficPolicy: {{ .Values.serviceUDP.externalTrafficPolicy }}
+  {{- end }}
+  ports:
+    - name: plex-dlna-udp
+      port: 1900
+      protocol: UDP
+      targetPort: plex-dlna-udp
+    - name: plex-gdm1
+      port: 32410
+      protocol: UDP
+      targetPort: plex-gdm1
+    - name: plex-gdm2
+      port: 32412
+      protocol: UDP
+      targetPort: plex-gdm2
+    - name: plex-gdm3
+      port: 32413
+      protocol: UDP
+      targetPort: plex-gdm3
+    - name: plex-gdm4
+      port: 32414
+      protocol: UDP
+      targetPort: plex-gdm4
+  selector:
+    {{- include "plex.selectorLabels" . | nindent 4 }}

+ 57 - 0
test/plex/templates/volumes.yaml

@@ -0,0 +1,57 @@
+{{- if and (not .Values.persistence.transcode.claimName) .Values.persistence.transcode.enabled }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: {{ template "plex.fullname" . }}-transcode
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+    component: transcode
+spec:
+  accessModes:
+  - {{ .Values.persistence.config.accessMode | quote }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.transcode.size | quote }}
+{{- if .Values.persistence.transcode.storageClass }}
+  storageClassName: {{ .Values.persistence.transcode.storageClass | quote }}
+{{- end }}
+---
+{{- end }}
+{{- if not .Values.persistence.config.claimName }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: {{ template "plex.fullname" . }}-config
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+    component: config
+spec:
+  accessModes:
+  - {{ .Values.persistence.config.accessMode | quote }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.config.size | quote }}
+{{- if .Values.persistence.config.storageClass }}
+  storageClassName: {{ .Values.persistence.config.storageClass | quote }}
+{{- end }}
+---
+{{- end }}
+{{- if and (not .Values.persistence.data.claimName) .Values.persistence.data.enabled  }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: {{ template "plex.fullname" . }}-data
+  labels:
+    {{- include "plex.labels" . | nindent 4 }}
+    component: data
+spec:
+  accessModes:
+  - {{ .Values.persistence.data.accessMode | quote }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.data.size | quote }}
+{{- if .Values.persistence.data.storageClass }}
+  storageClassName: {{ .Values.persistence.data.storageClass | quote }}
+{{- end }}
+---
+{{- end }}

+ 349 - 0
test/plex/values.yaml

@@ -0,0 +1,349 @@
+# Default values
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+# The Image to use for PLEX
+
+image:
+  repository: plexinc/pms-docker
+  tag: 1.20.2.3402-0fec14d92
+  pullPolicy: IfNotPresent
+
+#####   START  --> Official PLEX container environment variables
+# Override this with the plex claim token from plex.tv/claim
+claimToken: ""
+
+# Set the timezone of the plex server
+timezone: "UTC"
+
+# add your pod network subnet to the `List of IP addresses and networks that are allowed without auth`
+# This will override the manual settings, so only use this if you will not need to change it manually.
+# This list will be automatically converted to a command seperated string when passed to the container.
+# You would specify this when using helm CLI with --set allowedNetworks="{127.0.0.1,10.54.2.0/24}"
+# allowedNetworks:
+#   -   127.0.0.1
+#   -   10.54.2.0/24
+
+# Instruct the Plex Media Server Container to Change the Configuration Directory Ownership
+# Default is true, you would only need to set this if you want to disable it.
+# changeConfigDirOwnership: true
+
+# advertiseIp This variable defines the additional IPs on which the server may be be found.
+# For example: http://10.1.1.23:32400.
+# This adds to the list where the server advertises that it can be found.
+# See https://hub.docker.com/r/plexinc/pms-docker/ for details
+# advertiseIp: "http://10.1.1.23:32400"
+
+# Set The user id of the plex user created inside the container.
+# See https://hub.docker.com/r/plexinc/pms-docker/ for details
+# plexUid: 1000
+
+# Set The group id of the plex group created inside the container
+# See https://hub.docker.com/r/plexinc/pms-docker/ for details
+# plexGid: 1000
+
+#####   END  --> Official PLEX container environment variables
+
+# You can add as many Additional ENV variables here
+# The following is the same as --set extraEnv.TMPDIR="/transcode"
+# extraEnv:
+#   TMPDIR: /transcode
+
+# upgrade strategy type (e.g. Recreate or RollingUpdate)
+strategyType: Recreate
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+podSecurityContext: {}
+  # fsGroup: 2000
+
+securityContext: {}
+  # capabilities:
+  #   drop:
+  #   - ALL
+  # readOnlyRootFilesystem: true
+  # runAsNonRoot: true
+  # runAsUser: 1000
+
+serviceTCP:
+  type: ClusterIP
+  port: 32400
+  ## Specify the nodePort value for the LoadBalancer and NodePort service types.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
+  ##
+  # nodePort:
+  ## Provide any additional annotations which may be required. This can be used to
+  ## set the LoadBalancer service type to internal only.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
+  ##
+  annotations: {}
+  # metallb.universe.tf/allow-shared-ip: plex-svc
+  labels: {}
+  ## Use loadBalancerIP to request a specific static IP,
+  ## otherwise leave blank
+  ##
+  loadBalancerIP:
+  # loadBalancerSourceRanges: []
+  ## Set the externalTrafficPolicy in the Service to either Cluster or Local
+  # externalTrafficPolicy: Cluster
+
+serviceUDP:
+  type: ClusterIP
+  ## Provide any additional annotations which may be required. This can be used to
+  ## set the LoadBalancer service type to internal only.
+  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
+  ##
+  annotations: {}
+  # metallb.universe.tf/allow-shared-ip: plex-svc
+  labels: {}
+  ## Use loadBalancerIP to request a specific static IP,
+  ## otherwise leave blank
+  ##
+  loadBalancerIP:
+  # loadBalancerSourceRanges: []
+  ## Set the externalTrafficPolicy in the Service to either Cluster or Local
+  # externalTrafficPolicy: Cluster
+
+ingress:
+  enabled: false
+  annotations: {}
+    # kubernetes.io/ingress.class: nginx
+    # kubernetes.io/tls-acme: "true"
+  path: /
+  hosts:
+    - chart-example.local
+  tls: []
+  #  - secretName: chart-example-tls
+  #    hosts:
+  #      - chart-example.local
+
+plexPreferences:
+  # Enable init script that will read all environment variables starting with PLEX_PREFERENCE_
+  # and take the value (of PLEX_PREFERENCE_<whatever>) as the Key:Value option to set in Plex Preference.xml
+  # You can use extraEnv to add the addtional ENV's to the container.
+  # NOTE: Plex preference options are camelCase and CASE SENSITIVE!
+  # You can do horrible things to your PLEX configuration if you are not careful.
+  # --set extraEnv.PLEX_PREFERENCE_1="FriendlyName=plex-kubeernetes-test1" `
+  # --set extraEnv.PLEX_PREFERENCE_2="EnableIPv6=0" `
+  # --set extraEnv.PLEX_PREFERENCE_3="logDebug=0" `
+  # --set extraEnv.PLEX_PREFERENCE_4="DisableTLSv1_0=1" `
+  # --set extraEnv.PLEX_PREFERENCE_5="LanNetworksBandwidth=xxx.xxx.xxx.0/18\,xxx.xxx.xxx.0/24\,xxx.xxx.xxx.0/24" `
+  # --set extraEnv.PLEX_PREFERENCE_6="TranscoderQuality=2" `
+  # --set extraEnv.PLEX_PREFERENCE_7="TreatWanIpAsLocal=0" `
+  # --set extraEnv.PLEX_PREFERENCE_8="TranscoderH264BackgroundPreset=fast"
+  # Why not use a single ENV?
+  #      I thought using multiple environment variables would be less confusing
+  #      It should work easily with CLI and value.yaml usage
+  #      There is only minimal parsing required on the ENV value, as the only deliminator is =
+  #      From what I can see, all the PLEX preferences that are NOT currently supported by the OFFICIAL
+  #      Container are simple enough to work with this.
+  enabled: false
+  configmap:
+    labels: {}
+    annotations: {}
+    # Right now you can't really change this, additionally the configmap data is
+    # not configurable.
+    name: 41-plex-preferences
+  volume:
+    name: 41-plex-preferences
+    defaultMode: 493  # 0755 in octal permission notation
+    # Using mountPath & SubPath allow you to volume mount a configMap AS A FILE
+    # Unfortunately this also means that updates to the configMap are not automtically
+    # propagated to the file contents. But it's better then replacing the entire
+    # /etc/cont-init.d/ directory which is the "normal" behavior when doing volume
+    # mounts.
+    mountPath: /etc/cont-init.d/41-plex-preferences
+    subPath: 41-plex-preferences
+
+hostNetwork: false
+
+persistence:
+  transcode:
+    # We want to enable a transcode pvc
+    enabled: false
+    # Optionally specify claimName to manually override the PVC to be used for
+    # the transcode directory. If claimName is specified, storageClass and size
+    # are ignored.
+    ## claimName: "plex-transcode-pvc"
+    # Optionally specify a storage class to be used for the transcode directory.
+    # If not specified and claimName is not specified, the default storage
+    # class will be used.
+    storageClass: ""
+    # subPath: some-subpath
+    # The requested size of the volume to be used when creating a
+    # PersistentVolumeClaim.
+    size: 20Gi
+    # Access mode for this volume
+    accessMode: ReadWriteOnce
+    # If not using a transcode PVC, specify emptyDir.medium="Memory" to use a tmpfs (in-memory)
+    # Volume for /transcode. Warning! this will greatly increase the amount of memory the plex pod is using
+    # AND it will count toward any ram pod/namespace limits. Additionally all data will be lost if/when the
+    # pod is moved to another node. --set persistence.transcode.emptyDir.medium="Memory" `
+    emptyDir:
+      medium: ""
+  #   medium: "Memory"
+
+
+  data:
+    # We want to enable a data pvc
+    enabled: true
+    # Optionally specify claimName to manually override the PVC to be used for
+    # the data directory. If claimName is specified, storageClass and size are
+    # ignored.
+    ## claimName: "plex-data-pvc"
+    # Optionally specify a storage class to be used for the data directory.
+    # If not specified and claimName is not specified, the default storage
+    # class will be used.
+    storageClass: ""
+    # subPath: some-subpath
+    # The requested size of the volume to be used when creating a
+    # PersistentVolumeClaim.
+    size: 40Gi
+    # Access mode for this volume
+    accessMode: ReadWriteOnce
+
+  extraData: []
+    # Optionally specifify additional Data mounts.  These will be mounted as
+    # /data-${name}.  This should be in the same format as the above 'data',
+    # with the additional field 'name'
+    # - claimName: "special-tv"
+    #   name: 'foo'
+    #   subPath: optional/sub/path
+
+  extraMounts: []
+  ## Include additional claims that can be mounted inside the
+  ## pod. This is useful if you wish to use different paths with categories
+  ## Claim will me mounted as /{mountPath} if specified. If no {mountPath} is given,
+  ## mountPath will default to {name}
+  # - name: video
+  #   # if claimName is specified the a new volume will mounted, if omitted the mount will be considered to be associated with one of the standard volumes (e.g data, config, transcode).
+  #   # This useful to mount data to a different subPath
+  #   claimName: optional-claim
+  #   mountPath: /mnt/path/in/pod
+  #   subPath: optional/sub/path
+
+  config:
+    # Optionally specify claimName to manually override the PVC to be used for
+    # the config directory. If claimName is specified, storageClass and size
+    # are ignored.
+    ## claimName: "plex-config-pvc"
+    # Optionally specify a storage class to be used for the config directory.
+    # If not specified and claimName is not specified, the default storage
+    # class will be used.
+    # subPath: some-subpath
+    storageClass: ""
+    # The requested size of the volume to be used when creating a
+    # PersistentVolumeClaim.
+    size: 20Gi
+    # Access mode for this volume
+    accessMode: ReadWriteOnce
+
+# Certificate(s) in Plex
+certificate:
+  # Assuming you have a kubernetes certificate secret (say from cert-manager) that has a tls.crt and tls.key but NO PFX!
+  # pkcsMangler to the rescue. The pkcsMangler part will add the supplied pfxPassword to a kubernetes secret
+  # This is so it's not in the clear in the YAML of the deployment in the kubernetes api.
+  # We will then use an OpenSSL init container to create a pfx file using the supplied secret (only available in container)
+  # Then we will use an init script (via configMap) to move the pfx file out of /shared (it's temporary storage) to
+  # the location specified in pfxInContainerPath.
+  pkcsMangler:
+    enabled: false
+    # The Image to use for pkcsMangler
+    image:
+      repository: tlsprint/openssl
+      tag: 1.1.1f
+    configmap:
+      labels: {}
+      annotations: {}
+      # Right now you can't really change this, additionally the configmap data is
+      # not configurable.
+      name: 42-pkcs-mangler
+    volume:
+      name: 42-pkcs-mangler
+      defaultMode: 493  # 0755 in octal permission notation
+      # Using mountPath & SubPath allow you to volume mount a configMap AS A FILE
+      # Unfortunately this also means that updates to the configMap are not automtically
+      # propagated to the file contents. But it's better then replacing the entire
+      # /etc/cont-init.d/ directory which is the "normal" behavior when doing volume
+      # mounts.
+      mountPath: /etc/cont-init.d/42-pkcs-mangler
+      subPath: 42-pkcs-mangler
+    setPlexPreferences:
+      enabled: true  # Set Plex Preferences related to Certificates
+      customCertificateDomain: ""  # If not empty, Set the Plex Preference customCertificateDomain
+      # Use spec.certificate.pkcsMangler.pfxPassword.value to Set the Plex Preference customCertificateKey
+      # Use spec.certificate.pkcsMangler.pfxInContainerPath to Set the Plex Preference customCertificatePath
+    pfxPassword:
+      value: "setpassword"
+      # We wlll create a Kubernetes Secret for spec.certificate.pkcsMangler.pfxPassword.value
+      # These are your options.
+      secretName: "plex-media-server-pfx-password"
+      passwordKey: "pfx-password"
+      labels: {}
+      annotations: {}
+    pfxInContainerPath: "/config/plex.pfx"  # This is full path in the container pkcsMangler will copy the pfx file to
+    # This is the SSL Certificate Secret that will provide our crt and key file.  If you used cert-manager to create
+    # the certificate, these defaults should work for you.  This Secret (and volume details) are only used by the
+    # pkcsMangler Init Container.
+    certificateSecret:
+      name: ""
+      keyName: "tls.key"
+      crtName: "tls.crt"
+      volume:
+        name: plex-certs
+        mountPath: /etc/plex-certs
+
+# Logging configuration
+logging:
+  promtail:
+    enabled: false
+    image:
+      repository: grafana/promtail
+      tag: 1.6.0
+      pullPolicy: IfNotPresent
+    loki:
+      url: http://loki.logs.svc.cluster.local:3100/loki/api/v1/push
+
+# Probes configuration
+probes:
+  liveness:
+    failureThreshold: 5
+    periodSeconds: 10
+  readiness:
+    failureThreshold: 5
+    periodSeconds: 10
+  startup:
+    initialDelaySeconds: 5
+    failureThreshold: 30
+    periodSeconds: 10
+
+resources: {}
+  # We usually recommend not to specify default resources and to leave this as a conscious
+  # choice for the user. This also increases chances charts run on environments with little
+  # resources, such as Minikube. If you do want to specify resources, uncomment the following
+  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+  # limits:
+  #   cpu: 100m
+  #   memory: 128Mi
+  # requests:
+  #   cpu: 100m
+  #   memory: 128Mi
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+podAnnotations: {}
+
+deploymentAnnotations: {}
+
+proxy:
+  # This allows to set a proxy environment variable, which PMS uses to fetch the token and assets like movie cover
+  enabled: false
+  # http: "http://proxy:8080"
+  # https: "https://proxy:8080"
+  # noproxy: "localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/12"