Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion charts/kube-plex/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
appVersion: 1.16.0.1226-7eb2c8f6f
description: Plex Media Server
name: kube-plex
version: 0.2.7
version: 0.2.11
keywords:
- plex
home: https://plex.tv/
Expand Down
12 changes: 12 additions & 0 deletions charts/kube-plex/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ The following tables lists the configurable parameters of the Plex chart and the
| `kubePlex.image.pullPolicy` | Image pull policy | `IfNotPresent` |
| `claimToken` | Plex Claim Token to authenticate your acount | `` |
| `timezone` | Timezone plex instance should run as, e.g. 'America/New_York' | `Europe/London` |
| `allowedNetworks` | List of IP addresses and networks that are allowed without auth' | `nil` |
| `changeConfigDirOwnership` | Instruct the Plex Media Server Container to Change the Configuration Directory Ownership | `nil` |
| `advertiseIp` | This adds to the list where the server advertises that it can be found.' | `nil` |
| `plexUid` | The user id of the plex user created inside the container' | `nil` |
| `plexGid` | The group id of the plex group created inside the container | `nil` |
| `extraEnv` | Pass arbitrary environment variables to the Plex container as a map. See values.yaml for details | `nil` |
| `service.type` | Kubernetes service type for the plex GUI/API | `ClusterIP` |
| `service.port` | Kubernetes port where the plex GUI/API is exposed| `32400` |
| `service.annotations` | Service annotations for the Plex GUI | `{}` |
Expand All @@ -29,12 +35,18 @@ The following tables lists the configurable parameters of the Plex chart and the
| `ingress.tls` | Ingress TLS configuration | `[]` |
| `rbac.create` | Create RBAC roles? | `true` |
| `nodeSelector` | Node labels for pod assignment | `beta.kubernetes.io/arch: amd64` |
| `configMap.plexPreferences.enabled` | Enable init script(and load configMap) that will read all environment variables starting with PLEX_PREFERENCE_ | `false` |
| `configMap.plexPreferences.name` | Name of configMap | `41-plex-preferences` |
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would a user want to configure/override this, given that it's created/managed/controlled by the Helm chart anyway? From what I can tell, the user doesn't ever have a need to set/override the name of this ConfigMap (only needing to set the options within it)

| `configMap.plexPreferences.defaultMode` | Unix permissions in container (0755) | `493` |
| `configMap.plexPreferences.mountPath` | The full path to the file we will mount the configMap to | `/etc/cont-init.d/41-plex-preferences` |
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would someone want to customise these? Would it make more sense for us to set these appropriately always when the chart is installed? I'm conscious of exposing too many options and causing confusion, when instead the Helm chart should take care of non-relevant (to the user) bits like the mountPath, file mode etc.

| `configMap.plexPreferences.subPath` | And use subpath to mount it as an individual file not a volume | `41-plex-preferences` |
| `persistence.transcode.enabled` | Use persistent volume for transcoding | `false` |
| `persistence.transcode.size` | Size of persistent volume claim | `20Gi` |
| `persistence.transcode.claimName`| Use an existing PVC to persist data | `nil` |
| `persistence.transcode.subPath` | SubPath to use for existing Claim | `nil` |
| `persistence.transcode.storageClass` | Type of persistent volume claim | `-` |
| `persistence.transcode.accessMode` | Persistent volume access mode | `ReadWriteMany` |
| `persistence.transcode.emptyDir.medium` | Set this if you want to use tmpfs (in-memory) file system for /transcode | `Memory` |
| `persistence.data.size` | Size of persistent volume claim | `40Gi` |
| `persistence.data.claimName`| Use an existing PVC to persist data | `nil` |
| `persistence.data.subPath` | SubPath to use for existing Claim | `nil` |
Expand Down
57 changes: 57 additions & 0 deletions charts/kube-plex/configs/41-plex-preferences
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/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 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_IDENTIFIER="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"
18 changes: 18 additions & 0 deletions charts/kube-plex/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,21 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- 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 -}}
14 changes: 14 additions & 0 deletions charts/kube-plex/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{{- if .Values.configMap.plexPreferences.enabled -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.configMap.plexPreferences.name }}
labels:
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}

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 -}}
44 changes: 43 additions & 1 deletion charts/kube-plex/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,32 @@ spec:
- name: "NO_PROXY"
value: "{{.Values.proxy.noproxy}}"
{{- end }}
{{- end }}
# Official kube-plex container environment variables
{{- if .Values.advertiseIp }}
- name: "ADVERTISE_IP"
value: "{{.Values.advertiseIp}}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These vars seem unrelated to the PLEX_PREFERENCES bit right?

