diff --git a/catalog.json b/catalog.json index 5126f697c5..260d5a90d9 100644 --- a/catalog.json +++ b/catalog.json @@ -673,6 +673,33 @@ "tags": [], "icon_url": "https://avatars.githubusercontent.com/u/48932923" }, + "jellyfin": { + "app_readme": "

Jellyfin

\n

Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media.

\n
\n

When application is installed, a container will be launched with root privileges.\nThis is required in order to apply the correct permissions to the Jellyfin directories.\nAfterward, the Jellyfin container will run as a non-root user (Default: 568).\nAll mounted storage(s) will be chowned only if the parent directory does not match the configured user.

\n
", + "categories": [ + "media", + "streaming" + ], + "description": "Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media.", + "healthy": true, + "healthy_error": null, + "location": "/__w/charts/charts/community/jellyfin", + "latest_version": "1.0.0", + "latest_app_version": "10.8.10", + "latest_human_version": "10.8.10_1.0.0", + "last_update": null, + "name": "jellyfin", + "recommended": false, + "title": "Jellyfin", + "maintainers": [ + { + "name": "truenas", + "url": "https://www.truenas.com/", + "email": "dev@ixsystems.com" + } + ], + "tags": [], + "icon_url": "https://jellyfin.org/images/logo.svg" + }, "sonarr": { "app_readme": "

Sonarr

\n

Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them.

\n
\n

When application is installed, a container will be launched with root privileges.\nThis is required in order to apply the correct permissions to the Sonarr directories.\nAfterward, the Sonarr container will run as a non-root user (Default: 568).\nAll mounted storage(s) will be chowned only if the parent directory does not match the configured user.

\n
", "categories": [ diff --git a/community/jellyfin/1.0.0/Chart.lock b/community/jellyfin/1.0.0/Chart.lock new file mode 100644 index 0000000000..126ed7af98 --- /dev/null +++ b/community/jellyfin/1.0.0/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: file://../../../common + version: 1.0.6 +digest: sha256:2f1f31c15fb7f92db141a66adbb8d23a8598727730050a3883a211763a4e5472 +generated: "2023-04-20T01:44:20.846268287+03:00" diff --git a/community/jellyfin/1.0.0/Chart.yaml b/community/jellyfin/1.0.0/Chart.yaml new file mode 100644 index 0000000000..2ca1311019 --- /dev/null +++ b/community/jellyfin/1.0.0/Chart.yaml @@ -0,0 +1,26 @@ +name: jellyfin +description: Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. +annotations: + title: Jellyfin +type: application +version: 1.0.0 +apiVersion: v2 +appVersion: '10.8.10' +kubeVersion: '>=1.16.0-0' +maintainers: + - name: truenas + url: https://www.truenas.com/ + email: dev@ixsystems.com +dependencies: + - name: common + repository: file://../../../common + version: 1.0.6 +home: https://jellyfin.org/ +icon: https://jellyfin.org/images/logo.svg +sources: + - https://hub.docker.com/r/jellyfin/jellyfin + - https://github.com/truenas/charts/tree/master/community/jellyfin + - https://jellyfin.org/ +keywords: + - media + - streaming diff --git a/community/jellyfin/1.0.0/README.md b/community/jellyfin/1.0.0/README.md new file mode 100644 index 0000000000..e6cc2f8b26 --- /dev/null +++ b/community/jellyfin/1.0.0/README.md @@ -0,0 +1,8 @@ +# Jellyfin + +[Jellyfin](https://jellyfin.org/) is a Free Software Media System that puts you in control of managing and streaming your media. + +> When application is installed, a container will be launched with **root** privileges. +> This is required in order to apply the correct permissions to the `Jellyfin` directories. +> Afterward, the `Jellyfin` container will run as a **non**-root user (Default: `568`). +> All mounted storage(s) will be `chown`ed only if the parent directory does not match the configured user. diff --git a/community/jellyfin/1.0.0/app-readme.md b/community/jellyfin/1.0.0/app-readme.md new file mode 100644 index 0000000000..e6cc2f8b26 --- /dev/null +++ b/community/jellyfin/1.0.0/app-readme.md @@ -0,0 +1,8 @@ +# Jellyfin + +[Jellyfin](https://jellyfin.org/) is a Free Software Media System that puts you in control of managing and streaming your media. + +> When application is installed, a container will be launched with **root** privileges. +> This is required in order to apply the correct permissions to the `Jellyfin` directories. +> Afterward, the `Jellyfin` container will run as a **non**-root user (Default: `568`). +> All mounted storage(s) will be `chown`ed only if the parent directory does not match the configured user. diff --git a/community/jellyfin/1.0.0/charts/common-1.0.6.tgz b/community/jellyfin/1.0.0/charts/common-1.0.6.tgz new file mode 100644 index 0000000000..701fac6117 Binary files /dev/null and b/community/jellyfin/1.0.0/charts/common-1.0.6.tgz differ diff --git a/community/jellyfin/1.0.0/ci/basic-values.yaml b/community/jellyfin/1.0.0/ci/basic-values.yaml new file mode 100644 index 0000000000..9a85f98574 --- /dev/null +++ b/community/jellyfin/1.0.0/ci/basic-values.yaml @@ -0,0 +1,22 @@ +jellyfinNetwork: + webPort: 31000 + +jellyfinRunAs: + user: 1000 + group: 1000 + +jellyfinStorage: + config: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/config + cache: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/cache + transcodes: + type: emptyDir + medium: Memory + size: 1Gi + +# TODO: Test on a GPU-enabled system +# jellyfinGPU: +# nvidia.com/gpu: 1 diff --git a/community/jellyfin/1.0.0/ci/extra-values.yaml b/community/jellyfin/1.0.0/ci/extra-values.yaml new file mode 100644 index 0000000000..db993b9465 --- /dev/null +++ b/community/jellyfin/1.0.0/ci/extra-values.yaml @@ -0,0 +1,22 @@ +jellyfinNetwork: + webPort: 31000 + +jellyfinStorage: + config: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/config + cache: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/cache + transcodes: + type: emptyDir + medium: '' + size: '' + + additionalStorages: + - type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/movies + mountPath: /movies + - type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/series + mountPath: /series diff --git a/community/jellyfin/1.0.0/ci/hostNet-values.yaml b/community/jellyfin/1.0.0/ci/hostNet-values.yaml new file mode 100644 index 0000000000..d85fc2ab77 --- /dev/null +++ b/community/jellyfin/1.0.0/ci/hostNet-values.yaml @@ -0,0 +1,13 @@ +jellyfinNetwork: + hostNetwork: true + +jellyfinStorage: + config: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/config + cache: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/cache + transcodes: + type: hostPath + hostPath: /mnt/{{ .Release.Namespace }}/transcodes diff --git a/community/jellyfin/1.0.0/ix_values.yaml b/community/jellyfin/1.0.0/ix_values.yaml new file mode 100644 index 0000000000..7ddfbd3257 --- /dev/null +++ b/community/jellyfin/1.0.0/ix_values.yaml @@ -0,0 +1,36 @@ +image: + repository: jellyfin/jellyfin + pullPolicy: IfNotPresent + tag: '10.8.10' + +resources: + limits: + cpu: 4000m + memory: 8Gi + +jellyfinConfig: + publishedServerUrl: '' + additionalEnvs: [] +jellyfinGPU: {} +jellyfinNetwork: + webPort: 30000 + hostNetwork: false +jellyfinRunAs: + user: 568 + group: 568 +jellyfinStorage: + config: + type: ixVolume + hostPath: '' + datasetName: config + cache: + type: ixVolume + hostPath: '' + datasetName: cache + transcodes: + type: ixVolume + hostPath: '' + datasetName: transcodes + medium: '' + size: '' + additionalStorages: [] diff --git a/community/jellyfin/1.0.0/metadata.yaml b/community/jellyfin/1.0.0/metadata.yaml new file mode 100644 index 0000000000..d806ba85f0 --- /dev/null +++ b/community/jellyfin/1.0.0/metadata.yaml @@ -0,0 +1,8 @@ +runAsContext: + - userName: jellyfin + groupName: jellyfin + gid: 568 + uid: 568 + description: Jellyfin runs as any non-root user. +capabilities: [] +hostMounts: [] diff --git a/community/jellyfin/1.0.0/questions.yaml b/community/jellyfin/1.0.0/questions.yaml new file mode 100644 index 0000000000..6b7fa028bd --- /dev/null +++ b/community/jellyfin/1.0.0/questions.yaml @@ -0,0 +1,337 @@ +groups: + - name: Jellyfin Configuration + description: Configure Jellyfin + - name: User and Group Configuration + description: Configure User and Group for Jellyfin + - name: Network Configuration + description: Configure Network for Jellyfin + - name: Storage Configuration + description: Configure Storage for Jellyfin + - name: Resources Configuration + description: Configure Resources for Jellyfin + +portals: + web_portal: + protocols: + - "$kubernetes-resource_configmap_portal_protocol" + host: + - "$kubernetes-resource_configmap_portal_host" + ports: + - "$kubernetes-resource_configmap_portal_port" + path: "$kubernetes-resource_configmap_portal_path" + +questions: + - variable: jellyfinConfig + label: "" + group: Jellyfin Configuration + schema: + type: dict + attrs: + - variable: publishServerUrl + label: Published Server URL + description: Optional - The URL that Jellyfin will be advertised. + schema: + type: string + default: "" + - variable: additionalEnvs + label: Additional Environment Variables + description: Configure additional environment variables for Jellyfin. + schema: + type: list + default: [] + items: + - variable: env + label: Environment Variable + schema: + type: dict + attrs: + - variable: name + label: Name + schema: + type: string + required: true + - variable: value + label: Value + schema: + type: string + required: true + + - variable: jellyfinRunAs + label: "" + group: User and Group Configuration + schema: + type: dict + attrs: + - variable: user + label: User ID + description: The user id that Jellyfin will run as. + schema: + type: int + min: 2 + default: 568 + required: true + - variable: group + label: Group ID + description: The group id that Jellyfin will run as. + schema: + type: int + min: 2 + default: 568 + required: true + + - variable: jellyfinNetwork + label: "" + group: Network Configuration + schema: + type: dict + attrs: + - variable: webPort + label: Web Port + description: The port for the Jellyfin Web UI. + schema: + type: int + default: 30000 + min: 9000 + max: 65535 + required: true + - variable: hostNetwork + label: Host Network + description: | + Bind to the host network. While it's recommended to keep this disabled.
+ It's required for autodiscovery to work. + schema: + type: boolean + default: false + + - variable: jellyfinStorage + label: "" + group: Storage Configuration + schema: + type: dict + attrs: + - variable: config + label: Jellyfin Config Storage + description: The path to store Jellyfin Configuration. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "config" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: cache + label: Jellyfin Cache Storage + description: The path to store Jellyfin Cache. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "cache" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: transcodes + label: Jellyfin Transcodes Storage + description: The path to store Jellyfin Transcodes. + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system.
+ emptyDir: Is a temporary directory that will be created on the disk or in memory. + schema: + type: string + required: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - value: "emptyDir" + description: emptyDir (Temporary directory created on the disk or in memory) + - variable: datasetName + label: Dataset Name + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + hidden: true + immutable: true + default: "transcodes" + $ref: + - "normalize/ixVolume" + - variable: hostPath + label: Host Path + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + immutable: true + required: true + - variable: medium + label: emptyDir Medium + description: | + Disk: Creates a temporary directory on the disk.
+ Memory: Creates a temporary directory in memory. + schema: + type: string + show_if: [["type", "=", "emptyDir"]] + default: "" + enum: + - value: "" + description: Disk (Temporary directory created on the disk) + - value: "Memory" + description: Memory (Temporary directory created in memory) + - variable: size + label: emptyDir Size Limit + description: | + The maximum size of the temporary directory.
+ For example: 2Gi + schema: + type: string + show_if: [["type", "=", "emptyDir"]] + default: "2Gi" + + - variable: additionalStorages + label: Additional Storage + description: Additional storage for Jellyfin. + schema: + type: list + default: [] + items: + - variable: storageEntry + label: Storage Entry + schema: + type: dict + attrs: + - variable: type + label: Type + description: | + ixVolume: Is dataset created automatically by the system.
+ Host Path: Is a path that already exists on the system. + schema: + type: string + required: true + default: "ixVolume" + enum: + - value: "hostPath" + description: Host Path (Path that already exists on the system) + - value: "ixVolume" + description: ixVolume (Dataset created automatically by the system) + - variable: mountPath + label: Mount Path + description: The path inside the container to mount the storage. + schema: + type: path + required: true + - variable: hostPath + label: Host Path + description: The host path to use for storage. + schema: + type: hostpath + show_if: [["type", "=", "hostPath"]] + required: true + - variable: datasetName + label: Dataset Name + description: The name of the dataset to use for storage. + schema: + type: string + show_if: [["type", "=", "ixVolume"]] + required: true + immutable: true + default: "storage_entry" + $ref: + - "normalize/ixVolume" + + - variable: resources + group: Resources Configuration + label: "" + schema: + type: dict + attrs: + - variable: limits + label: Limits + schema: + type: dict + attrs: + - variable: cpu + label: CPU + description: CPU limit for Jellyfin. + schema: + type: string + default: "4000m" + required: true + - variable: memory + label: Memory + description: Memory limit for Jellyfin. + schema: + type: string + default: "8Gi" + required: true + + - variable: jellyfinGPU + group: Resources Configuration + label: GPU Configuration + schema: + type: dict + $ref: + - "definitions/gpuConfiguration" + attrs: [] diff --git a/community/jellyfin/1.0.0/templates/NOTES.txt b/community/jellyfin/1.0.0/templates/NOTES.txt new file mode 100644 index 0000000000..ba4e01146c --- /dev/null +++ b/community/jellyfin/1.0.0/templates/NOTES.txt @@ -0,0 +1 @@ +{{ include "ix.v1.common.lib.chart.notes" $ }} diff --git a/community/jellyfin/1.0.0/templates/_jellyfin.tpl b/community/jellyfin/1.0.0/templates/_jellyfin.tpl new file mode 100644 index 0000000000..b16526e79b --- /dev/null +++ b/community/jellyfin/1.0.0/templates/_jellyfin.tpl @@ -0,0 +1,136 @@ +{{- define "jellyfin.workload" -}} +workload: + jellyfin: + enabled: true + primary: true + type: Deployment + podSpec: + hostNetwork: {{ .Values.jellyfinNetwork.hostNetwork }} + containers: + jellyfin: + enabled: true + primary: true + imageSelector: image + securityContext: + runAsUser: {{ .Values.jellyfinRunAs.user }} + runAsGroup: {{ .Values.jellyfinRunAs.group }} + env: + {{ with .Values.jellyfinConfig.publishedServerUrl }} + JELLYFIN_PublishedServerUrl: {{ . | quote }} + {{ end }} + {{ with .Values.jellyfinConfig.additionalEnvs }} + {{ range $env := . }} + {{ $env.name }}: {{ $env.value }} + {{ end }} + {{ end }} + probes: + liveness: + enabled: true + type: http + port: 8096 + path: /health + readiness: + enabled: true + type: http + port: 8096 + path: /health + startup: + enabled: true + type: http + port: 8096 + path: /health + initContainers: + {{- include "ix.v1.common.app.permissions" (dict "containerName" "01-permissions" + "UID" .Values.jellyfinRunAs.user + "GID" .Values.jellyfinRunAs.group + "mode" "check" + "type" "init") | nindent 8 }} + +{{/* Service */}} +service: + jellyfin: + enabled: true + primary: true + type: NodePort + targetSelector: jellyfin + ports: + webui: + enabled: true + primary: true + port: {{ .Values.jellyfinNetwork.webPort }} + nodePort: {{ .Values.jellyfinNetwork.webPort }} + targetPort: 8096 + targetSelector: jellyfin + +{{/* Persistence */}} +persistence: + config: + enabled: true + type: {{ .Values.jellyfinStorage.config.type }} + datasetName: {{ .Values.jellyfinStorage.config.datasetName | default "" }} + hostPath: {{ .Values.jellyfinStorage.config.hostPath | default "" }} + targetSelector: + jellyfin: + jellyfin: + mountPath: /config + 01-permissions: + mountPath: /mnt/directories/config + cache: + enabled: true + type: {{ .Values.jellyfinStorage.cache.type }} + datasetName: {{ .Values.jellyfinStorage.cache.datasetName | default "" }} + hostPath: {{ .Values.jellyfinStorage.cache.hostPath | default "" }} + targetSelector: + jellyfin: + jellyfin: + mountPath: /cache + 01-permissions: + mountPath: /mnt/directories/cache + transcode: + enabled: true + type: {{ .Values.jellyfinStorage.transcodes.type }} + datasetName: {{ .Values.jellyfinStorage.transcodes.datasetName | default "" }} + hostPath: {{ .Values.jellyfinStorage.transcodes.hostPath | default "" }} + medium: {{ .Values.jellyfinStorage.transcodes.medium | default "" }} + {{/* Size of the emptyDir */}} + size: {{ .Values.jellyfinStorage.transcodes.size | default "" }} + targetSelector: + jellyfin: + jellyfin: + mountPath: /config/transcodes + {{ if ne .Values.jellyfinStorage.transcodes.type "emptyDir" }} + 01-permissions: + mountPath: /mnt/directories/transcodes + {{ end }} + tmp: + enabled: true + type: emptyDir + targetSelector: + jellyfin: + jellyfin: + mountPath: /tmp + {{- range $idx, $storage := .Values.jellyfinStorage.additionalStorages }} + {{ printf "jellyfin-%v" (int $idx) }}: + enabled: true + type: {{ $storage.type }} + datasetName: {{ $storage.datasetName | default "" }} + hostPath: {{ $storage.hostPath | default "" }} + targetSelector: + jellyfin: + jellyfin: + mountPath: {{ $storage.mountPath }} + 01-permissions: + mountPath: /mnt/directories{{ $storage.mountPath }} + {{- end }} +{{ with .Values.jellyfinGPU }} + {{ if gt (. | len) 1 }} + {{- fail "Jellyfin - Max [1] GPUs allowed" -}} + {{ end }} +scaleGPU: + - gpu: + {{ . | keys | first }}: {{ . | values | first }} + targetSelector: + jellyfin: + - jellyfin +{{ end }} +{{- end -}} diff --git a/community/jellyfin/1.0.0/templates/_portal.tpl b/community/jellyfin/1.0.0/templates/_portal.tpl new file mode 100644 index 0000000000..73e6083a7b --- /dev/null +++ b/community/jellyfin/1.0.0/templates/_portal.tpl @@ -0,0 +1,12 @@ +{{- define "jellyfin.portal" -}} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: portal +data: + path: "/" + port: {{ .Values.jellyfinNetwork.webPort | quote }} + protocol: http + host: $node_ip +{{- end -}} diff --git a/community/jellyfin/1.0.0/templates/common.yaml b/community/jellyfin/1.0.0/templates/common.yaml new file mode 100644 index 0000000000..ee3c3a7796 --- /dev/null +++ b/community/jellyfin/1.0.0/templates/common.yaml @@ -0,0 +1,9 @@ +{{- include "ix.v1.common.loader.init" . -}} + +{{/* Merge the templates with Values */}} +{{- $_ := mustMergeOverwrite .Values (include "jellyfin.workload" $ | fromYaml) -}} + +{{/* Create the configmap for portal manually*/}} +{{- include "jellyfin.portal" $ -}} + +{{- include "ix.v1.common.loader.apply" . -}} diff --git a/community/jellyfin/item.yaml b/community/jellyfin/item.yaml new file mode 100644 index 0000000000..a5fbb69e6b --- /dev/null +++ b/community/jellyfin/item.yaml @@ -0,0 +1,4 @@ +icon_url: https://jellyfin.org/images/logo.svg +categories: + - media + - streaming