I'm a bit conscious that PLEX_PREFERENCES doesn't really 'protect' users from misconfigurations in any way, and could potentially lead to someone doing something 'bad' (e.g. setting ALLOWED_NETWORKS here, as well as setting PLEX_PREFERENCES_ALLOWED_NETWORKS).

Would it make more sense for us to remove PLEX_PREFERENCES_ and instead just add fields here for each preference we want to allow users to modify? If we have a standard pattern for how this is done, it should be trivial for us to extend the options we support in future

{{- end }}
{{- if .Values.changeConfigDirOwnership }}
- name: "CHANGE_CONFIG_DIR_OWNERSHIP"
value: "{{.Values.changeConfigDirOwnership}}"
{{- end }}
{{- if .Values.allowedNetworks }}
- name: "ALLOWED_NETWORKS"
value: "{{include "joinListWithComma" .Values.allowedNetworks}}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be simpler to just make this {{ .Values.allowedNetworks }} and require the user to specify a comma separated list, but it's not a particular big deal either way 😄 (although it makes things a little simpler and reduces the Helm templating magic, which could well come back to bite 😅)

{{- 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 }}
volumeMounts:
- name: data
Expand All @@ -156,13 +182,24 @@ spec:
{{- end }}
- name: shared
mountPath: /shared
{{- if .Values.configMap.plexPreferences.enabled }}
- name: {{ .Values.configMap.plexPreferences.name }}
mountPath: {{ .Values.configMap.plexPreferences.mountPath }}
subPath: {{ .Values.configMap.plexPreferences.subPath }}
{{- end }}
resources:
{{ toYaml .Values.resources | indent 10 }}
{{- if .Values.nodeSelector }}
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
volumes:
{{- if .Values.configMap.plexPreferences.enabled }}
- name: {{ .Values.configMap.plexPreferences.name }}
configMap:
name: {{ .Values.configMap.plexPreferences.name }}
defaultMode: {{ .Values.configMap.plexPreferences.defaultMode }}
{{- end }}
- name: data
persistentVolumeClaim:
{{- if .Values.persistence.data.claimName }}
Expand All @@ -186,7 +223,12 @@ spec:
claimName: "{{ template "fullname" . }}-transcode"
{{- end }}
{{- else }}
emptyDir: {}
{{- if .Values.persistence.transcode.emptyDir.medium }}
emptyDir:
medium: "{{ .Values.persistence.transcode.emptyDir.medium }}"
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}
{{- range .Values.persistence.extraData }}
- name: "extradata-{{ .name }}"
Expand Down
58 changes: 58 additions & 0 deletions charts/kube-plex/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,38 @@ claimToken: ""
# Set the timezone of the plex server
timezone: Europe/London

# 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

# You can add Additional ENV variables here
# The following is the same as --set extraEnv.TMPDIR="/transcode"
# extraEnv:
# TMPDIR: /transcode


service:
type: ClusterIP
port: 32400
Expand Down Expand Up @@ -63,8 +95,29 @@ rbac:
nodeSelector:
beta.kubernetes.io/arch: amd64

configMap:
# Enable init script that will read all environment variables starting with PLEX_PREFERENCE_
# and take the value as the Key:Value option to set in Plex Preference.xml
# You can use extraEnv to add the addtional ENV's to the container.
# --set extraEnv.PLEX_PREFERENCE_1="FriendlyName=plex-kube-plex-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"
plexPreferences:
enabled: false
name: 41-plex-preferences
defaultMode: 493
mountPath: /etc/cont-init.d/41-plex-preferences
subPath: 41-plex-preferences
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite understanding why options to change the name, mountpath, subpath or mode of this configmap are exposed here, nor why enabled is exposed either.

I'd expect the init script to not take any action if these PLEX_PREFERENCE vars are not set (i.e. the default), and I don't see anywhere/any reason why a user would want to provide their own ConfigMap to use instead of this one.

If we want to allow a user to inject arbitrary shell code that is executed before PMS starts, I think a dedicated variable that indicates what it is (i.e. preStartShellScript) would be clearer.

As an alternative way of structuring this values.yaml, what about if there was:

# An optional list of Plex Preferences.xml keys/values that will be set/updated before the Plex Media Server process starts.
plexPreferences:
  FriendlyName: plex-kube-plex-test1
  EnableIPv6: "0"
  logDebug: "0"

etc?


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.
Expand All @@ -79,6 +132,11 @@ persistence:
size: 20Gi
# Access mode for this volume
accessMode: ReadWriteMany
# 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.
# emptyDir:
# medium: "Memory"
data:
# Optionally specify claimName to manually override the PVC to be used for
# the data directory. If claimName is specified, storageClass and size are
Expand Down