Compare commits
No files matched your search
@@ -1,2 +0,0 @@
|
|||||||
owner: jellyfin
|
|
||||||
release-name-template: "{{ .Name }}-{{ .Version }}"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
||||||
"extends": [
|
|
||||||
"github>jellyfin/.github//renovate-presets/default"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
name: Bump Helm Chart Version
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
jellyfin_version:
|
|
||||||
description: 'Application version to set in Chart.yaml'
|
|
||||||
required: true
|
|
||||||
default: '1.0.0'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump-version:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5
|
|
||||||
with:
|
|
||||||
python-version: 3.x
|
|
||||||
|
|
||||||
- name: Bump chart version and set appVersion
|
|
||||||
id: bump_version
|
|
||||||
run: |
|
|
||||||
# Read the current version from the Chart.yaml
|
|
||||||
current_version=$(grep '^version:' charts/jellyfin/Chart.yaml | awk '{print $2}')
|
|
||||||
echo "Current version: $current_version"
|
|
||||||
|
|
||||||
# Split the version by dot and increment the minor version
|
|
||||||
major=$(echo "$current_version" | cut -d '.' -f 1)
|
|
||||||
minor=$(echo "$current_version" | cut -d '.' -f 2)
|
|
||||||
patch=$(echo "$current_version" | cut -d '.' -f 3)
|
|
||||||
new_version="$major.$((minor+1)).0"
|
|
||||||
|
|
||||||
echo "New chart version: $new_version"
|
|
||||||
|
|
||||||
# Get the app version passed as an input
|
|
||||||
jellyfin_version="${{ github.event.inputs.jellyfin_version }}"
|
|
||||||
echo "Setting appVersion to: $jellyfin_version"
|
|
||||||
|
|
||||||
# Update the Chart.yaml with the new version and appVersion
|
|
||||||
sed -i "s/^version:.*/version: $new_version/" charts/jellyfin/Chart.yaml
|
|
||||||
sed -i "s/^appVersion:.*/appVersion: $jellyfin_version/" charts/jellyfin/Chart.yaml
|
|
||||||
|
|
||||||
# Output the new chart version for further use
|
|
||||||
echo "new_version=$new_version" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Commit changes
|
|
||||||
run: |
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add charts/jellyfin/Chart.yaml
|
|
||||||
git commit -m "chore(jellyfin): Bump chart version to ${{ steps.bump_version.outputs.new_version }} and set appVersion to ${{ github.event.inputs.jellyfin_version }}"
|
|
||||||
|
|
||||||
- name: Push changes
|
|
||||||
uses: ad-m/github-push-action@master
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.JF_BOT_TOKEN }}
|
|
||||||
|
|
||||||
- name: Create Git tag
|
|
||||||
id: create_tag
|
|
||||||
run: |
|
|
||||||
new_version="${{ steps.bump_version.outputs.new_version }}"
|
|
||||||
git tag "$new_version"
|
|
||||||
echo "Tag created: $new_version"
|
|
||||||
|
|
||||||
- name: Push changes
|
|
||||||
uses: ad-m/github-push-action@master
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.JF_BOT_TOKEN }}
|
|
||||||
tags: true
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
name: Docs Update
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
generate-docs:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Helm Docs GitHub Action
|
|
||||||
uses: losisin/helm-docs-github-action@57d2dc9379d9f0d5d22d2845a62c935d32cddfe2 # v1.3.3
|
|
||||||
with:
|
|
||||||
git-push: true
|
|
||||||
git-commit-message: "docs(charts): :memo: write updated reademe"
|
|
||||||
|
|
||||||
- name: Push changes
|
|
||||||
run: git push
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
# depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions
|
|
||||||
# see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Configure Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name "jellyfin-bot"
|
|
||||||
git config --global user.email "team@jellyfin.org"
|
|
||||||
|
|
||||||
- name: Install Helm
|
|
||||||
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
|
|
||||||
- name: Run chart-releaser
|
|
||||||
uses: helm/chart-releaser-action@a917fd15b20e8b64b94d9158ad54cd6345335584 # v1.6.0
|
|
||||||
env:
|
|
||||||
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
with:
|
|
||||||
config: .github/cr.yaml
|
|
||||||
@@ -7,7 +7,7 @@ This repository contains Helm charts for the jellyfin project.
|
|||||||
Each Helm chart is stored in its own directory. Each chart follows the standard Helm chart structure:
|
Each Helm chart is stored in its own directory. Each chart follows the standard Helm chart structure:
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
hellyfin-helm/
|
jellyfin-helm/
|
||||||
├── jellyfin/
|
├── jellyfin/
|
||||||
│ ├── Chart.yaml
|
│ ├── Chart.yaml
|
||||||
│ ├── values.yaml
|
│ ├── values.yaml
|
||||||
@@ -32,7 +32,7 @@ hellyfin-helm/
|
|||||||
To use the charts in this repository, first add the repository to Helm:
|
To use the charts in this repository, first add the repository to Helm:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm repo add jellyfin https://<your-repo-url>.git
|
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
||||||
helm repo update
|
helm repo update
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# 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
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 1.4.0
|
|
||||||
description: Jellyfin Media Server
|
|
||||||
name: jellyfin
|
name: jellyfin
|
||||||
version: 1.4.0
|
description: A Helm chart for Jellyfin Media Server
|
||||||
type: application
|
type: application
|
||||||
home: https://jellyfin.org/
|
home: https://jellyfin.org/
|
||||||
icon: https://jellyfin.org/images/logo.svg
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
@@ -10,3 +8,33 @@ keywords:
|
|||||||
- jellyfin
|
- jellyfin
|
||||||
- media
|
- media
|
||||||
- self-hosted
|
- self-hosted
|
||||||
|
version: 3.0.0
|
||||||
|
appVersion: 10.11.5
|
||||||
|
annotations:
|
||||||
|
artifacthub.io/changes: |
|
||||||
|
- kind: deprecated
|
||||||
|
description: Deprecate initContainers parameter in favor of extraInitContainers for consistency (will be removed after 2030)
|
||||||
|
- kind: fixed
|
||||||
|
description: Fix extraInitContainers not working (was using wrong parameter name in template)
|
||||||
|
- kind: added
|
||||||
|
description: Add NetworkPolicy support for network isolation and security hardening
|
||||||
|
links:
|
||||||
|
- name: Documentation
|
||||||
|
url: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||||
|
description: Add troubleshooting documentation for inotify instance limits with workaround example
|
||||||
|
- kind: added
|
||||||
|
description: Add support for Gateway API HTTPRoute resource
|
||||||
|
- kind: added
|
||||||
|
description: Add envFrom support to load environment variables from ConfigMap or Secret
|
||||||
|
- kind: added
|
||||||
|
description: Add NOTES.txt with helpful post-installation information and deprecation warnings
|
||||||
|
- kind: added
|
||||||
|
description: Add startup probe to prevent pod restarts during slow initial startup with large media libraries
|
||||||
|
- kind: added
|
||||||
|
description: Add persistence.cache configuration for dedicated cache volume support
|
||||||
|
- kind: added
|
||||||
|
description: Add comprehensive IPv6 and dual-stack networking documentation
|
||||||
|
- kind: added
|
||||||
|
description: Add revisionHistoryLimit parameter to control rollback history retention (defaults to 3 instead of Kubernetes default 10)
|
||||||
|
- kind: changed
|
||||||
|
description: Improve health probe configuration examples for IPv6 compatibility
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Migration Guide
|
||||||
|
|
||||||
|
## v1.x to v2.x
|
||||||
|
|
||||||
|
### General
|
||||||
|
|
||||||
|
1. The `enableDLNA` key has been moved from the top level to the `jellyfin` subkey.
|
||||||
|
2. Some renames have occurred to align with the standard:
|
||||||
|
```yaml
|
||||||
|
extraPodLabels -> podLabels
|
||||||
|
extraPodAnnotations -> podAnnotations
|
||||||
|
```
|
||||||
|
3. The `extraEnvVars` key has been moved and renamed to `jellyfin.env`.
|
||||||
|
4. `extraVolumes` has been moved to `volumes`, and `extraVolumeMounts` has been moved to `volumeMounts`.
|
||||||
|
5. The `extraExistingClaimMounts` key has been removed, as it can now be represented with `volumes` and `volumeMounts`.
|
||||||
|
|
||||||
|
### Service
|
||||||
|
|
||||||
|
1. The `name` field has been renamed to `portName` for consistency.
|
||||||
|
2. The following fields have been added:
|
||||||
|
```yaml
|
||||||
|
# -- Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/
|
||||||
|
ipFamilyPolicy: ""
|
||||||
|
# -- Supported IP families (IPv4, IPv6).
|
||||||
|
ipFamilies: []
|
||||||
|
# -- Class of the LoadBalancer.
|
||||||
|
loadBalancerClass: ""
|
||||||
|
# -- External traffic policy (Cluster or Local).
|
||||||
|
# externalTrafficPolicy: Cluster
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ingress
|
||||||
|
|
||||||
|
1. The `className` field has been added for ingress class, as annotations are deprecated.
|
||||||
|
2. The `path` field has been moved under the `hosts` key to better represent the actual CRD, providing more fine-grained control.
|
||||||
|
3. The `labels` field has been added for additional labels.
|
||||||
|
|
||||||
|
### Persistence
|
||||||
|
|
||||||
|
PVC creation is now enabled by default to prevent data loss when the chart is used without a specific configuration.
|
||||||
|
|
||||||
|
### Probes
|
||||||
|
|
||||||
|
The liveness and readiness probes are now always enabled to ensure proper Kubernetes lifecycle management. Adjust the values accordingly if you have a large library.
|
||||||
+414
-51
@@ -1,8 +1,8 @@
|
|||||||
# jellyfin
|
# jellyfin
|
||||||
|
|
||||||
  
|
  
|
||||||
|
|
||||||
Jellyfin Media Server
|
A Helm chart for Jellyfin Media Server
|
||||||
|
|
||||||
**Homepage:** <https://jellyfin.org/>
|
**Homepage:** <https://jellyfin.org/>
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ Jellyfin Media Server
|
|||||||
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm repo add <repo-name> <repo-url>
|
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Install the Helm Chart
|
### 2. Install the Helm Chart
|
||||||
@@ -21,7 +21,7 @@ helm repo add <repo-name> <repo-url>
|
|||||||
To install a chart, use the following command:
|
To install a chart, use the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <repo-name>/jellyfin
|
helm install my-jellyfin jellyfin/jellyfin
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. View the Installation
|
### 3. View the Installation
|
||||||
@@ -29,7 +29,7 @@ helm install <release-name> <repo-name>/jellyfin
|
|||||||
You can check the status of the release using:
|
You can check the status of the release using:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm status <release-name>
|
helm status my-jellyfin
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customizing the Chart
|
## Customizing the Chart
|
||||||
@@ -38,72 +38,165 @@ Helm charts come with default values, but you can customize them by using the --
|
|||||||
|
|
||||||
### 1. Using --set to Override Values
|
### 1. Using --set to Override Values
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <chart-name> --set key1=value1,key2=value2
|
helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Using a values.yaml File
|
### 2. Using a values.yaml File
|
||||||
You can create a custom values.yaml file and pass it to the install command:
|
You can create a custom values.yaml file and pass it to the install command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <chart-name> -f values.yaml
|
helm install my-jellyfin jellyfin/jellyfin -f values.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Values
|
## Values
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
| Key | Type | Default | Description |
|
||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| affinity | object | `{}` | |
|
| affinity | object | `{}` | Affinity rules for pod scheduling. |
|
||||||
| enableDLNA | bool | `false` | Setting this to true enables DLNA which requires the pod to be attached to the host network in order to be useful - this can break things like ingress to the service https://jellyfin.org/docs/general/networking/dlna.html |
|
| deploymentAnnotations | object | `{}` | Annotations to add to the deployment. |
|
||||||
|
| deploymentStrategy | object | `{"type":"RollingUpdate"}` | Deployment strategy configuration. See `kubectl explain deployment.spec.strategy`. |
|
||||||
|
| dnsConfig | object | `{}` | Define a dnsConfig. See https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config Use this to provide a custom DNS resolver configuration |
|
||||||
|
| dnsPolicy | string | `""` | Define a dnsPolicy. See https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy |
|
||||||
| extraContainers | list | `[]` | additional sidecar containers to run inside the pod. |
|
| extraContainers | list | `[]` | additional sidecar containers to run inside the pod. |
|
||||||
| extraEnvVars | list | `[]` | aditional environment variables passed to the pod |
|
| extraInitContainers | list | `[]` | Additional init containers to run inside the pod. Init containers run before the main application container starts. See: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ Example: extraInitContainers: - name: init-config image: busybox:1.35 command: ['sh', '-c', 'echo "Initializing..." && sleep 5'] volumeMounts: - name: config mountPath: /config |
|
||||||
| extraInitContainers | list | `[]` | additional init containers to run inside the pod. |
|
| fullnameOverride | string | `""` | Override the default full name of the chart. |
|
||||||
| extraPodAnnotations | object | `{}` | additional annotations applied to the pod |
|
| httpRoute | object | `{"annotations":{},"enabled":false,"hostnames":[],"parentRefs":[],"rules":[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]}` | HTTPRoute configuration for Gateway API. See: https://gateway-api.sigs.k8s.io/ |
|
||||||
| extraPodLabels | object | `{}` | additional pod labels. Not used as a selector label. |
|
| httpRoute.hostnames | list | `[]` | Hostnames to match for this HTTPRoute |
|
||||||
| extraVolumeMounts | list | `[]` | Define mount points for additional volumes. |
|
| httpRoute.parentRefs | list | `[]` | Gateway references to attach this HTTPRoute to |
|
||||||
| extraVolumes | list | `[]` | Define additional volumes to mount to the pod. |
|
| httpRoute.rules | list | `[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]` | Rules for routing traffic |
|
||||||
| fullnameOverride | string | `""` | |
|
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy (Always, IfNotPresent, or Never). |
|
||||||
| image.pullPolicy | string | `"IfNotPresent"` | |
|
| image.repository | string | `"docker.io/jellyfin/jellyfin"` | Container image repository for Jellyfin. |
|
||||||
| image.repository | string | `"docker.io/jellyfin/jellyfin"` | Set cutom repository for jellyfin image |
|
| image.tag | string | `""` | Jellyfin container image tag. Leave empty to automatically use the Chart's app version. |
|
||||||
| image.tag | string | `""` | Set jellyfin version which should be required since chart is updated with new versions automatically |
|
| imagePullSecrets | list | `[]` | Image pull secrets to authenticate with private repositories. See: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ |
|
||||||
| imagePullSecrets | list | `[]` | |
|
| ingress | object | `{"annotations":{},"className":"","enabled":false,"hosts":[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}],"tls":[]}` | Ingress configuration. See: https://kubernetes.io/docs/concepts/services-networking/ingress/ |
|
||||||
| ingress.annotations | object | `{}` | |
|
| initContainers | list | `[]` | DEPRECATED: Use extraInitContainers instead. Will be removed after 2030. @deprecated - This parameter is deprecated, use extraInitContainers instead |
|
||||||
| ingress.enabled | bool | `false` | |
|
| jellyfin.args | list | `[]` | Additional arguments for the entrypoint command. |
|
||||||
| ingress.hosts[0] | string | `"chart-example.local"` | |
|
| jellyfin.command | list | `[]` | Custom command to use as container entrypoint. |
|
||||||
| ingress.labels | object | `{}` | |
|
| jellyfin.enableDLNA | bool | `false` | Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html |
|
||||||
| ingress.path | string | `"/"` | |
|
| jellyfin.env | list | `[]` | Additional environment variables for the container. Example: Workaround for inotify limits (see Troubleshooting section in README) Example: env: - name: JELLYFIN_CACHE_DIR value: /cache |
|
||||||
| ingress.tls | list | `[]` | |
|
| jellyfin.envFrom | list | `[]` | Load environment variables from ConfigMap or Secret. See: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables Example: envFrom: - configMapRef: name: jellyfin-config - secretRef: name: jellyfin-secrets |
|
||||||
| livenessProbe | object | `{"enabled":true,"initialDelaySeconds":10}` | Larger libraries may need to increase the readinessProbe and livenessProbe timeouts. Start by increasing the initialDelaySeconds. |
|
| livenessProbe | object | `{"httpGet":{"path":"/health","port":"http"},"initialDelaySeconds":10}` | Configure liveness probe for Jellyfin. This probe is disabled during startup (startup probe handles initial checks). Uses httpGet for compatibility with both IPv4 and IPv6. |
|
||||||
| nameOverride | string | `""` | |
|
| metrics | object | `{"enabled":false,"serviceMonitor":{"enabled":false,"interval":"30s","labels":{},"metricRelabelings":[],"namespace":"","path":"/metrics","port":8096,"relabelings":[],"scheme":"http","scrapeTimeout":"30s","targetLabels":[],"tlsConfig":{}}}` | Configuration for metrics collection and monitoring |
|
||||||
| nodeSelector | object | `{}` | |
|
| metrics.enabled | bool | `false` | Enable or disable metrics collection |
|
||||||
|
| metrics.serviceMonitor | object | `{"enabled":false,"interval":"30s","labels":{},"metricRelabelings":[],"namespace":"","path":"/metrics","port":8096,"relabelings":[],"scheme":"http","scrapeTimeout":"30s","targetLabels":[],"tlsConfig":{}}` | Configuration for the Prometheus ServiceMonitor |
|
||||||
|
| metrics.serviceMonitor.enabled | bool | `false` | Enable or disable the creation of a ServiceMonitor resource |
|
||||||
|
| metrics.serviceMonitor.interval | string | `"30s"` | Interval at which metrics should be scraped |
|
||||||
|
| metrics.serviceMonitor.labels | object | `{}` | Labels to add to the ServiceMonitor resource |
|
||||||
|
| metrics.serviceMonitor.metricRelabelings | list | `[]` | Relabeling rules for the metrics before ingestion |
|
||||||
|
| metrics.serviceMonitor.namespace | string | `""` | Namespace where the ServiceMonitor resource should be created. Defaults to Release.Namespace |
|
||||||
|
| metrics.serviceMonitor.path | string | `"/metrics"` | Path to scrape for metrics |
|
||||||
|
| metrics.serviceMonitor.port | int | `8096` | Port to scrape for metrics |
|
||||||
|
| metrics.serviceMonitor.relabelings | list | `[]` | Relabeling rules for the scraped metrics |
|
||||||
|
| metrics.serviceMonitor.scheme | string | `"http"` | Scheme to use for scraping metrics (http or https) |
|
||||||
|
| metrics.serviceMonitor.scrapeTimeout | string | `"30s"` | Timeout for scraping metrics |
|
||||||
|
| metrics.serviceMonitor.targetLabels | list | `[]` | Target labels to add to the scraped metrics |
|
||||||
|
| metrics.serviceMonitor.tlsConfig | object | `{}` | TLS configuration for scraping metrics |
|
||||||
|
| nameOverride | string | `""` | Override the default name of the chart. |
|
||||||
|
| networkPolicy | object | `{"egress":{"allowAllEgress":true,"allowDNS":true,"customRules":[],"dnsNamespace":"kube-system","dnsPodSelector":{"k8s-app":"kube-dns"},"restrictedEgress":{"allowInCluster":true,"allowMetadata":true,"allowedCIDRs":[]}},"enabled":false,"ingress":{"allowExternal":true,"customRules":[],"namespaceSelector":{},"podSelector":{}},"metrics":{"namespace":"","podSelector":{"app.kubernetes.io/name":"prometheus"}},"policyTypes":["Ingress","Egress"]}` | Network Policy configuration for network isolation and security. Requires a CNI plugin that supports NetworkPolicy (Calico, Cilium, Weave, etc.). WARNING: NetworkPolicy cannot be enabled when hostNetwork is used (DLNA mode). The chart will fail with an error if both are enabled simultaneously. |
|
||||||
|
| networkPolicy.egress | object | `{"allowAllEgress":true,"allowDNS":true,"customRules":[],"dnsNamespace":"kube-system","dnsPodSelector":{"k8s-app":"kube-dns"},"restrictedEgress":{"allowInCluster":true,"allowMetadata":true,"allowedCIDRs":[]}}` | Egress rules configuration - controls what external connections Jellyfin can make. |
|
||||||
|
| networkPolicy.egress.allowAllEgress | bool | `true` | Allow all egress traffic (internet access for metadata, subtitles, images). When true, Jellyfin can connect to any external destination (0.0.0.0/0). This is the recommended default as Jellyfin needs internet access for: - Downloading movie/TV show metadata (TMDB, TheTVDB, OMDb) - Fetching poster images, fanart, and other artwork - Downloading subtitles (OpenSubtitles) - Updating plugins When false, you must configure restrictedEgress or customRules. |
|
||||||
|
| networkPolicy.egress.allowDNS | bool | `true` | Allow DNS resolution (required for Jellyfin to function). This adds an egress rule for kube-system namespace with kube-dns pods. DNS is required for resolving metadata provider domains and subtitle services. It is highly recommended to keep this enabled. |
|
||||||
|
| networkPolicy.egress.customRules | list | `[]` | Additional custom egress rules. Allows for complex scenarios not covered by the standard template. These rules are added as-is to the NetworkPolicy egress section. Example - allow connections to specific database: customRules: - to: - podSelector: matchLabels: app: postgresql ports: - protocol: TCP port: 5432 |
|
||||||
|
| networkPolicy.egress.dnsNamespace | string | `"kube-system"` | DNS namespace where DNS service is running. Usually "kube-system" but can differ in some Kubernetes distributions. |
|
||||||
|
| networkPolicy.egress.dnsPodSelector | object | `{"k8s-app":"kube-dns"}` | DNS pod selector labels. Default selector is for kube-dns, but CoreDNS or other DNS providers may use different labels. Adjust if needed. Common alternatives: k8s-app: kube-dns (default) k8s-app: coredns app.kubernetes.io/name: coredns |
|
||||||
|
| networkPolicy.egress.restrictedEgress | object | `{"allowInCluster":true,"allowMetadata":true,"allowedCIDRs":[]}` | Restricted egress mode for security-conscious deployments. Only used when allowAllEgress is false. Provides fine-grained control over outbound connections. |
|
||||||
|
| networkPolicy.egress.restrictedEgress.allowInCluster | bool | `true` | Allow communication within the cluster (pod-to-pod). Useful if Jellyfin needs to connect to other services in the cluster. This allows connections to any pod in any namespace. |
|
||||||
|
| networkPolicy.egress.restrictedEgress.allowMetadata | bool | `true` | Allow HTTPS (443/TCP) for metadata providers. Most metadata providers (TMDB, TheTVDB, OpenSubtitles, Fanart.tv) use HTTPS, so this covers the majority of use cases. This allows connections to any IP on port 443. |
|
||||||
|
| networkPolicy.egress.restrictedEgress.allowedCIDRs | list | `[]` | Additional IP CIDR blocks to allow egress. Useful for allowing specific IP ranges for metadata providers or other external services. Example - allow entire internet except private networks: allowedCIDRs: - 0.0.0.0/0 Example - allow specific metadata provider IP ranges: allowedCIDRs: - 13.224.0.0/14 # CloudFront (used by many CDNs) |
|
||||||
|
| networkPolicy.enabled | bool | `false` | Enable NetworkPolicy for the Jellyfin pod. By default, this is disabled to maintain backward compatibility. When enabled, you can control which pods can access Jellyfin (ingress) and what external connections Jellyfin can make (egress). |
|
||||||
|
| networkPolicy.ingress | object | `{"allowExternal":true,"customRules":[],"namespaceSelector":{},"podSelector":{}}` | Ingress rules configuration - controls which pods/namespaces can access Jellyfin. |
|
||||||
|
| networkPolicy.ingress.allowExternal | bool | `true` | Allow external access from any namespace and any pod. When true, any pod in the cluster can access Jellyfin (default behavior). When false, only pods matching podSelector/namespaceSelector can access. Set to false for production environments to restrict access. |
|
||||||
|
| networkPolicy.ingress.customRules | list | `[]` | Additional custom ingress rules. Allows for complex scenarios not covered by the standard template. These rules are added as-is to the NetworkPolicy ingress section. Example - allow from monitoring namespace: customRules: - from: - namespaceSelector: matchLabels: name: monitoring ports: - protocol: TCP port: 8096 |
|
||||||
|
| networkPolicy.ingress.namespaceSelector | object | `{}` | Namespace selector to allow cross-namespace ingress. Only used when allowExternal is false. Allows you to specify which namespaces can access Jellyfin. Example - only allow from ingress-nginx namespace: namespaceSelector: matchLabels: name: ingress-nginx |
|
||||||
|
| networkPolicy.ingress.podSelector | object | `{}` | Custom pod selector for allowed ingress traffic. Only used when allowExternal is false. Allows you to specify which pods can access Jellyfin based on labels. Example - only allow pods with specific label: podSelector: matchLabels: jellyfin-client: "true" |
|
||||||
|
| networkPolicy.metrics | object | `{"namespace":"","podSelector":{"app.kubernetes.io/name":"prometheus"}}` | Prometheus metrics scraping configuration. Automatically allows ingress from Prometheus when metrics.serviceMonitor.enabled is true. This ensures Prometheus can scrape metrics without additional configuration. |
|
||||||
|
| networkPolicy.metrics.namespace | string | `""` | Namespace where Prometheus is running. Leave empty to use the same namespace as Jellyfin. Set to the monitoring namespace if Prometheus is in a different namespace. Example: "monitoring" or "prometheus" |
|
||||||
|
| networkPolicy.metrics.podSelector | object | `{"app.kubernetes.io/name":"prometheus"}` | Pod selector for Prometheus pods. These labels must match your Prometheus deployment. The chart will automatically add an ingress rule for pods matching these labels. Default selector works with prometheus-operator and kube-prometheus-stack. Adjust if your Prometheus uses different labels. |
|
||||||
|
| networkPolicy.policyTypes | list | `["Ingress","Egress"]` | Policy types to enforce. Both ingress and egress policies can be enabled. See: https://kubernetes.io/docs/concepts/services-networking/network-policies/#policy-types |
|
||||||
|
| nodeSelector | object | `{}` | Node selector for pod scheduling. |
|
||||||
|
| persistence.cache.accessMode | string | `"ReadWriteOnce"` | PVC specific settings, only used if type is 'pvc'. |
|
||||||
|
| persistence.cache.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
||||||
|
| persistence.cache.enabled | bool | `false` | set to false to use emptyDir |
|
||||||
|
| persistence.cache.hostPath | string | `""` | Path on the host node for cache storage, only used if type is 'hostPath'. |
|
||||||
|
| persistence.cache.size | string | `"10Gi"` | |
|
||||||
|
| persistence.cache.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
||||||
|
| persistence.cache.type | string | `"pvc"` | Type of volume for cache storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting. |
|
||||||
| persistence.config.accessMode | string | `"ReadWriteOnce"` | |
|
| persistence.config.accessMode | string | `"ReadWriteOnce"` | |
|
||||||
| persistence.config.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
| persistence.config.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
||||||
| persistence.config.enabled | bool | `false` | |
|
| persistence.config.enabled | bool | `true` | set to false to use emptyDir |
|
||||||
| persistence.config.labels | object | `{}` | Custom labels to be added to the PVC |
|
| persistence.config.size | string | `"5Gi"` | |
|
||||||
| persistence.config.size | string | `"1Gi"` | |
|
| persistence.config.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
||||||
| persistence.config.storageClass | string | `"-"` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
| persistence.media.accessMode | string | `"ReadWriteOnce"` | PVC specific settings, only used if type is 'pvc'. |
|
||||||
| persistence.extraExistingClaimMounts | list | `[]` | Add aditional PVs/PVCs to our container. Check values.yaml to see an example. |
|
|
||||||
| persistence.media.accessMode | string | `"ReadWriteOnce"` | |
|
|
||||||
| persistence.media.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
| persistence.media.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
||||||
| persistence.media.enabled | bool | `false` | |
|
| persistence.media.enabled | bool | `true` | set to false to use emptyDir |
|
||||||
| persistence.media.labels | object | `{}` | Custom labels to be added to the PVC |
|
| persistence.media.hostPath | string | `""` | Path on the host node for media storage, only used if type is 'hostPath'. |
|
||||||
| persistence.media.size | string | `"10Gi"` | |
|
| persistence.media.size | string | `"25Gi"` | |
|
||||||
| persistence.media.storageClass | string | `"-"` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
| persistence.media.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. |
|
||||||
| podSecurityContext | object | `{}` | SecurityContext configuration for the Jellyfin pod |
|
| persistence.media.type | string | `"pvc"` | Type of volume for media storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting. |
|
||||||
| readinessProbe | object | `{"enabled":true,"initialDelaySeconds":10}` | Larger libraries may need to increase the readinessProbe and livenessProbe timeouts. Start by increasing the initialDelaySeconds. |
|
| podAnnotations | object | `{}` | Annotations to add to the pod. |
|
||||||
| replicaCount | int | `1` | Number of jellyfin replicas to start. Should be left at 1 |
|
| podLabels | object | `{}` | Additional labels to add to the pod. |
|
||||||
| resources | object | `{}` | |
|
| podPrivileges | object | `{"hostIPC":false,"hostNetwork":false,"hostPID":false}` | Privileged pod settings for advanced use cases |
|
||||||
| runtimeClassName | string | `nil` | |
|
| podPrivileges.hostIPC | bool | `false` | Enable hostIPC namespace. Required for NVIDIA MPS (Multi-Process Service) GPU sharing. See: https://docs.nvidia.com/deploy/mps/index.html |
|
||||||
| securityContext | object | `{}` | SecurityContext configuration for the Jellyfin container |
|
| podPrivileges.hostNetwork | bool | `false` | Enable hostNetwork. Allows pod to use the host's network namespace. |
|
||||||
| service.annotations | object | `{}` | |
|
| podPrivileges.hostPID | bool | `false` | Enable hostPID namespace. Allows pod to see processes on the host. |
|
||||||
| service.labels | object | `{}` | |
|
| podSecurityContext | object | `{}` | Security context for the pod. |
|
||||||
| service.loadBalancerIP | string | `nil` | |
|
| priorityClassName | string | `""` | Define a priorityClassName for the pod. |
|
||||||
| service.port | int | `8096` | |
|
| readinessProbe | object | `{"httpGet":{"path":"/health","port":"http"},"initialDelaySeconds":10}` | Configure readiness probe for Jellyfin. This probe is disabled during startup (startup probe handles initial checks). Uses httpGet for compatibility with both IPv4 and IPv6. |
|
||||||
| service.type | string | `"ClusterIP"` | |
|
| replicaCount | int | `1` | Number of Jellyfin replicas to start. Should be left at 1. |
|
||||||
| tolerations | list | `[]` | |
|
| resources | object | `{}` | Resource requests and limits for the Jellyfin container. |
|
||||||
|
| revisionHistoryLimit | int | `3` | Number of old ReplicaSets to retain for rollback history. Set to 0 to disable revision history (not recommended). If not specified, Kubernetes defaults to 10. See: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit |
|
||||||
|
| runtimeClassName | string | `""` | Define a custom runtimeClassName for the pod. |
|
||||||
|
| securityContext | object | `{}` | Security context for the container. |
|
||||||
|
| service.annotations | object | `{}` | Annotations for the service. |
|
||||||
|
| service.ipFamilies | list | `[]` | Supported IP families (IPv4, IPv6). Examples: IPv4 only: ["IPv4"] IPv6 only: ["IPv6"] Dual-stack (IPv4 primary): ["IPv4", "IPv6"] Dual-stack (IPv6 primary): ["IPv6", "IPv4"] Note: When using IPv6, ensure your health checks are compatible (consider using httpGet instead of tcpSocket) |
|
||||||
|
| service.ipFamilyPolicy | string | `""` | Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ Options: SingleStack, PreferDualStack, RequireDualStack For IPv6-only clusters, use "SingleStack" with ipFamilies: ["IPv6"] For dual-stack, use "PreferDualStack" or "RequireDualStack" with ipFamilies: ["IPv4", "IPv6"] or ["IPv6", "IPv4"] |
|
||||||
|
| service.labels | object | `{}` | Labels for the service. |
|
||||||
|
| service.loadBalancerClass | string | `""` | Class of the LoadBalancer. |
|
||||||
|
| service.loadBalancerIP | string | `""` | Specific IP address for the LoadBalancer. |
|
||||||
|
| service.loadBalancerSourceRanges | list | `[]` | Source ranges allowed to access the LoadBalancer. |
|
||||||
|
| service.port | int | `8096` | Port for the Jellyfin service. |
|
||||||
|
| service.portName | string | `"service"` | Name of the port in the service. |
|
||||||
|
| service.type | string | `"ClusterIP"` | Service type (ClusterIP, NodePort, or LoadBalancer). |
|
||||||
|
| serviceAccount | object | `{"annotations":{},"automount":true,"create":true,"name":""}` | Service account configuration. See: https://kubernetes.io/docs/concepts/security/service-accounts/ |
|
||||||
|
| serviceAccount.annotations | object | `{}` | Annotations for the service account. |
|
||||||
|
| serviceAccount.automount | bool | `true` | Automatically mount API credentials for the service account. |
|
||||||
|
| serviceAccount.create | bool | `true` | Specifies whether to create a service account. |
|
||||||
|
| serviceAccount.name | string | `""` | Custom name for the service account. If left empty, the name will be autogenerated. |
|
||||||
|
| startupProbe | object | `{"failureThreshold":30,"initialDelaySeconds":0,"periodSeconds":10,"tcpSocket":{"port":"http"}}` | Configure startup probe for Jellyfin. This probe gives Jellyfin enough time to start, especially with large media libraries. After the startup probe succeeds once, liveness and readiness probes take over. |
|
||||||
|
| tolerations | list | `[]` | Tolerations for pod scheduling. |
|
||||||
|
| volumeMounts | list | `[]` | Additional volume mounts for the Jellyfin container. |
|
||||||
|
| volumes | list | `[]` | Additional volumes to mount in the Jellyfin pod. |
|
||||||
|
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
|
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
|
||||||
|
|
||||||
|
## Gateway API HTTPRoute
|
||||||
|
|
||||||
|
This chart supports the Kubernetes Gateway API HTTPRoute resource as a modern alternative to Ingress.
|
||||||
|
|
||||||
|
To use HTTPRoute, you need to have Gateway API CRDs installed in your cluster and a Gateway resource configured.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
httpRoute:
|
||||||
|
enabled: true
|
||||||
|
annotations: {}
|
||||||
|
parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
namespace: gateway-system
|
||||||
|
sectionName: https
|
||||||
|
hostnames:
|
||||||
|
- jellyfin.example.com
|
||||||
|
rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about Gateway API, see: <https://gateway-api.sigs.k8s.io/>
|
||||||
|
|
||||||
## Hardware acceleration
|
## Hardware acceleration
|
||||||
|
|
||||||
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
||||||
@@ -130,3 +223,273 @@ extraVolumeMounts:
|
|||||||
- name: hwa
|
- name: hwa
|
||||||
mountPath: /dev/dri
|
mountPath: /dev/dri
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Network Security
|
||||||
|
|
||||||
|
Jellyfin chart supports Kubernetes NetworkPolicy for network isolation and security hardening. NetworkPolicy allows you to control which pods can access Jellyfin (ingress) and what external connections Jellyfin can make (egress).
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- **CNI Plugin**: NetworkPolicy requires a Container Network Interface (CNI) plugin that supports NetworkPolicies, such as:
|
||||||
|
- Calico
|
||||||
|
- Cilium
|
||||||
|
- Weave Net
|
||||||
|
- Canal
|
||||||
|
|
||||||
|
Check with your cluster administrator if NetworkPolicy is supported in your cluster.
|
||||||
|
|
||||||
|
- **DLNA Incompatibility**: NetworkPolicy cannot be enabled when `enableDLNA: true` or `podPrivileges.hostNetwork: true` is set, as pods using `hostNetwork` bypass NetworkPolicy rules. The chart will fail deployment with a clear error message if both are enabled.
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
By default, NetworkPolicy is disabled to maintain backward compatibility. To enable basic network isolation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a NetworkPolicy with the following defaults:
|
||||||
|
- **Ingress**: Allow connections from any pod in any namespace
|
||||||
|
- **Egress**: Allow DNS resolution and all internet access (required for metadata)
|
||||||
|
|
||||||
|
### Production Configuration - Restrict to Ingress Controller
|
||||||
|
|
||||||
|
For production environments, you typically want to restrict access to only allow traffic through the Ingress controller:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: ingress-nginx
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
hosts:
|
||||||
|
- host: jellyfin.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
### High Security Configuration - Restricted Egress
|
||||||
|
|
||||||
|
For security-conscious deployments that need to limit outbound connections:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
jellyfin-client: "true" # Only pods with this label can access
|
||||||
|
egress:
|
||||||
|
allowDNS: true # Always needed
|
||||||
|
allowAllEgress: false # Block unrestricted internet
|
||||||
|
restrictedEgress:
|
||||||
|
allowMetadata: true # Allow HTTPS/443 for metadata providers (TMDB, etc.)
|
||||||
|
allowInCluster: false # Block pod-to-pod communication
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: With this configuration, Jellyfin can only:
|
||||||
|
- Resolve DNS queries
|
||||||
|
- Connect to HTTPS (port 443) endpoints for metadata providers
|
||||||
|
- Cannot connect to other pods in the cluster
|
||||||
|
- Cannot access non-HTTPS services
|
||||||
|
|
||||||
|
### Monitoring Integration
|
||||||
|
|
||||||
|
If you're using Prometheus for monitoring, the chart automatically allows ingress from Prometheus pods when metrics are enabled:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the chart allows ingress from pods with label `app.kubernetes.io/name: prometheus`. If your Prometheus uses different labels, customize the selector:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
metrics:
|
||||||
|
namespace: monitoring # If Prometheus is in a different namespace
|
||||||
|
podSelector:
|
||||||
|
app: my-prometheus
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
#### Multiple Namespaces Access
|
||||||
|
|
||||||
|
Allow access from multiple namespaces using custom rules:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
customRules:
|
||||||
|
# Frontend namespace
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: frontend
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
access-jellyfin: "true"
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
|
||||||
|
# Admin tools namespace
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: admin-tools
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom Egress Rules
|
||||||
|
|
||||||
|
Allow connections to specific external services:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
egress:
|
||||||
|
allowAllEgress: false
|
||||||
|
restrictedEgress:
|
||||||
|
allowMetadata: true
|
||||||
|
allowedCIDRs:
|
||||||
|
- 10.0.0.0/8 # Internal network
|
||||||
|
- 192.168.0.0/16 # Another internal network
|
||||||
|
customRules:
|
||||||
|
# Allow connection to external database
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 203.0.113.0/24
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Considerations
|
||||||
|
|
||||||
|
1. **Metadata Providers**: Jellyfin requires internet access to download metadata (movie posters, descriptions, etc.) from:
|
||||||
|
- TheMovieDB (api.themoviedb.org)
|
||||||
|
- TheTVDB (api.thetvdb.com)
|
||||||
|
- OpenSubtitles (api.opensubtitles.com)
|
||||||
|
- Fanart.tv (fanart.tv)
|
||||||
|
|
||||||
|
If you use `restrictedEgress.allowMetadata: true`, these will work as they all use HTTPS (port 443).
|
||||||
|
|
||||||
|
2. **DNS Access**: DNS resolution is critical for Jellyfin operation. The chart prevents accidental DNS blocking by defaulting `allowDNS: true`.
|
||||||
|
|
||||||
|
3. **Local Metadata**: If you want to completely block internet access, you can use local metadata (NFO files and local images). This requires manual setup and is not the default Jellyfin behavior.
|
||||||
|
|
||||||
|
4. **Testing**: Always test NetworkPolicy changes in a development environment first. Misconfigured policies can block legitimate traffic.
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**Jellyfin can't download metadata/images:**
|
||||||
|
- Check that `egress.allowAllEgress: true` or `restrictedEgress.allowMetadata: true` is set
|
||||||
|
- Verify DNS egress is allowed: `egress.allowDNS: true`
|
||||||
|
|
||||||
|
**Can't access Jellyfin web interface:**
|
||||||
|
- Verify ingress rules allow traffic from your access point (Ingress controller, LoadBalancer, etc.)
|
||||||
|
- Check NOTES.txt after deployment for detailed NetworkPolicy status
|
||||||
|
|
||||||
|
**Prometheus can't scrape metrics:**
|
||||||
|
- Ensure `metrics.enabled: true` and `metrics.serviceMonitor.enabled: true`
|
||||||
|
- Verify `networkPolicy.metrics.podSelector` matches your Prometheus labels
|
||||||
|
- Set `networkPolicy.metrics.namespace` if Prometheus is in a different namespace
|
||||||
|
|
||||||
|
**Deployment fails with "NetworkPolicy cannot be enabled...":**
|
||||||
|
- You have both `networkPolicy.enabled: true` and `hostNetwork: true` (or `enableDLNA: true`)
|
||||||
|
- NetworkPolicy doesn't work with host networking
|
||||||
|
- Either disable NetworkPolicy or disable host networking
|
||||||
|
|
||||||
|
For more configuration options, see the full values documentation in [values.yaml](values.yaml).
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### inotify Instance Limit Reached
|
||||||
|
|
||||||
|
**Problem:** Jellyfin crashes with error:
|
||||||
|
```
|
||||||
|
System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached
|
||||||
|
```
|
||||||
|
|
||||||
|
**Root cause:** The Linux kernel has a limit on inotify instances (file system watchers) per user. Jellyfin uses inotify to monitor media libraries for changes.
|
||||||
|
|
||||||
|
**Proper solution (recommended):**
|
||||||
|
|
||||||
|
Increase the inotify limit on the Kubernetes nodes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Temporary (until reboot)
|
||||||
|
sysctl -w fs.inotify.max_user_instances=512
|
||||||
|
|
||||||
|
# Permanent
|
||||||
|
echo "fs.inotify.max_user_instances=512" >> /etc/sysctl.conf
|
||||||
|
sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended values:
|
||||||
|
- `fs.inotify.max_user_instances`: 512 or higher
|
||||||
|
- `fs.inotify.max_user_watches`: 524288 or higher (if you have large media libraries)
|
||||||
|
|
||||||
|
**Workaround (if you cannot modify host settings):**
|
||||||
|
|
||||||
|
If you're running on a managed Kubernetes cluster where you cannot modify node-level settings, you can force Jellyfin to use polling instead of inotify. **Note: This is less efficient and may increase CPU usage and delay change detection.**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jellyfin:
|
||||||
|
env:
|
||||||
|
- name: DOTNET_USE_POLLING_FILE_WATCHER
|
||||||
|
value: "1"
|
||||||
|
```
|
||||||
|
|
||||||
|
This workaround disables inotify file watching in favor of periodic polling, which doesn't require inotify instances but is less efficient.
|
||||||
|
|
||||||
|
## IPv6 Configuration
|
||||||
|
|
||||||
|
This chart supports IPv6 and dual-stack networking configurations out of the box. Health probes use httpGet by default for compatibility with both IPv4 and IPv6.
|
||||||
|
|
||||||
|
### IPv6-only Configuration
|
||||||
|
|
||||||
|
For IPv6-only clusters:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
ipFamilyPolicy: SingleStack
|
||||||
|
ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dual-stack Configuration
|
||||||
|
|
||||||
|
For dual-stack clusters (both IPv4 and IPv6):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
ipFamilyPolicy: PreferDualStack # or RequireDualStack
|
||||||
|
ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6 # First family in the list is the primary
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about Kubernetes dual-stack networking, see: <https://kubernetes.io/docs/concepts/services-networking/dual-stack/>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm repo add <repo-name> <repo-url>
|
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Install the Helm Chart
|
### 2. Install the Helm Chart
|
||||||
@@ -22,7 +22,7 @@ helm repo add <repo-name> <repo-url>
|
|||||||
To install a chart, use the following command:
|
To install a chart, use the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <repo-name>/jellyfin
|
helm install my-jellyfin jellyfin/jellyfin
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. View the Installation
|
### 3. View the Installation
|
||||||
@@ -30,7 +30,7 @@ helm install <release-name> <repo-name>/jellyfin
|
|||||||
You can check the status of the release using:
|
You can check the status of the release using:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm status <release-name>
|
helm status my-jellyfin
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customizing the Chart
|
## Customizing the Chart
|
||||||
@@ -39,14 +39,14 @@ Helm charts come with default values, but you can customize them by using the --
|
|||||||
|
|
||||||
### 1. Using --set to Override Values
|
### 1. Using --set to Override Values
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <chart-name> --set key1=value1,key2=value2
|
helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Using a values.yaml File
|
### 2. Using a values.yaml File
|
||||||
You can create a custom values.yaml file and pass it to the install command:
|
You can create a custom values.yaml file and pass it to the install command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
helm install <release-name> <chart-name> -f values.yaml
|
helm install my-jellyfin jellyfin/jellyfin -f values.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
{{ template "chart.maintainersSection" . }}
|
{{ template "chart.maintainersSection" . }}
|
||||||
@@ -59,6 +59,33 @@ helm install <release-name> <chart-name> -f values.yaml
|
|||||||
|
|
||||||
{{ template "helm-docs.versionFooter" . }}
|
{{ template "helm-docs.versionFooter" . }}
|
||||||
|
|
||||||
|
## Gateway API HTTPRoute
|
||||||
|
|
||||||
|
This chart supports the Kubernetes Gateway API HTTPRoute resource as a modern alternative to Ingress.
|
||||||
|
|
||||||
|
To use HTTPRoute, you need to have Gateway API CRDs installed in your cluster and a Gateway resource configured.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
httpRoute:
|
||||||
|
enabled: true
|
||||||
|
annotations: {}
|
||||||
|
parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
namespace: gateway-system
|
||||||
|
sectionName: https
|
||||||
|
hostnames:
|
||||||
|
- jellyfin.example.com
|
||||||
|
rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about Gateway API, see: <https://gateway-api.sigs.k8s.io/>
|
||||||
|
|
||||||
## Hardware acceleration
|
## Hardware acceleration
|
||||||
|
|
||||||
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
||||||
@@ -85,3 +112,273 @@ extraVolumeMounts:
|
|||||||
- name: hwa
|
- name: hwa
|
||||||
mountPath: /dev/dri
|
mountPath: /dev/dri
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Network Security
|
||||||
|
|
||||||
|
Jellyfin chart supports Kubernetes NetworkPolicy for network isolation and security hardening. NetworkPolicy allows you to control which pods can access Jellyfin (ingress) and what external connections Jellyfin can make (egress).
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- **CNI Plugin**: NetworkPolicy requires a Container Network Interface (CNI) plugin that supports NetworkPolicies, such as:
|
||||||
|
- Calico
|
||||||
|
- Cilium
|
||||||
|
- Weave Net
|
||||||
|
- Canal
|
||||||
|
|
||||||
|
Check with your cluster administrator if NetworkPolicy is supported in your cluster.
|
||||||
|
|
||||||
|
- **DLNA Incompatibility**: NetworkPolicy cannot be enabled when `enableDLNA: true` or `podPrivileges.hostNetwork: true` is set, as pods using `hostNetwork` bypass NetworkPolicy rules. The chart will fail deployment with a clear error message if both are enabled.
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
By default, NetworkPolicy is disabled to maintain backward compatibility. To enable basic network isolation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a NetworkPolicy with the following defaults:
|
||||||
|
- **Ingress**: Allow connections from any pod in any namespace
|
||||||
|
- **Egress**: Allow DNS resolution and all internet access (required for metadata)
|
||||||
|
|
||||||
|
### Production Configuration - Restrict to Ingress Controller
|
||||||
|
|
||||||
|
For production environments, you typically want to restrict access to only allow traffic through the Ingress controller:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: ingress-nginx
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: ingress-nginx
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: nginx
|
||||||
|
hosts:
|
||||||
|
- host: jellyfin.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
### High Security Configuration - Restricted Egress
|
||||||
|
|
||||||
|
For security-conscious deployments that need to limit outbound connections:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
jellyfin-client: "true" # Only pods with this label can access
|
||||||
|
egress:
|
||||||
|
allowDNS: true # Always needed
|
||||||
|
allowAllEgress: false # Block unrestricted internet
|
||||||
|
restrictedEgress:
|
||||||
|
allowMetadata: true # Allow HTTPS/443 for metadata providers (TMDB, etc.)
|
||||||
|
allowInCluster: false # Block pod-to-pod communication
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: With this configuration, Jellyfin can only:
|
||||||
|
- Resolve DNS queries
|
||||||
|
- Connect to HTTPS (port 443) endpoints for metadata providers
|
||||||
|
- Cannot connect to other pods in the cluster
|
||||||
|
- Cannot access non-HTTPS services
|
||||||
|
|
||||||
|
### Monitoring Integration
|
||||||
|
|
||||||
|
If you're using Prometheus for monitoring, the chart automatically allows ingress from Prometheus pods when metrics are enabled:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
serviceMonitor:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the chart allows ingress from pods with label `app.kubernetes.io/name: prometheus`. If your Prometheus uses different labels, customize the selector:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
metrics:
|
||||||
|
namespace: monitoring # If Prometheus is in a different namespace
|
||||||
|
podSelector:
|
||||||
|
app: my-prometheus
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
#### Multiple Namespaces Access
|
||||||
|
|
||||||
|
Allow access from multiple namespaces using custom rules:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
ingress:
|
||||||
|
allowExternal: false
|
||||||
|
customRules:
|
||||||
|
# Frontend namespace
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: frontend
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
access-jellyfin: "true"
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
|
||||||
|
# Admin tools namespace
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: admin-tools
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom Egress Rules
|
||||||
|
|
||||||
|
Allow connections to specific external services:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networkPolicy:
|
||||||
|
enabled: true
|
||||||
|
egress:
|
||||||
|
allowAllEgress: false
|
||||||
|
restrictedEgress:
|
||||||
|
allowMetadata: true
|
||||||
|
allowedCIDRs:
|
||||||
|
- 10.0.0.0/8 # Internal network
|
||||||
|
- 192.168.0.0/16 # Another internal network
|
||||||
|
customRules:
|
||||||
|
# Allow connection to external database
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 203.0.113.0/24
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Considerations
|
||||||
|
|
||||||
|
1. **Metadata Providers**: Jellyfin requires internet access to download metadata (movie posters, descriptions, etc.) from:
|
||||||
|
- TheMovieDB (api.themoviedb.org)
|
||||||
|
- TheTVDB (api.thetvdb.com)
|
||||||
|
- OpenSubtitles (api.opensubtitles.com)
|
||||||
|
- Fanart.tv (fanart.tv)
|
||||||
|
|
||||||
|
If you use `restrictedEgress.allowMetadata: true`, these will work as they all use HTTPS (port 443).
|
||||||
|
|
||||||
|
2. **DNS Access**: DNS resolution is critical for Jellyfin operation. The chart prevents accidental DNS blocking by defaulting `allowDNS: true`.
|
||||||
|
|
||||||
|
3. **Local Metadata**: If you want to completely block internet access, you can use local metadata (NFO files and local images). This requires manual setup and is not the default Jellyfin behavior.
|
||||||
|
|
||||||
|
4. **Testing**: Always test NetworkPolicy changes in a development environment first. Misconfigured policies can block legitimate traffic.
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**Jellyfin can't download metadata/images:**
|
||||||
|
- Check that `egress.allowAllEgress: true` or `restrictedEgress.allowMetadata: true` is set
|
||||||
|
- Verify DNS egress is allowed: `egress.allowDNS: true`
|
||||||
|
|
||||||
|
**Can't access Jellyfin web interface:**
|
||||||
|
- Verify ingress rules allow traffic from your access point (Ingress controller, LoadBalancer, etc.)
|
||||||
|
- Check NOTES.txt after deployment for detailed NetworkPolicy status
|
||||||
|
|
||||||
|
**Prometheus can't scrape metrics:**
|
||||||
|
- Ensure `metrics.enabled: true` and `metrics.serviceMonitor.enabled: true`
|
||||||
|
- Verify `networkPolicy.metrics.podSelector` matches your Prometheus labels
|
||||||
|
- Set `networkPolicy.metrics.namespace` if Prometheus is in a different namespace
|
||||||
|
|
||||||
|
**Deployment fails with "NetworkPolicy cannot be enabled...":**
|
||||||
|
- You have both `networkPolicy.enabled: true` and `hostNetwork: true` (or `enableDLNA: true`)
|
||||||
|
- NetworkPolicy doesn't work with host networking
|
||||||
|
- Either disable NetworkPolicy or disable host networking
|
||||||
|
|
||||||
|
For more configuration options, see the full values documentation in [values.yaml](values.yaml).
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### inotify Instance Limit Reached
|
||||||
|
|
||||||
|
**Problem:** Jellyfin crashes with error:
|
||||||
|
```
|
||||||
|
System.IO.IOException: The configured user limit (128) on the number of inotify instances has been reached
|
||||||
|
```
|
||||||
|
|
||||||
|
**Root cause:** The Linux kernel has a limit on inotify instances (file system watchers) per user. Jellyfin uses inotify to monitor media libraries for changes.
|
||||||
|
|
||||||
|
**Proper solution (recommended):**
|
||||||
|
|
||||||
|
Increase the inotify limit on the Kubernetes nodes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Temporary (until reboot)
|
||||||
|
sysctl -w fs.inotify.max_user_instances=512
|
||||||
|
|
||||||
|
# Permanent
|
||||||
|
echo "fs.inotify.max_user_instances=512" >> /etc/sysctl.conf
|
||||||
|
sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
|
Recommended values:
|
||||||
|
- `fs.inotify.max_user_instances`: 512 or higher
|
||||||
|
- `fs.inotify.max_user_watches`: 524288 or higher (if you have large media libraries)
|
||||||
|
|
||||||
|
**Workaround (if you cannot modify host settings):**
|
||||||
|
|
||||||
|
If you're running on a managed Kubernetes cluster where you cannot modify node-level settings, you can force Jellyfin to use polling instead of inotify. **Note: This is less efficient and may increase CPU usage and delay change detection.**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jellyfin:
|
||||||
|
env:
|
||||||
|
- name: DOTNET_USE_POLLING_FILE_WATCHER
|
||||||
|
value: "1"
|
||||||
|
```
|
||||||
|
|
||||||
|
This workaround disables inotify file watching in favor of periodic polling, which doesn't require inotify instances but is less efficient.
|
||||||
|
|
||||||
|
## IPv6 Configuration
|
||||||
|
|
||||||
|
This chart supports IPv6 and dual-stack networking configurations out of the box. Health probes use httpGet by default for compatibility with both IPv4 and IPv6.
|
||||||
|
|
||||||
|
### IPv6-only Configuration
|
||||||
|
|
||||||
|
For IPv6-only clusters:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
ipFamilyPolicy: SingleStack
|
||||||
|
ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dual-stack Configuration
|
||||||
|
|
||||||
|
For dual-stack clusters (both IPv4 and IPv6):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
ipFamilyPolicy: PreferDualStack # or RequireDualStack
|
||||||
|
ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6 # First family in the list is the primary
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information about Kubernetes dual-stack networking, see: <https://kubernetes.io/docs/concepts/services-networking/dual-stack/>
|
||||||
@@ -1,19 +1,291 @@
|
|||||||
1. Get the application URL by running these commands:
|
{{- if .Values.initContainers }}
|
||||||
|
#############################################################################
|
||||||
|
## ⚠️ WARNING ⚠️ ##
|
||||||
|
## ##
|
||||||
|
## The 'initContainers' parameter is DEPRECATED! ##
|
||||||
|
## Please migrate to 'extraInitContainers' instead. ##
|
||||||
|
## ##
|
||||||
|
## Support for 'initContainers' will be removed after 2030. ##
|
||||||
|
## ##
|
||||||
|
## Migration guide: ##
|
||||||
|
## Old: initContainers: [...] ##
|
||||||
|
## New: extraInitContainers: [...] ##
|
||||||
|
## ##
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
|
Thank you for installing {{ .Chart.Name }}!
|
||||||
|
|
||||||
|
Your release is named {{ .Release.Name }}.
|
||||||
|
|
||||||
|
To learn more about the release, try:
|
||||||
|
|
||||||
|
$ helm status {{ .Release.Name }} --namespace {{ .Release.Namespace }}
|
||||||
|
$ helm get all {{ .Release.Name }} --namespace {{ .Release.Namespace }}
|
||||||
|
|
||||||
{{- if .Values.ingress.enabled }}
|
{{- if .Values.ingress.enabled }}
|
||||||
{{- range .Values.ingress.hosts }}
|
{{- range $host := .Values.ingress.hosts }}
|
||||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
|
{{- range .paths }}
|
||||||
|
|
||||||
|
Jellyfin is available at:
|
||||||
|
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- else if contains "NodePort" .Values.service.type }}
|
{{- else if contains "NodePort" .Values.service.type }}
|
||||||
|
|
||||||
|
Get the Jellyfin URL by running:
|
||||||
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "jellyfin.fullname" . }})
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "jellyfin.fullname" . }})
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
echo "Jellyfin URL: http://$NODE_IP:$NODE_PORT"
|
||||||
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
{{- else if contains "LoadBalancer" .Values.service.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 svc -w {{ include "jellyfin.fullname" . }}'
|
Get the Jellyfin URL by running:
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "jellyfin.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
|
You can watch the status by running:
|
||||||
|
kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "jellyfin.fullname" . }}
|
||||||
|
|
||||||
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "jellyfin.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
|
echo "Jellyfin URL: http://$SERVICE_IP:{{ .Values.service.port }}"
|
||||||
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||||
|
|
||||||
|
Get the Jellyfin URL by running:
|
||||||
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "jellyfin.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "jellyfin.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
Visit http://127.0.0.1:8080 to use your application
|
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||||
kubectl port-forward $POD_NAME 8080:80
|
echo "Jellyfin URL: http://127.0.0.1:8080"
|
||||||
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||||
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.persistence.config.enabled }}
|
||||||
|
|
||||||
|
Configuration is persisted to:
|
||||||
|
{{- if .Values.persistence.config.existingClaim }}
|
||||||
|
Existing PVC: {{ .Values.persistence.config.existingClaim }}
|
||||||
|
{{- else }}
|
||||||
|
PVC: {{ include "jellyfin.fullname" . }}-config
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
|
||||||
|
WARNING: Configuration persistence is disabled!
|
||||||
|
Data will be lost when the pod is restarted.
|
||||||
|
Enable persistence.config.enabled to persist your configuration.
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.persistence.media.enabled }}
|
||||||
|
|
||||||
|
Media is {{ if eq .Values.persistence.media.type "hostPath" }}mounted from host path{{ else if eq .Values.persistence.media.type "pvc" }}persisted to PVC{{ else }}stored in emptyDir{{ end }}:
|
||||||
|
{{- if eq .Values.persistence.media.type "hostPath" }}
|
||||||
|
Host path: {{ .Values.persistence.media.hostPath }}
|
||||||
|
{{- else if eq .Values.persistence.media.type "pvc" }}
|
||||||
|
{{- if .Values.persistence.media.existingClaim }}
|
||||||
|
Existing PVC: {{ .Values.persistence.media.existingClaim }}
|
||||||
|
{{- else }}
|
||||||
|
PVC: {{ include "jellyfin.fullname" . }}-media
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
|
||||||
|
WARNING: Media persistence is disabled!
|
||||||
|
Your media files will be lost when the pod is restarted.
|
||||||
|
Enable persistence.media.enabled to persist your media.
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
For more information and documentation:
|
||||||
|
Repository: https://github.com/jellyfin/jellyfin-helm
|
||||||
|
Jellyfin Docs: https://jellyfin.org/docs/
|
||||||
|
$ helm status {{ .Release.Name }}
|
||||||
|
$ helm get all {{ .Release.Name }}
|
||||||
|
|
||||||
|
{{- if .Values.httpRoute.enabled }}
|
||||||
|
|
||||||
|
HTTPRoute (Gateway API) is ENABLED:
|
||||||
|
{{- if .Values.httpRoute.parentRefs }}
|
||||||
|
Gateway References:
|
||||||
|
{{- range .Values.httpRoute.parentRefs }}
|
||||||
|
- {{ .name }}{{ if .namespace }} (namespace: {{ .namespace }}){{ end }}{{ if .sectionName }} [{{ .sectionName }}]{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
⚠ WARNING: No parentRefs defined - HTTPRoute will not attach to any Gateway!
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.httpRoute.hostnames }}
|
||||||
|
Hostnames:
|
||||||
|
{{- range .Values.httpRoute.hostnames }}
|
||||||
|
- {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
Rules: {{ len .Values.httpRoute.rules }} route(s) configured
|
||||||
|
Backend: {{ include "jellyfin.fullname" . }}:{{ .Values.service.port }}
|
||||||
|
|
||||||
|
Access Jellyfin via Gateway API at:
|
||||||
|
{{- if .Values.httpRoute.hostnames }}
|
||||||
|
{{- range .Values.httpRoute.hostnames }}
|
||||||
|
https://{{ . }}{{ with (index $.Values.httpRoute.rules 0) }}{{ with (index .matches 0) }}{{ .path.value }}{{ end }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
(Configure httpRoute.hostnames for external access)
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Note: Ensure your Gateway API CRDs are installed and Gateway is configured.
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.networkPolicy.enabled }}
|
||||||
|
|
||||||
|
Network Policy is ENABLED:
|
||||||
|
{{- if or .Values.jellyfin.enableDLNA .Values.podPrivileges.hostNetwork }}
|
||||||
|
WARNING: NetworkPolicy is incompatible with hostNetwork (DLNA mode).
|
||||||
|
The deployment will FAIL. Please disable networkPolicy.enabled or hostNetwork.
|
||||||
|
{{- else }}
|
||||||
|
|
||||||
|
Ingress Policy:
|
||||||
|
{{- if .Values.networkPolicy.ingress.allowExternal }}
|
||||||
|
- ✓ Allowing connections from ANY pod in ANY namespace
|
||||||
|
{{- else }}
|
||||||
|
{{- if or .Values.networkPolicy.ingress.podSelector .Values.networkPolicy.ingress.namespaceSelector }}
|
||||||
|
- ✓ Allowing connections ONLY from pods matching:
|
||||||
|
{{- if .Values.networkPolicy.ingress.podSelector }}
|
||||||
|
Pod Labels: {{ .Values.networkPolicy.ingress.podSelector | toYaml | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.ingress.namespaceSelector }}
|
||||||
|
Namespace Labels: {{ .Values.networkPolicy.ingress.namespaceSelector | toYaml | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
- ⚠ WARNING: allowExternal=false but no selectors defined - NO pods can connect!
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
|
||||||
|
- ✓ Allowing Prometheus metrics scraping from {{ .Values.networkPolicy.metrics.podSelector | toYaml }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.ingress.customRules }}
|
||||||
|
- ✓ Custom ingress rules applied ({{ len .Values.networkPolicy.ingress.customRules }} rules)
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Egress Policy:
|
||||||
|
{{- if .Values.networkPolicy.egress.allowDNS }}
|
||||||
|
- ✓ DNS resolution allowed ({{ .Values.networkPolicy.egress.dnsNamespace }}/{{ .Values.networkPolicy.egress.dnsPodSelector | toYaml }})
|
||||||
|
{{- else }}
|
||||||
|
- ⚠ WARNING: DNS is DISABLED - Jellyfin will NOT function properly!
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.egress.allowAllEgress }}
|
||||||
|
- ✓ All egress allowed (metadata, subtitles, images)
|
||||||
|
{{- else }}
|
||||||
|
{{- if .Values.networkPolicy.egress.restrictedEgress.allowMetadata }}
|
||||||
|
- ✓ HTTPS/443 allowed (metadata providers)
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.egress.restrictedEgress.allowInCluster }}
|
||||||
|
- ✓ In-cluster communication allowed
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.egress.restrictedEgress.allowedCIDRs }}
|
||||||
|
- ✓ Custom CIDRs allowed: {{ .Values.networkPolicy.egress.restrictedEgress.allowedCIDRs | join ", " }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if not (or .Values.networkPolicy.egress.restrictedEgress.allowMetadata .Values.networkPolicy.egress.restrictedEgress.allowInCluster .Values.networkPolicy.egress.restrictedEgress.allowedCIDRs) }}
|
||||||
|
- ⚠ WARNING: No egress rules defined - Jellyfin cannot download metadata!
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.networkPolicy.egress.customRules }}
|
||||||
|
- ✓ Custom egress rules applied ({{ len .Values.networkPolicy.egress.customRules }} rules)
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Note: NetworkPolicy requires a CNI plugin with NetworkPolicy support (Calico, Cilium, etc.)
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
|
||||||
|
Network Policy is DISABLED (default).
|
||||||
|
To enable network isolation, set networkPolicy.enabled=true in your values.
|
||||||
|
{{- end }}
|
||||||
|
For troubleshooting common issues, see the README:
|
||||||
|
- inotify instance limit errors
|
||||||
|
- Hardware acceleration setup
|
||||||
|
- Network configuration
|
||||||
|
|
||||||
|
Useful resources:
|
||||||
|
Documentation: https://jellyfin.org/docs/
|
||||||
|
Troubleshooting: See README.md in the chart repository
|
||||||
|
|
||||||
|
{{- if .Values.jellyfin.envFrom }}
|
||||||
|
|
||||||
|
Environment Configuration:
|
||||||
|
Loading environment variables from {{ len .Values.jellyfin.envFrom }} source(s):
|
||||||
|
{{- range .Values.jellyfin.envFrom }}
|
||||||
|
{{- if .configMapRef }}
|
||||||
|
- ConfigMap: {{ .configMapRef.name }}{{ if .configMapRef.optional }} (optional){{ end }}{{ if .prefix }} with prefix: {{ .prefix }}{{ end }}
|
||||||
|
{{- else if .secretRef }}
|
||||||
|
- Secret: {{ .secretRef.name }}{{ if .secretRef.optional }} (optional){{ end }}{{ if .prefix }} with prefix: {{ .prefix }}{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.startupProbe }}
|
||||||
|
{{- $startupTimeout := mul (default 10 .Values.startupProbe.periodSeconds) (default 30 .Values.startupProbe.failureThreshold) }}
|
||||||
|
|
||||||
|
Startup Configuration:
|
||||||
|
Startup Probe: Enabled
|
||||||
|
Max Startup Time: {{ $startupTimeout }}s ({{ div $startupTimeout 60 }} minutes)
|
||||||
|
|
||||||
|
The startup probe gives Jellyfin enough time to initialize, especially
|
||||||
|
with large media libraries. After startup succeeds, liveness and
|
||||||
|
readiness probes take over for health monitoring.
|
||||||
|
|
||||||
|
{{- if gt $startupTimeout 600 }}
|
||||||
|
⚠ NOTE: Startup timeout is very long ({{ div $startupTimeout 60 }}+ minutes).
|
||||||
|
Consider optimizing your media library or reducing failureThreshold.
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Persistence Configuration:
|
||||||
|
Config: {{ if .Values.persistence.config.enabled }}{{ .Values.persistence.config.type | default "pvc" }}{{ if .Values.persistence.config.existingClaim }} (existing: {{ .Values.persistence.config.existingClaim }}){{ end }}{{ else }}emptyDir{{ end }}
|
||||||
|
Media: {{ if .Values.persistence.media.enabled }}{{ .Values.persistence.media.type | default "pvc" }}{{ if .Values.persistence.media.existingClaim }} (existing: {{ .Values.persistence.media.existingClaim }}){{ end }}{{ else }}emptyDir{{ end }}
|
||||||
|
Cache: {{ if .Values.persistence.cache.enabled }}{{ .Values.persistence.cache.type | default "pvc" }}{{ if .Values.persistence.cache.existingClaim }} (existing: {{ .Values.persistence.cache.existingClaim }}){{ end }}{{ else }}emptyDir{{ end }}
|
||||||
|
|
||||||
|
{{- if and .Values.persistence.cache.enabled (eq .Values.persistence.cache.type "pvc") }}
|
||||||
|
Cache Volume:
|
||||||
|
Dedicated cache volume is enabled for improved performance.
|
||||||
|
Size: {{ .Values.persistence.cache.size }}
|
||||||
|
Access Mode: {{ .Values.persistence.cache.accessMode }}
|
||||||
|
{{- if .Values.persistence.cache.storageClass }}
|
||||||
|
Storage Class: {{ .Values.persistence.cache.storageClass }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Benefits:
|
||||||
|
- Faster transcoding and metadata operations
|
||||||
|
- Separate cache lifecycle from config/media
|
||||||
|
- Can use faster storage class (SSD) for cache
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and .Values.persistence.cache.enabled (eq .Values.persistence.cache.type "hostPath") }}
|
||||||
|
⚠ WARNING: Using hostPath for cache - ensure {{ .Values.persistence.cache.hostPath }} exists on the node
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if or .Values.service.ipFamilyPolicy .Values.service.ipFamilies }}
|
||||||
|
|
||||||
|
Service IP Configuration:
|
||||||
|
{{- if .Values.service.ipFamilyPolicy }}
|
||||||
|
IP Family Policy: {{ .Values.service.ipFamilyPolicy }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.ipFamilies }}
|
||||||
|
IP Families: {{ .Values.service.ipFamilies | join ", " }}
|
||||||
|
{{- if eq (index .Values.service.ipFamilies 0) "IPv6" }}
|
||||||
|
⚠ NOTE: IPv6 primary - ensure your probes use httpGet instead of tcpSocket for compatibility
|
||||||
|
{{- end }}
|
||||||
|
{{- if has "IPv6" .Values.service.ipFamilies }}
|
||||||
|
{{- if not .Values.service.ipFamilyPolicy }}
|
||||||
|
⚠ WARNING: ipFamilies includes IPv6 but ipFamilyPolicy is not set
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
Deployment Configuration:
|
||||||
|
Revision History Limit: {{ .Values.revisionHistoryLimit }}
|
||||||
|
{{- $limit := int .Values.revisionHistoryLimit }}
|
||||||
|
{{- if eq $limit 0 }}
|
||||||
|
⚠ WARNING: Revision history is disabled - rollback will not be possible!
|
||||||
|
{{- else if eq $limit 1 }}
|
||||||
|
⚠ NOTE: Only 1 revision kept - limited rollback capability
|
||||||
|
{{- else }}
|
||||||
|
You can rollback to any of the last {{ .Values.revisionHistoryLimit }} revisions using:
|
||||||
|
kubectl rollout undo deployment/{{ include "jellyfin.fullname" . }} --namespace {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
{{/* vim: set filetype=mustache: */}}
|
{{/*
|
||||||
|
Fail if command and metrics are set
|
||||||
|
*/}}
|
||||||
|
{{- if and .Values.image.command .Values.metrics.enabled }}
|
||||||
|
{{- fail "Can't use custom command and metrics in combination. They are exclusive features" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Expand the name of the chart.
|
Expand the name of the chart.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "jellyfin.name" -}}
|
{{- define "jellyfin.name" -}}
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Create a default fully qualified app name.
|
Create a default fully qualified app name.
|
||||||
@@ -12,21 +18,52 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
|
|||||||
If release name contains chart name it will be used as a full name.
|
If release name contains chart name it will be used as a full name.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "jellyfin.fullname" -}}
|
{{- define "jellyfin.fullname" -}}
|
||||||
{{- if .Values.fullnameOverride -}}
|
{{- if .Values.fullnameOverride }}
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- else -}}
|
{{- else }}
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
{{- if contains $name .Release.Name -}}
|
{{- if contains $name .Release.Name }}
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
{{- else -}}
|
{{- else }}
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Create chart name and version as used by the chart label.
|
Create chart name and version as used by the chart label.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "jellyfin.chart" -}}
|
{{- define "jellyfin.chart" -}}
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "jellyfin.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
||||||
|
{{ include "jellyfin.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "jellyfin.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "jellyfin.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "jellyfin.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
{{- if and .Values.persistence.config.enabled (not .Values.persistence.config.existingClaim) }}
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: {{ template "jellyfin.fullname" . }}-config
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
|
||||||
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- with .Values.persistence.config.labels }}
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.persistence.config.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- {{ .Values.persistence.config.accessMode | quote }}
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: {{ .Values.persistence.config.size | quote }}
|
|
||||||
{{- if .Values.persistence.config.storageClass }}
|
|
||||||
{{- if (eq "-" .Values.persistence.config.storageClass) }}
|
|
||||||
storageClassName: ""
|
|
||||||
{{- else }}
|
|
||||||
storageClassName: "{{ .Values.persistence.config.storageClass }}"
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end -}}
|
|
||||||
@@ -2,175 +2,216 @@ apiVersion: apps/v1
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "jellyfin.fullname" . }}
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
|
{{- with .Values.deploymentAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
spec:
|
spec:
|
||||||
|
{{- with .Values.deploymentStrategy }}
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
{{- toYaml . | trim | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
replicas: {{ .Values.replicaCount }}
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- with .Values.revisionHistoryLimit }}
|
||||||
|
revisionHistoryLimit: {{ . }}
|
||||||
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
{{- include "jellyfin.selectorLabels" . | nindent 6 }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
{{- with .Values.podAnnotations }}
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- with .Values.extraPodLabels }}
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.extraPodAnnotations }}
|
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 8 }}
|
||||||
|
{{- with .Values.podLabels }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
{{- with .Values.imagePullSecrets }}
|
{{- with .Values.imagePullSecrets }}
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.enableDLNA }}
|
serviceAccountName: {{ include "jellyfin.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
{{- if or .Values.jellyfin.enableDLNA .Values.podPrivileges.hostNetwork }}
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Values.podPrivileges.hostIPC }}
|
||||||
|
hostIPC: true
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.podPrivileges.hostPID }}
|
||||||
|
hostPID: true
|
||||||
|
{{- end }}
|
||||||
containers:
|
containers:
|
||||||
- name: {{ .Chart.Name }}
|
- name: {{ .Chart.Name }}
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
{{ if .Values.image.command }}
|
|
||||||
command:
|
|
||||||
{{- toYaml .Values.image.command | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.image.args }}
|
|
||||||
args:
|
|
||||||
{{- toYaml .Values.image.args | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.extraEnvVars }}
|
|
||||||
env:
|
|
||||||
{{- toYaml .Values.extraEnvVars | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.securityContext }}
|
|
||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
{{- end }}
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
{{- with .Values.jellyfin.command }}
|
||||||
|
command:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.jellyfin.args }}
|
||||||
|
args:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.jellyfin.envFrom }}
|
||||||
|
envFrom:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.jellyfin.env }}
|
||||||
|
env:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.metrics.enabled }}
|
||||||
|
lifecycle:
|
||||||
|
postStart:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Waiting for system.xml to enable metrics..."
|
||||||
|
timeout=300 # 5 minutes timeout
|
||||||
|
interval=5 # Check every 5 seconds
|
||||||
|
elapsed=0
|
||||||
|
while [ ! -f /config/config/system.xml ]; do
|
||||||
|
if [ $elapsed -ge $timeout ]; then
|
||||||
|
echo "ERROR: Timed out waiting for /config/config/system.xml" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep $interval
|
||||||
|
elapsed=$((elapsed + interval))
|
||||||
|
done
|
||||||
|
echo "Found /config/config/system.xml, enabling metrics..."
|
||||||
|
# Check if metrics are already enabled before running sed
|
||||||
|
if ! grep -q '<EnableMetrics>true</EnableMetrics>' /config/config/system.xml; then
|
||||||
|
sed 's,<EnableMetrics>false</EnableMetrics>,<EnableMetrics>true</EnableMetrics>,' -i /config/config/system.xml
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Metrics enabled successfully."
|
||||||
|
else
|
||||||
|
echo "ERROR: Failed to enable metrics in /config/config/system.xml" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Metrics already enabled."
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8096
|
containerPort: 8096
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
{{ if .Values.enableDLNA }}
|
{{- if .Values.jellyfin.enableDLNA }}
|
||||||
- name: dlna
|
- name: dlna
|
||||||
containerPort: 1900
|
containerPort: 1900
|
||||||
hostPort: 1900
|
hostPort: 1900
|
||||||
protocol: UDP
|
protocol: UDP
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.startupProbe }}
|
||||||
|
startupProbe:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{ if .Values.livenessProbe.enabled }}
|
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
{{ if .Values.livenessProbe.initialDelaySeconds }}
|
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||||
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.livenessProbe.periodSeconds }}
|
|
||||||
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.livenessProbe.timeoutSeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.livenessProbe.failureThreshold }}
|
|
||||||
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.livenessProbe.successThreshold }}
|
|
||||||
successThreshold: {{ .Values.livenessProbe.successThreshold }}
|
|
||||||
{{- end }}
|
|
||||||
tcpSocket:
|
|
||||||
port: http
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.readinessProbe.enabled }}
|
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
{{ if .Values.readinessProbe.initialDelaySeconds }}
|
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
||||||
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
|
resources:
|
||||||
{{- end }}
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
{{ if .Values.readinessProbe.periodSeconds }}
|
|
||||||
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.readinessProbe.timeoutSeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.readinessProbe.failureThreshold }}
|
|
||||||
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
|
|
||||||
{{- end }}
|
|
||||||
{{ if .Values.readinessProbe.successThreshold }}
|
|
||||||
successThreshold: {{ .Values.readinessProbe.successThreshold }}
|
|
||||||
{{- end }}
|
|
||||||
tcpSocket:
|
|
||||||
port: http
|
|
||||||
{{- end }}
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /config
|
- mountPath: /config
|
||||||
name: config
|
name: config
|
||||||
{{- if .Values.persistence.config.subPath }}
|
|
||||||
subPath: {{ .Values.persistence.config.subPath }}
|
|
||||||
{{- end }}
|
|
||||||
- mountPath: /media
|
- mountPath: /media
|
||||||
name: media
|
name: media
|
||||||
{{- if .Values.persistence.media.subPath }}
|
- mountPath: /cache
|
||||||
subPath: {{ .Values.persistence.media.subPath }}
|
name: cache
|
||||||
|
{{- with .Values.volumeMounts }}
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- range .Values.persistence.extraExistingClaimMounts }}
|
{{- with .Values.extraContainers }}
|
||||||
- name: {{ .name }}
|
{{- toYaml . | nindent 8 }}
|
||||||
mountPath: {{ .mountPath }}
|
{{- end }}
|
||||||
readOnly: {{ .readOnly }}
|
{{- if or .Values.initContainers .Values.extraInitContainers }}
|
||||||
{{- end }}
|
# Support both initContainers (deprecated) and extraInitContainers for backward compatibility.
|
||||||
{{- if .Values.extraVolumeMounts }}
|
# TODO: Remove initContainers support after 2030
|
||||||
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.extraContainers }}
|
|
||||||
{{- toYaml .Values.extraContainers | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
resources:
|
|
||||||
{{ toYaml .Values.resources | indent 12 }}
|
|
||||||
terminationMessagePolicy: FallbackToLogsOnError
|
|
||||||
securityContext: {{- toYaml .Values.securityContext | nindent 12 }}
|
|
||||||
{{- if .Values.extraInitContainers }}
|
|
||||||
initContainers:
|
initContainers:
|
||||||
{{- toYaml .Values.extraInitContainers | nindent 10 }}
|
{{- if .Values.initContainers }}
|
||||||
{{- end }}
|
{{- toYaml .Values.initContainers | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.extraInitContainers }}
|
||||||
|
{{- toYaml .Values.extraInitContainers | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
volumes:
|
volumes:
|
||||||
- name: config
|
- name: config
|
||||||
{{- if .Values.persistence.config.enabled }}
|
{{- if .Values.persistence.config.enabled }}
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ if .Values.persistence.config.existingClaim }}{{ .Values.persistence.config.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-config{{- end }}
|
claimName: {{ if .Values.persistence.config.existingClaim }}{{ .Values.persistence.config.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-config{{- end }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
- name: media
|
- name: media
|
||||||
{{- if .Values.persistence.media.enabled }}
|
{{- if .Values.persistence.media.enabled }}
|
||||||
persistentVolumeClaim:
|
{{- if eq .Values.persistence.media.type "pvc" }}
|
||||||
claimName: {{ if .Values.persistence.media.existingClaim }}{{ .Values.persistence.media.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-media{{- end }}
|
persistentVolumeClaim:
|
||||||
{{- else }}
|
claimName: {{ if .Values.persistence.media.existingClaim }}{{ .Values.persistence.media.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-media{{- end }}
|
||||||
emptyDir: {}
|
{{- else if eq .Values.persistence.media.type "hostPath" }}
|
||||||
{{- end }}
|
hostPath:
|
||||||
{{- range .Values.persistence.extraExistingClaimMounts }}
|
path: {{ .Values.persistence.media.hostPath }}
|
||||||
- name: {{ .name }}
|
type: Directory
|
||||||
persistentVolumeClaim:
|
{{- else }}
|
||||||
claimName: {{ .existingClaim }}
|
emptyDir: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.extraVolumes }}
|
{{- else }}
|
||||||
{{- toYaml .Values.extraVolumes | nindent 6 }}
|
emptyDir: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.nodeSelector }}
|
- name: cache
|
||||||
|
{{- if .Values.persistence.cache.enabled }}
|
||||||
|
{{- if eq .Values.persistence.cache.type "pvc" }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ if .Values.persistence.cache.existingClaim }}{{ .Values.persistence.cache.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-cache{{- end }}
|
||||||
|
{{- else if eq .Values.persistence.cache.type "hostPath" }}
|
||||||
|
hostPath:
|
||||||
|
path: {{ .Values.persistence.cache.hostPath }}
|
||||||
|
type: Directory
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.volumes }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
{{ toYaml . | indent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.affinity }}
|
{{- with .Values.affinity }}
|
||||||
affinity:
|
affinity:
|
||||||
{{ toYaml . | indent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.tolerations }}
|
{{- with .Values.tolerations }}
|
||||||
tolerations:
|
tolerations:
|
||||||
{{ toYaml . | indent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }}
|
{{- with .Values.runtimeClassName }}
|
||||||
{{- if .Values.runtimeClassName }}
|
runtimeClassName: {{ . | quote }}
|
||||||
runtimeClassName: {{.Values.runtimeClassName}}
|
{{- end }}
|
||||||
{{- end }}
|
{{- with .Values.priorityClassName }}
|
||||||
|
priorityClassName: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.dnsConfig }}
|
||||||
|
dnsConfig:
|
||||||
|
{{- toYaml . | nindent 8}}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.dnsPolicy }}
|
||||||
|
dnsPolicy: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{{- if .Values.httpRoute.enabled }}
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.httpRoute.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.httpRoute.parentRefs }}
|
||||||
|
parentRefs:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.httpRoute.hostnames }}
|
||||||
|
hostnames:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.httpRoute.rules }}
|
||||||
|
- matches:
|
||||||
|
{{- range .matches }}
|
||||||
|
- path:
|
||||||
|
type: {{ .path.type }}
|
||||||
|
value: {{ .path.value }}
|
||||||
|
{{- end }}
|
||||||
|
backendRefs:
|
||||||
|
- name: {{ include "jellyfin.fullname" $ }}
|
||||||
|
port: {{ $.Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,50 +1,43 @@
|
|||||||
{{- if .Values.ingress.enabled -}}
|
{{- if .Values.ingress.enabled }}
|
||||||
{{- $fullName := include "jellyfin.fullname" . -}}
|
|
||||||
{{- $servicePort := .Values.service.port -}}
|
|
||||||
{{- $ingressPath := .Values.ingress.path -}}
|
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ $fullName }}
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
{{- with .Values.ingress.annotations }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- with .Values.ingress.labels }}
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.ingress.annotations }}
|
|
||||||
annotations:
|
annotations:
|
||||||
{{ toYaml . | indent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
{{- if or (.Capabilities.APIVersions.Has "networking.k8s.io/v1/IngressClass") (.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/IngressClass") }}
|
{{- with .Values.ingress.className }}
|
||||||
{{- if .Values.ingress.ingressClassName }}
|
ingressClassName: {{ . }}
|
||||||
ingressClassName: {{ .Values.ingress.ingressClassName }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- if .Values.ingress.tls }}
|
||||||
{{- if .Values.ingress.tls }}
|
|
||||||
tls:
|
tls:
|
||||||
{{- range .Values.ingress.tls }}
|
{{- range .Values.ingress.tls }}
|
||||||
- hosts:
|
- hosts:
|
||||||
{{- range .hosts }}
|
{{- range .hosts }}
|
||||||
- {{ . | quote }}
|
- {{ . | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
secretName: {{ .secretName }}
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
|
||||||
rules:
|
rules:
|
||||||
{{- range .Values.ingress.hosts }}
|
{{- range .Values.ingress.hosts }}
|
||||||
- host: {{ . | quote }}
|
- host: {{ .host | quote }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- pathType: Prefix
|
{{- range .paths }}
|
||||||
path: {{ $ingressPath }}
|
- path: {{ .path }}
|
||||||
|
{{- with .pathType }}
|
||||||
|
pathType: {{ . }}
|
||||||
|
{{- end }}
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: {{ $fullName }}
|
name: {{ include "jellyfin.fullname" $ }}
|
||||||
port:
|
port:
|
||||||
name: http
|
number: {{ $.Values.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
|
|
||||||
{{- if and .Values.persistence.media.enabled (not .Values.persistence.media.existingClaim) }}
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: {{ template "jellyfin.fullname" . }}-media
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
|
||||||
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- with .Values.persistence.media.labels }}
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.persistence.media.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
accessModes:
|
|
||||||
- {{ .Values.persistence.media.accessMode | quote }}
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: {{ .Values.persistence.media.size | quote }}
|
|
||||||
{{- if .Values.persistence.media.storageClass }}
|
|
||||||
{{- if (eq "-" .Values.persistence.media.storageClass) }}
|
|
||||||
storageClassName: ""
|
|
||||||
{{- else }}
|
|
||||||
storageClassName: "{{ .Values.persistence.media.storageClass }}"
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end -}}
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
{{- if .Values.networkPolicy.enabled }}
|
||||||
|
{{- if or .Values.jellyfin.enableDLNA .Values.podPrivileges.hostNetwork }}
|
||||||
|
{{- fail "NetworkPolicy cannot be enabled when hostNetwork is enabled (DLNA mode or podPrivileges.hostNetwork). NetworkPolicy does not apply to pods using hostNetwork. Please set networkPolicy.enabled=false or disable hostNetwork." }}
|
||||||
|
{{- end }}
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: NetworkPolicy
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "jellyfin.selectorLabels" . | nindent 6 }}
|
||||||
|
policyTypes:
|
||||||
|
{{- toYaml .Values.networkPolicy.policyTypes | nindent 4 }}
|
||||||
|
|
||||||
|
{{- if has "Ingress" .Values.networkPolicy.policyTypes }}
|
||||||
|
ingress:
|
||||||
|
# Allow traffic to Jellyfin HTTP port
|
||||||
|
- ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: http
|
||||||
|
{{- if not .Values.networkPolicy.ingress.allowExternal }}
|
||||||
|
from:
|
||||||
|
{{- if or .Values.networkPolicy.ingress.podSelector .Values.networkPolicy.ingress.namespaceSelector }}
|
||||||
|
- podSelector:
|
||||||
|
{{- toYaml .Values.networkPolicy.ingress.podSelector | nindent 12 }}
|
||||||
|
{{- if .Values.networkPolicy.ingress.namespaceSelector }}
|
||||||
|
namespaceSelector:
|
||||||
|
{{- toYaml .Values.networkPolicy.ingress.namespaceSelector | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }}
|
||||||
|
# Allow Prometheus metrics scraping
|
||||||
|
- ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: {{ .Values.metrics.serviceMonitor.port }}
|
||||||
|
from:
|
||||||
|
- podSelector:
|
||||||
|
{{- toYaml .Values.networkPolicy.metrics.podSelector | nindent 12 }}
|
||||||
|
{{- if .Values.networkPolicy.metrics.namespace }}
|
||||||
|
namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: {{ .Values.networkPolicy.metrics.namespace }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- with .Values.networkPolicy.ingress.customRules }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if has "Egress" .Values.networkPolicy.policyTypes }}
|
||||||
|
egress:
|
||||||
|
{{- if .Values.networkPolicy.egress.allowDNS }}
|
||||||
|
# Allow DNS resolution (required for Jellyfin operation)
|
||||||
|
- to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: {{ .Values.networkPolicy.egress.dnsNamespace }}
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
{{- toYaml .Values.networkPolicy.egress.dnsPodSelector | nindent 14 }}
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.networkPolicy.egress.allowAllEgress }}
|
||||||
|
# Allow all egress traffic (metadata providers, subtitles, images, etc.)
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
{{- else }}
|
||||||
|
{{- if .Values.networkPolicy.egress.restrictedEgress.allowMetadata }}
|
||||||
|
# Allow HTTPS for metadata providers (TMDB, TheTVDB, OpenSubtitles, etc.)
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.networkPolicy.egress.restrictedEgress.allowInCluster }}
|
||||||
|
# Allow pod-to-pod communication within the cluster
|
||||||
|
- to:
|
||||||
|
- podSelector: {}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- range .Values.networkPolicy.egress.restrictedEgress.allowedCIDRs }}
|
||||||
|
# Custom CIDR egress rule
|
||||||
|
- to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- with .Values.networkPolicy.egress.customRules }}
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
{{- if and .Values.persistence.config.enabled (not .Values.persistence.config.existingClaim) }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}-config
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.persistence.config.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.config.accessMode | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.config.size | quote }}
|
||||||
|
{{- with .Values.persistence.config.storageClass }}
|
||||||
|
storageClassName: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and .Values.persistence.media.enabled (eq .Values.persistence.media.type "pvc") (not .Values.persistence.media.existingClaim) }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}-media
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.persistence.media.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.media.accessMode | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.media.size | quote }}
|
||||||
|
{{- with .Values.persistence.media.storageClass }}
|
||||||
|
storageClassName: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and .Values.persistence.cache.enabled (eq .Values.persistence.cache.type "pvc") (not .Values.persistence.cache.existingClaim) }}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}-cache
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.persistence.cache.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.cache.accessMode | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.cache.size | quote }}
|
||||||
|
{{- with .Values.persistence.cache.storageClass }}
|
||||||
|
storageClassName: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,52 +1,58 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ template "jellyfin.fullname" . }}
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
helm.sh/chart: {{ include "jellyfin.chart" . }}
|
{{- with .Values.service.labels }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
{{- toYaml . | nindent 4 }}
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
{{- end }}
|
||||||
{{- if .Values.service.labels }}
|
{{- with .Values.service.annotations }}
|
||||||
{{ toYaml .Values.service.labels | indent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
annotations:
|
||||||
{{ toYaml . | indent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }}
|
|
||||||
type: ClusterIP
|
|
||||||
{{- if .Values.service.clusterIP }}
|
|
||||||
clusterIP: {{ .Values.service.clusterIP }}
|
|
||||||
{{end}}
|
|
||||||
{{- else if eq .Values.service.type "LoadBalancer" }}
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
{{- if .Values.service.loadBalancerIP }}
|
|
||||||
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.service.loadBalancerSourceRanges }}
|
spec:
|
||||||
|
{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }}
|
||||||
|
type: ClusterIP
|
||||||
|
{{- with .Values.service.clusterIP }}
|
||||||
|
clusterIP: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if eq .Values.service.type "LoadBalancer" }}
|
||||||
|
type: LoadBalancer
|
||||||
|
{{- with .Values.service.loadBalancerIP }}
|
||||||
|
loadBalancerIP: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.loadBalancerClass }}
|
||||||
|
loadBalancerClass: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.loadBalancerSourceRanges }}
|
||||||
loadBalancerSourceRanges:
|
loadBalancerSourceRanges:
|
||||||
{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end -}}
|
{{- end }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.service.type }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.service.externalIPs }}
|
{{- if .Values.service.ipFamilyPolicy }}
|
||||||
|
ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.service.ipFamilies }}
|
||||||
|
ipFamilies:
|
||||||
|
{{- toYaml .Values.service.ipFamilies | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.service.externalIPs }}
|
||||||
externalIPs:
|
externalIPs:
|
||||||
{{ toYaml .Values.service.externalIPs | indent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.service.externalTrafficPolicy }}
|
{{- with .Values.service.externalTrafficPolicy }}
|
||||||
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }}
|
externalTrafficPolicy: {{ . }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: {{ .Values.service.name | default "http" }}
|
||||||
port: {{ .Values.service.port }}
|
port: {{ .Values.service.port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: http
|
targetPort: http
|
||||||
{{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
|
{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
|
||||||
nodePort: {{.Values.service.nodePort}}
|
nodePort: {{ .Values.service.nodePort }}
|
||||||
{{ end }}
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
{{- include "jellyfin.selectorLabels" . | nindent 4 }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
{{- if and .Values.metrics.serviceMonitor.enabled .Values.metrics.enabled }}
|
||||||
|
---
|
||||||
|
apiVersion: monitoring.coreos.com/v1
|
||||||
|
kind: ServiceMonitor
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.fullname" . }}
|
||||||
|
{{- if .Values.metrics.serviceMonitor.namespace }}
|
||||||
|
namespace: {{ tpl .Values.metrics.serviceMonitor.namespace . }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.labels }}
|
||||||
|
{{- tpl (toYaml . | nindent 4) $ }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
endpoints:
|
||||||
|
- port: {{ .Values.service.name | default "http" }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.interval }}
|
||||||
|
interval: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.scrapeTimeout }}
|
||||||
|
scrapeTimeout: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
honorLabels: true
|
||||||
|
path: {{ .Values.metrics.serviceMonitor.path }}
|
||||||
|
scheme: {{ .Values.metrics.serviceMonitor.scheme }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.tlsConfig }}
|
||||||
|
tlsConfig:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.relabelings }}
|
||||||
|
relabelings:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.metricRelabelings }}
|
||||||
|
metricRelabelings:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
jobLabel: "{{ .Release.Name }}"
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: {{ include "jellyfin.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- with .Values.metrics.serviceMonitor.targetLabels }}
|
||||||
|
targetLabels:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "jellyfin.serviceAccountName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "jellyfin.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
suite: test cache persistence
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
- persistentVolumeClaim.yaml
|
||||||
|
tests:
|
||||||
|
# Deployment volume mount tests
|
||||||
|
- it: should mount cache as emptyDir by default
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
emptyDir: {}
|
||||||
|
|
||||||
|
- it: should mount cache PVC when enabled
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: RELEASE-NAME-jellyfin-cache
|
||||||
|
|
||||||
|
- it: should mount cache from hostPath when configured
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: hostPath
|
||||||
|
persistence.cache.hostPath: /mnt/jellyfin-cache
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/jellyfin-cache
|
||||||
|
|
||||||
|
- it: should mount cache at correct path
|
||||||
|
template: deployment.yaml
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].volumeMounts
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
mountPath: /cache
|
||||||
|
|
||||||
|
# PVC tests
|
||||||
|
- it: should not create cache PVC by default
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only
|
||||||
|
|
||||||
|
- it: should create cache PVC when enabled
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 3 # config, media, and cache
|
||||||
|
- contains:
|
||||||
|
path: metadata.name
|
||||||
|
content: RELEASE-NAME-jellyfin-cache
|
||||||
|
|
||||||
|
- it: should not create cache PVC when type is hostPath
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: hostPath
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only
|
||||||
|
|
||||||
|
- it: should not create cache PVC when type is emptyDir
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: emptyDir
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2
|
||||||
|
|
||||||
|
- it: should set cache PVC size correctly
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.size: 20Gi
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.resources.requests.storage
|
||||||
|
value: 20Gi
|
||||||
|
|
||||||
|
- it: should set cache PVC access mode
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.accessMode: ReadWriteMany
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.accessModes
|
||||||
|
content: ReadWriteMany
|
||||||
|
|
||||||
|
- it: should set cache PVC storage class
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.storageClass: fast-ssd
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.storageClassName
|
||||||
|
value: fast-ssd
|
||||||
|
|
||||||
|
- it: should add annotations to cache PVC
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
documentIndex: 2
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.annotations:
|
||||||
|
my-annotation: my-value
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.my-annotation
|
||||||
|
value: my-value
|
||||||
|
|
||||||
|
- it: should use existing claim when specified
|
||||||
|
template: deployment.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.existingClaim: my-existing-cache-claim
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.volumes
|
||||||
|
content:
|
||||||
|
name: cache
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: my-existing-cache-claim
|
||||||
|
|
||||||
|
- it: should not create PVC when existing claim used
|
||||||
|
template: persistentVolumeClaim.yaml
|
||||||
|
set:
|
||||||
|
persistence.cache.enabled: true
|
||||||
|
persistence.cache.type: pvc
|
||||||
|
persistence.cache.existingClaim: my-existing-cache-claim
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 2 # config and media only, not cache
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
suite: test envFrom
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
tests:
|
||||||
|
- it: should not have envFrom by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
|
||||||
|
- it: should add envFrom from ConfigMap
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: jellyfin-config
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 1
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
||||||
|
value: jellyfin-config
|
||||||
|
|
||||||
|
- it: should add envFrom from Secret
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: jellyfin-secrets
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].secretRef.name
|
||||||
|
value: jellyfin-secrets
|
||||||
|
|
||||||
|
- it: should support multiple envFrom sources
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: jellyfin-config
|
||||||
|
- secretRef:
|
||||||
|
name: jellyfin-secrets
|
||||||
|
- configMapRef:
|
||||||
|
name: jellyfin-extra-config
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
count: 3
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
||||||
|
value: jellyfin-config
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[1].secretRef.name
|
||||||
|
value: jellyfin-secrets
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[2].configMapRef.name
|
||||||
|
value: jellyfin-extra-config
|
||||||
|
|
||||||
|
- it: should support optional ConfigMap
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: optional-config
|
||||||
|
optional: true
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.optional
|
||||||
|
value: true
|
||||||
|
|
||||||
|
- it: should support optional Secret
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: optional-secret
|
||||||
|
optional: true
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].secretRef.optional
|
||||||
|
value: true
|
||||||
|
|
||||||
|
- it: should support prefix for ConfigMap
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: my-config
|
||||||
|
prefix: CONFIG_
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
value: CONFIG_
|
||||||
|
|
||||||
|
- it: should support prefix for Secret
|
||||||
|
set:
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: my-secret
|
||||||
|
prefix: SECRET_
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].prefix
|
||||||
|
value: SECRET_
|
||||||
|
|
||||||
|
- it: should work alongside regular env variables
|
||||||
|
set:
|
||||||
|
jellyfin.env:
|
||||||
|
- name: CUSTOM_VAR
|
||||||
|
value: custom-value
|
||||||
|
jellyfin.envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: jellyfin-config
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].env
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].envFrom
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.containers[0].env
|
||||||
|
content:
|
||||||
|
name: CUSTOM_VAR
|
||||||
|
value: custom-value
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].envFrom[0].configMapRef.name
|
||||||
|
value: jellyfin-config
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
suite: test httproute
|
||||||
|
templates:
|
||||||
|
- httproute.yaml
|
||||||
|
tests:
|
||||||
|
- it: should not create HTTPRoute by default
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 0
|
||||||
|
|
||||||
|
- it: should create HTTPRoute when enabled
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
namespace: gateway-system
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1
|
||||||
|
- isKind:
|
||||||
|
of: HTTPRoute
|
||||||
|
- isAPIVersion:
|
||||||
|
of: gateway.networking.k8s.io/v1
|
||||||
|
- equal:
|
||||||
|
path: metadata.name
|
||||||
|
value: RELEASE-NAME-jellyfin
|
||||||
|
|
||||||
|
- it: should add annotations when specified
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.annotations:
|
||||||
|
my-annotation: my-value
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: metadata.annotations.my-annotation
|
||||||
|
value: my-value
|
||||||
|
|
||||||
|
- it: should set parentRefs correctly
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
namespace: gateway-system
|
||||||
|
sectionName: https
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.parentRefs[0].name
|
||||||
|
value: my-gateway
|
||||||
|
- equal:
|
||||||
|
path: spec.parentRefs[0].namespace
|
||||||
|
value: gateway-system
|
||||||
|
- equal:
|
||||||
|
path: spec.parentRefs[0].sectionName
|
||||||
|
value: https
|
||||||
|
|
||||||
|
- it: should set hostnames when specified
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.hostnames:
|
||||||
|
- jellyfin.example.com
|
||||||
|
- media.example.com
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.hostnames[0]
|
||||||
|
value: jellyfin.example.com
|
||||||
|
- equal:
|
||||||
|
path: spec.hostnames[1]
|
||||||
|
value: media.example.com
|
||||||
|
|
||||||
|
- it: should create rules with path matches
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /jellyfin
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].matches[0].path.type
|
||||||
|
value: PathPrefix
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].matches[0].path.value
|
||||||
|
value: /jellyfin
|
||||||
|
|
||||||
|
- it: should set backendRefs to jellyfin service
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
service.port: 8096
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].backendRefs[0].name
|
||||||
|
value: RELEASE-NAME-jellyfin
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].backendRefs[0].port
|
||||||
|
value: 8096
|
||||||
|
|
||||||
|
- it: should support multiple rules
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: Exact
|
||||||
|
value: /api
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.rules
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].matches[0].path.value
|
||||||
|
value: /
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[1].matches[0].path.value
|
||||||
|
value: /api
|
||||||
|
|
||||||
|
- it: should support multiple matches in single rule
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /api
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /web
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.rules[0].matches
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].matches[0].path.value
|
||||||
|
value: /api
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].matches[1].path.value
|
||||||
|
value: /web
|
||||||
|
|
||||||
|
- it: should use custom service port
|
||||||
|
set:
|
||||||
|
httpRoute.enabled: true
|
||||||
|
service.port: 9000
|
||||||
|
httpRoute.parentRefs:
|
||||||
|
- name: my-gateway
|
||||||
|
httpRoute.rules:
|
||||||
|
- matches:
|
||||||
|
- path:
|
||||||
|
type: PathPrefix
|
||||||
|
value: /
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.rules[0].backendRefs[0].port
|
||||||
|
value: 9000
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
suite: test init containers
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
tests:
|
||||||
|
- it: should not have init containers by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
|
||||||
|
- it: should add extraInitContainers when specified
|
||||||
|
set:
|
||||||
|
extraInitContainers:
|
||||||
|
- name: init-config
|
||||||
|
image: busybox:1.35
|
||||||
|
command: ['sh', '-c', 'echo Initializing']
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 1
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: init-config
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].image
|
||||||
|
value: busybox:1.35
|
||||||
|
|
||||||
|
- it: should support multiple extraInitContainers
|
||||||
|
set:
|
||||||
|
extraInitContainers:
|
||||||
|
- name: init-1
|
||||||
|
image: busybox:1.35
|
||||||
|
- name: init-2
|
||||||
|
image: alpine:3.18
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: init-1
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[1].name
|
||||||
|
value: init-2
|
||||||
|
|
||||||
|
- it: should preserve full container spec in extraInitContainers
|
||||||
|
set:
|
||||||
|
extraInitContainers:
|
||||||
|
- name: init-permissions
|
||||||
|
image: busybox:1.35
|
||||||
|
command: ['sh', '-c']
|
||||||
|
args: ['chown -R 1000:1000 /config']
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /config
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].command[0]
|
||||||
|
value: sh
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].args[0]
|
||||||
|
value: 'chown -R 1000:1000 /config'
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].volumeMounts[0].name
|
||||||
|
value: config
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].securityContext.runAsUser
|
||||||
|
value: 0
|
||||||
|
|
||||||
|
# Deprecated initContainers (backward compatibility)
|
||||||
|
- it: should still support deprecated initContainers parameter
|
||||||
|
set:
|
||||||
|
initContainers:
|
||||||
|
- name: legacy-init
|
||||||
|
image: busybox:1.35
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 1
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: legacy-init
|
||||||
|
|
||||||
|
- it: should merge initContainers and extraInitContainers
|
||||||
|
set:
|
||||||
|
initContainers:
|
||||||
|
- name: legacy-init
|
||||||
|
image: busybox:1.35
|
||||||
|
extraInitContainers:
|
||||||
|
- name: new-init
|
||||||
|
image: alpine:3.18
|
||||||
|
asserts:
|
||||||
|
- lengthEqual:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
count: 2
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[0].name
|
||||||
|
value: legacy-init
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.initContainers[1].name
|
||||||
|
value: new-init
|
||||||
|
|
||||||
|
- it: should prioritize extraInitContainers over initContainers
|
||||||
|
set:
|
||||||
|
initContainers:
|
||||||
|
- name: old-way
|
||||||
|
image: busybox:1.35
|
||||||
|
extraInitContainers:
|
||||||
|
- name: new-way
|
||||||
|
image: alpine:3.18
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.template.spec.initContainers
|
||||||
|
content:
|
||||||
|
name: new-way
|
||||||
|
image: alpine:3.18
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
suite: test networkpolicy
|
||||||
|
templates:
|
||||||
|
- networkpolicy.yaml
|
||||||
|
tests:
|
||||||
|
- it: should not create NetworkPolicy by default
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 0
|
||||||
|
|
||||||
|
- it: should create NetworkPolicy when enabled
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- hasDocuments:
|
||||||
|
count: 1
|
||||||
|
- isKind:
|
||||||
|
of: NetworkPolicy
|
||||||
|
- isAPIVersion:
|
||||||
|
of: networking.k8s.io/v1
|
||||||
|
- equal:
|
||||||
|
path: metadata.name
|
||||||
|
value: RELEASE-NAME-jellyfin
|
||||||
|
|
||||||
|
- it: should fail when NetworkPolicy enabled with DLNA
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
jellyfin.enableDLNA: true
|
||||||
|
asserts:
|
||||||
|
- failedTemplate:
|
||||||
|
errorMessage: "NetworkPolicy cannot be enabled when hostNetwork is enabled"
|
||||||
|
|
||||||
|
- it: should fail when NetworkPolicy enabled with hostNetwork
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
podPrivileges.hostNetwork: true
|
||||||
|
asserts:
|
||||||
|
- failedTemplate:
|
||||||
|
errorMessage: "NetworkPolicy cannot be enabled when hostNetwork is enabled"
|
||||||
|
|
||||||
|
- it: should have both Ingress and Egress policy types by default
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.policyTypes
|
||||||
|
content: Ingress
|
||||||
|
- contains:
|
||||||
|
path: spec.policyTypes
|
||||||
|
content: Egress
|
||||||
|
|
||||||
|
- it: should allow external ingress by default
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.ingress
|
||||||
|
# When allowExternal is true, there should be no 'from' in first ingress rule
|
||||||
|
- isNull:
|
||||||
|
path: spec.ingress[0].from
|
||||||
|
|
||||||
|
- it: should restrict ingress when allowExternal is false
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.ingress.allowExternal: false
|
||||||
|
networkPolicy.ingress.podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: test
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.ingress[0].from
|
||||||
|
- equal:
|
||||||
|
path: spec.ingress[0].from[0].podSelector.matchLabels.app
|
||||||
|
value: test
|
||||||
|
|
||||||
|
- it: should add namespace selector for ingress when specified
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.ingress.allowExternal: false
|
||||||
|
networkPolicy.ingress.namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: frontend
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ingress[0].from[0].namespaceSelector.matchLabels.name
|
||||||
|
value: frontend
|
||||||
|
|
||||||
|
- it: should create Prometheus ingress rule when metrics enabled
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
metrics.enabled: true
|
||||||
|
metrics.serviceMonitor.enabled: true
|
||||||
|
metrics.serviceMonitor.port: 8096
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.ingress
|
||||||
|
content:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 8096
|
||||||
|
from:
|
||||||
|
- podSelector:
|
||||||
|
app.kubernetes.io/name: prometheus
|
||||||
|
|
||||||
|
- it: should add Prometheus namespace selector when specified
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
metrics.enabled: true
|
||||||
|
metrics.serviceMonitor.enabled: true
|
||||||
|
networkPolicy.metrics.namespace: monitoring
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.ingress[1].from[0].namespaceSelector
|
||||||
|
- equal:
|
||||||
|
path: spec.ingress[1].from[0].namespaceSelector.matchLabels.kubernetes.io/metadata.name
|
||||||
|
value: monitoring
|
||||||
|
|
||||||
|
- it: should add custom ingress rules
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.ingress.customRules:
|
||||||
|
- from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: custom
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9999
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.ingress
|
||||||
|
content:
|
||||||
|
from:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
name: custom
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 9999
|
||||||
|
|
||||||
|
- it: should allow DNS egress by default
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- namespaceSelector:
|
||||||
|
matchLabels:
|
||||||
|
kubernetes.io/metadata.name: kube-system
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
- it: should allow custom DNS namespace
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.dnsNamespace: custom-dns-ns
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.egress[0].to[0].namespaceSelector.matchLabels.kubernetes.io/metadata.name
|
||||||
|
value: custom-dns-ns
|
||||||
|
|
||||||
|
- it: should allow custom DNS pod selector
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.dnsPodSelector:
|
||||||
|
k8s-app: coredns
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.egress[0].to[0].podSelector.matchLabels.k8s-app
|
||||||
|
value: coredns
|
||||||
|
|
||||||
|
- it: should allow all egress by default
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
|
||||||
|
- it: should not allow all egress when allowAllEgress is false
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
asserts:
|
||||||
|
- notContains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
|
||||||
|
- it: should allow HTTPS when restrictedEgress.allowMetadata is true
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress.allowMetadata: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 0.0.0.0/0
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 443
|
||||||
|
|
||||||
|
- it: should allow in-cluster communication when restrictedEgress.allowInCluster is true
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress.allowInCluster: true
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- podSelector: {}
|
||||||
|
|
||||||
|
- it: should add custom CIDR blocks
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowAllEgress: false
|
||||||
|
networkPolicy.egress.restrictedEgress.allowedCIDRs:
|
||||||
|
- 10.0.0.0/8
|
||||||
|
- 192.168.0.0/16
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 10.0.0.0/8
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- ipBlock:
|
||||||
|
cidr: 192.168.0.0/16
|
||||||
|
|
||||||
|
- it: should add custom egress rules
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.customRules:
|
||||||
|
- to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: database
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
asserts:
|
||||||
|
- contains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
to:
|
||||||
|
- podSelector:
|
||||||
|
matchLabels:
|
||||||
|
app: database
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 5432
|
||||||
|
|
||||||
|
- it: should not create DNS egress when allowDNS is false
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
networkPolicy.egress.allowDNS: false
|
||||||
|
asserts:
|
||||||
|
- notContains:
|
||||||
|
path: spec.egress
|
||||||
|
content:
|
||||||
|
ports:
|
||||||
|
- protocol: UDP
|
||||||
|
port: 53
|
||||||
|
- protocol: TCP
|
||||||
|
port: 53
|
||||||
|
|
||||||
|
- it: should use correct pod selector labels
|
||||||
|
set:
|
||||||
|
networkPolicy.enabled: true
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.podSelector.matchLabels.app\.kubernetes\.io/name
|
||||||
|
value: jellyfin
|
||||||
|
- equal:
|
||||||
|
path: spec.podSelector.matchLabels.app\.kubernetes\.io/instance
|
||||||
|
value: RELEASE-NAME
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
suite: test revision history limit
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
tests:
|
||||||
|
- it: should set revisionHistoryLimit to 3 by default
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.revisionHistoryLimit
|
||||||
|
value: 3
|
||||||
|
|
||||||
|
- it: should allow custom revisionHistoryLimit
|
||||||
|
set:
|
||||||
|
revisionHistoryLimit: 5
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.revisionHistoryLimit
|
||||||
|
value: 5
|
||||||
|
|
||||||
|
- it: should allow revisionHistoryLimit of 0
|
||||||
|
set:
|
||||||
|
revisionHistoryLimit: 0
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.revisionHistoryLimit
|
||||||
|
value: 0
|
||||||
|
|
||||||
|
- it: should allow revisionHistoryLimit of 1
|
||||||
|
set:
|
||||||
|
revisionHistoryLimit: 1
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.revisionHistoryLimit
|
||||||
|
value: 1
|
||||||
|
|
||||||
|
- it: should allow large revisionHistoryLimit
|
||||||
|
set:
|
||||||
|
revisionHistoryLimit: 100
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.revisionHistoryLimit
|
||||||
|
value: 100
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
suite: test service ipv6 and dual-stack
|
||||||
|
templates:
|
||||||
|
- service.yaml
|
||||||
|
tests:
|
||||||
|
- it: should not set ipFamilyPolicy by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
|
||||||
|
- it: should not set ipFamilies by default
|
||||||
|
asserts:
|
||||||
|
- isNull:
|
||||||
|
path: spec.ipFamilies
|
||||||
|
|
||||||
|
- it: should set ipFamilyPolicy when specified
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: PreferDualStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: PreferDualStack
|
||||||
|
|
||||||
|
- it: should support SingleStack policy
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: SingleStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: SingleStack
|
||||||
|
|
||||||
|
- it: should support RequireDualStack policy
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: RequireDualStack
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: RequireDualStack
|
||||||
|
|
||||||
|
- it: should set ipFamilies for IPv4 only
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should set ipFamilies for IPv6 only
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should set ipFamilies for dual-stack IPv4 primary
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should set ipFamilies for dual-stack IPv6 primary
|
||||||
|
set:
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should work with PreferDualStack and both families
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: PreferDualStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv4
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: PreferDualStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv4
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv6
|
||||||
|
|
||||||
|
- it: should work with RequireDualStack and both families
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: RequireDualStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
- IPv4
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: RequireDualStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[1]
|
||||||
|
value: IPv4
|
||||||
|
|
||||||
|
- it: should work with SingleStack IPv6 only
|
||||||
|
set:
|
||||||
|
service.ipFamilyPolicy: SingleStack
|
||||||
|
service.ipFamilies:
|
||||||
|
- IPv6
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilyPolicy
|
||||||
|
value: SingleStack
|
||||||
|
- equal:
|
||||||
|
path: spec.ipFamilies[0]
|
||||||
|
value: IPv6
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
suite: test startup probe
|
||||||
|
templates:
|
||||||
|
- deployment.yaml
|
||||||
|
tests:
|
||||||
|
- it: should have startup probe by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe
|
||||||
|
|
||||||
|
- it: should use tcpSocket by default
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should have default timing values
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
||||||
|
value: 0
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 10
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 30
|
||||||
|
|
||||||
|
- it: should allow custom initialDelaySeconds
|
||||||
|
set:
|
||||||
|
startupProbe.initialDelaySeconds: 5
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
|
||||||
|
value: 5
|
||||||
|
|
||||||
|
- it: should allow custom periodSeconds
|
||||||
|
set:
|
||||||
|
startupProbe.periodSeconds: 15
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 15
|
||||||
|
|
||||||
|
- it: should allow custom failureThreshold
|
||||||
|
set:
|
||||||
|
startupProbe.failureThreshold: 60
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 60
|
||||||
|
|
||||||
|
- it: should support httpGet probe
|
||||||
|
set:
|
||||||
|
startupProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
asserts:
|
||||||
|
- isNotNull:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet.path
|
||||||
|
value: /health
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.httpGet.port
|
||||||
|
value: http
|
||||||
|
|
||||||
|
- it: should support custom port
|
||||||
|
set:
|
||||||
|
startupProbe.tcpSocket.port: 9000
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.tcpSocket.port
|
||||||
|
value: 9000
|
||||||
|
|
||||||
|
- it: should calculate correct timeout window
|
||||||
|
set:
|
||||||
|
startupProbe.periodSeconds: 10
|
||||||
|
startupProbe.failureThreshold: 30
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.periodSeconds
|
||||||
|
value: 10
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[0].startupProbe.failureThreshold
|
||||||
|
value: 30
|
||||||
|
# Total startup time allowed: 10 * 30 = 300 seconds (5 minutes)
|
||||||
+452
-120
@@ -1,174 +1,506 @@
|
|||||||
# -- Number of jellyfin replicas to start. Should be left at 1
|
# Default values for Jellyfin.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
|
||||||
|
# -- Number of Jellyfin replicas to start. Should be left at 1.
|
||||||
replicaCount: 1
|
replicaCount: 1
|
||||||
|
|
||||||
|
# -- Number of old ReplicaSets to retain for rollback history.
|
||||||
|
# Set to 0 to disable revision history (not recommended).
|
||||||
|
# If not specified, Kubernetes defaults to 10.
|
||||||
|
# See: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit
|
||||||
|
revisionHistoryLimit: 3
|
||||||
|
|
||||||
|
# -- Image pull secrets to authenticate with private repositories.
|
||||||
|
# See: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||||
imagePullSecrets: []
|
imagePullSecrets: []
|
||||||
|
|
||||||
image:
|
image:
|
||||||
# -- Set cutom repository for jellyfin image
|
# -- Container image repository for Jellyfin.
|
||||||
repository: docker.io/jellyfin/jellyfin
|
repository: docker.io/jellyfin/jellyfin
|
||||||
# -- Set jellyfin version which should be required since chart is updated with new versions automatically
|
# -- Jellyfin container image tag. Leave empty to automatically use the Chart's app version.
|
||||||
tag: ""
|
tag: ""
|
||||||
|
# -- Image pull policy (Always, IfNotPresent, or Never).
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# -- Override the default name of the chart.
|
||||||
nameOverride: ""
|
nameOverride: ""
|
||||||
|
# -- Override the default full name of the chart.
|
||||||
fullnameOverride: ""
|
fullnameOverride: ""
|
||||||
|
|
||||||
# -- Setting this to true enables DLNA which requires the pod to be attached to the
|
# -- Service account configuration. See: https://kubernetes.io/docs/concepts/security/service-accounts/
|
||||||
# host network in order to be useful - this can break things like ingress to the service
|
serviceAccount:
|
||||||
# https://jellyfin.org/docs/general/networking/dlna.html
|
# -- Specifies whether to create a service account.
|
||||||
enableDLNA: false
|
create: true
|
||||||
|
# -- Automatically mount API credentials for the service account.
|
||||||
|
automount: true
|
||||||
|
# -- Annotations for the service account.
|
||||||
|
annotations: {}
|
||||||
|
# -- Custom name for the service account. If left empty, the name will be autogenerated.
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
# -- Annotations to add to the pod.
|
||||||
|
podAnnotations: {}
|
||||||
|
# -- Additional labels to add to the pod.
|
||||||
|
podLabels: {}
|
||||||
|
|
||||||
|
# -- Security context for the pod.
|
||||||
|
podSecurityContext: {}
|
||||||
|
# fsGroup: 2000
|
||||||
|
|
||||||
|
# -- Security context for the container.
|
||||||
|
securityContext: {}
|
||||||
|
# capabilities:
|
||||||
|
# drop:
|
||||||
|
# - ALL
|
||||||
|
# readOnlyRootFilesystem: true
|
||||||
|
# runAsNonRoot: true
|
||||||
|
# runAsUser: 1000
|
||||||
|
|
||||||
|
# -- Define a custom runtimeClassName for the pod.
|
||||||
|
runtimeClassName: ''
|
||||||
|
|
||||||
|
# -- Define a priorityClassName for the pod.
|
||||||
|
priorityClassName: ""
|
||||||
|
|
||||||
|
# -- Define a dnsConfig. See https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config
|
||||||
|
# Use this to provide a custom DNS resolver configuration
|
||||||
|
dnsConfig: {}
|
||||||
|
# nameservers:
|
||||||
|
# - 192.0.2.1
|
||||||
|
# searches:
|
||||||
|
# - ns1.svc.cluster-domain.example
|
||||||
|
# - my.dns.search.suffix
|
||||||
|
# options:
|
||||||
|
# - name: ndots
|
||||||
|
# value: "2"
|
||||||
|
# - name: edns0
|
||||||
|
|
||||||
|
# -- Define a dnsPolicy. See https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy
|
||||||
|
dnsPolicy: ""
|
||||||
|
|
||||||
|
# -- Deployment strategy configuration. See `kubectl explain deployment.spec.strategy`.
|
||||||
|
deploymentStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
|
||||||
|
# -- Annotations to add to the deployment.
|
||||||
|
deploymentAnnotations: {}
|
||||||
|
|
||||||
service:
|
service:
|
||||||
|
# # -- Custom name for the service port
|
||||||
|
# name: http
|
||||||
|
# -- Service type (ClusterIP, NodePort, or LoadBalancer).
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
|
# -- Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/
|
||||||
|
# Options: SingleStack, PreferDualStack, RequireDualStack
|
||||||
|
# For IPv6-only clusters, use "SingleStack" with ipFamilies: ["IPv6"]
|
||||||
|
# For dual-stack, use "PreferDualStack" or "RequireDualStack" with ipFamilies: ["IPv4", "IPv6"] or ["IPv6", "IPv4"]
|
||||||
|
ipFamilyPolicy: ""
|
||||||
|
# -- Supported IP families (IPv4, IPv6).
|
||||||
|
# Examples:
|
||||||
|
# IPv4 only: ["IPv4"]
|
||||||
|
# IPv6 only: ["IPv6"]
|
||||||
|
# Dual-stack (IPv4 primary): ["IPv4", "IPv6"]
|
||||||
|
# Dual-stack (IPv6 primary): ["IPv6", "IPv4"]
|
||||||
|
# Note: When using IPv6, ensure your health checks are compatible (consider using httpGet instead of tcpSocket)
|
||||||
|
ipFamilies: []
|
||||||
|
# -- Specific IP address for the LoadBalancer.
|
||||||
|
loadBalancerIP: ""
|
||||||
|
# -- Class of the LoadBalancer.
|
||||||
|
loadBalancerClass: ""
|
||||||
|
# -- Source ranges allowed to access the LoadBalancer.
|
||||||
|
loadBalancerSourceRanges: []
|
||||||
|
# -- Port for the Jellyfin service.
|
||||||
port: 8096
|
port: 8096
|
||||||
## Specify the nodePort value for the LoadBalancer and NodePort service types.
|
# -- Name of the port in the service.
|
||||||
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
|
portName: service
|
||||||
##
|
# -- Annotations for the service.
|
||||||
# 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: {}
|
annotations: {}
|
||||||
|
# -- Labels for the service.
|
||||||
labels: {}
|
labels: {}
|
||||||
## Use loadBalancerIP to request a specific static IP,
|
# -- External traffic policy (Cluster or Local).
|
||||||
## otherwise leave blank
|
|
||||||
##
|
|
||||||
loadBalancerIP:
|
|
||||||
# loadBalancerSourceRanges: []
|
|
||||||
## Set the externalTrafficPolicy in the Service to either Cluster or Local
|
|
||||||
# externalTrafficPolicy: Cluster
|
# externalTrafficPolicy: Cluster
|
||||||
|
# -- NodePort for the service (if applicable).
|
||||||
|
# nodePort:
|
||||||
|
|
||||||
|
# -- Ingress configuration. See: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||||
ingress:
|
ingress:
|
||||||
enabled: false
|
enabled: false
|
||||||
labels: {}
|
className: ""
|
||||||
annotations: {}
|
annotations: {}
|
||||||
# kubernetes.io/ingress.class: nginx
|
# kubernetes.io/ingress.class: nginx
|
||||||
# kubernetes.io/tls-acme: "true"
|
# kubernetes.io/tls-acme: "true"
|
||||||
path: /
|
|
||||||
hosts:
|
hosts:
|
||||||
- chart-example.local
|
- host: chart-example.local
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
tls: []
|
tls: []
|
||||||
# - secretName: chart-example-tls
|
# - secretName: chart-example-tls
|
||||||
# hosts:
|
# hosts:
|
||||||
# - chart-example.local
|
# - chart-example.local
|
||||||
|
|
||||||
persistence:
|
# -- HTTPRoute configuration for Gateway API. See: https://gateway-api.sigs.k8s.io/
|
||||||
config:
|
httpRoute:
|
||||||
enabled: false
|
enabled: false
|
||||||
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner.
|
annotations: {}
|
||||||
storageClass: "-"
|
# -- Gateway references to attach this HTTPRoute to
|
||||||
## If you want to reuse an existing claim, you can pass the name of the PVC using
|
parentRefs: []
|
||||||
## the existingClaim variable
|
# - name: my-gateway
|
||||||
# existingClaim: your-claim
|
# namespace: gateway-system
|
||||||
# subPath: some-subpath
|
# sectionName: https
|
||||||
accessMode: ReadWriteOnce
|
# -- Hostnames to match for this HTTPRoute
|
||||||
size: 1Gi
|
hostnames: []
|
||||||
# -- Custom labels to be added to the PVC
|
# - jellyfin.example.com
|
||||||
labels: {}
|
# -- Rules for routing traffic
|
||||||
# -- Custom annotations to be added to the PVC
|
rules:
|
||||||
annotations: {}
|
- matches:
|
||||||
media:
|
- path:
|
||||||
enabled: false
|
type: PathPrefix
|
||||||
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner.
|
value: /
|
||||||
storageClass: "-"
|
|
||||||
## If you want to reuse an existing claim, you can pass the name of the PVC using
|
|
||||||
## the existingClaim variable
|
|
||||||
# existingClaim: your-claim
|
|
||||||
# subPath: some-subpath
|
|
||||||
accessMode: ReadWriteOnce
|
|
||||||
size: 10Gi
|
|
||||||
# -- Custom labels to be added to the PVC
|
|
||||||
labels: {}
|
|
||||||
# -- Custom annotations to be added to the PVC
|
|
||||||
annotations: {}
|
|
||||||
|
|
||||||
# -- Add aditional PVs/PVCs to our container. Check values.yaml to see an example.
|
|
||||||
extraExistingClaimMounts: []
|
|
||||||
# - name: external-mount
|
|
||||||
# mountPath: /srv/external-mount
|
|
||||||
## A manually managed Persistent Volume and Claim
|
|
||||||
## If defined, PVC must be created manually before volume will be bound
|
|
||||||
# existingClaim:
|
|
||||||
# readOnly: true
|
|
||||||
|
|
||||||
|
# -- Resource requests and limits for the Jellyfin container.
|
||||||
resources: {}
|
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:
|
# limits:
|
||||||
# cpu: 100m
|
# cpu: 100m
|
||||||
# memory: 128Mi
|
# memory: 128Mi
|
||||||
# requests:
|
# requests:
|
||||||
# cpu: 100m
|
# cpu: 100m
|
||||||
# memory: 128Mi
|
# memory: 128Mi
|
||||||
|
|
||||||
# Define a custom runtimeClassName for the pod, e.g. "nvidia" if you have the NVIDIA GPU Operator installed
|
# -- Configure startup probe for Jellyfin.
|
||||||
runtimeClassName:
|
# This probe gives Jellyfin enough time to start, especially with large media libraries.
|
||||||
|
# After the startup probe succeeds once, liveness and readiness probes take over.
|
||||||
|
startupProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 0
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 30
|
||||||
|
# With these defaults, Jellyfin has up to 5 minutes (30 * 10s) to start.
|
||||||
|
# Adjust failureThreshold if you have very large media libraries or slow storage.
|
||||||
|
|
||||||
|
# -- Configure liveness probe for Jellyfin.
|
||||||
|
# This probe is disabled during startup (startup probe handles initial checks).
|
||||||
|
# Uses httpGet for compatibility with both IPv4 and IPv6.
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
# successThreshold: 1
|
||||||
|
# failureThreshold: 3
|
||||||
|
# timeoutSeconds: 1
|
||||||
|
# periodSeconds: 10
|
||||||
|
|
||||||
|
# -- Configure readiness probe for Jellyfin.
|
||||||
|
# This probe is disabled during startup (startup probe handles initial checks).
|
||||||
|
# Uses httpGet for compatibility with both IPv4 and IPv6.
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /health
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
# successThreshold: 1
|
||||||
|
# failureThreshold: 3
|
||||||
|
# timeoutSeconds: 1
|
||||||
|
# periodSeconds: 10
|
||||||
|
|
||||||
|
# -- Additional volumes to mount in the Jellyfin pod.
|
||||||
|
volumes: []
|
||||||
|
# - name: foo
|
||||||
|
# secret:
|
||||||
|
# secretName: mysecret
|
||||||
|
# optional: false
|
||||||
|
|
||||||
|
# -- Additional volume mounts for the Jellyfin container.
|
||||||
|
volumeMounts: []
|
||||||
|
# - name: foo
|
||||||
|
# mountPath: "/etc/foo"
|
||||||
|
# readOnly: true
|
||||||
|
|
||||||
|
# -- Node selector for pod scheduling.
|
||||||
nodeSelector: {}
|
nodeSelector: {}
|
||||||
|
|
||||||
|
# -- Tolerations for pod scheduling.
|
||||||
tolerations: []
|
tolerations: []
|
||||||
|
|
||||||
|
# -- Affinity rules for pod scheduling.
|
||||||
affinity: {}
|
affinity: {}
|
||||||
|
|
||||||
# -- Define additional volumes to mount to the pod.
|
# -- Privileged pod settings for advanced use cases
|
||||||
extraVolumes: []
|
podPrivileges:
|
||||||
#- name: renderD129
|
# -- Enable hostIPC namespace. Required for NVIDIA MPS (Multi-Process Service) GPU sharing. See: https://docs.nvidia.com/deploy/mps/index.html
|
||||||
# hostPath:
|
hostIPC: false
|
||||||
# path: /dev/dri/renderD129
|
# -- Enable hostNetwork. Allows pod to use the host's network namespace.
|
||||||
|
hostNetwork: false
|
||||||
|
# -- Enable hostPID namespace. Allows pod to see processes on the host.
|
||||||
|
hostPID: false
|
||||||
|
|
||||||
# -- Define mount points for additional volumes.
|
jellyfin:
|
||||||
extraVolumeMounts: []
|
# -- Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html
|
||||||
#- mountPath: /dev/dri/renderD129
|
enableDLNA: false
|
||||||
# name: renderD129
|
# -- Custom command to use as container entrypoint.
|
||||||
|
command: []
|
||||||
|
# -- Additional arguments for the entrypoint command.
|
||||||
|
args: []
|
||||||
|
# -- Load environment variables from ConfigMap or Secret.
|
||||||
|
# See: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables
|
||||||
|
# Example:
|
||||||
|
# envFrom:
|
||||||
|
# - configMapRef:
|
||||||
|
# name: jellyfin-config
|
||||||
|
# - secretRef:
|
||||||
|
# name: jellyfin-secrets
|
||||||
|
envFrom: []
|
||||||
|
# -- Additional environment variables for the container.
|
||||||
|
# Example: Workaround for inotify limits (see Troubleshooting section in README)
|
||||||
|
# Example:
|
||||||
|
# env:
|
||||||
|
# - name: JELLYFIN_CACHE_DIR
|
||||||
|
# value: /cache
|
||||||
|
env: []
|
||||||
|
# - name: DOTNET_USE_POLLING_FILE_WATCHER
|
||||||
|
# value: "1"
|
||||||
|
|
||||||
# -- additional pod labels. Not used as a selector label.
|
persistence:
|
||||||
extraPodLabels: {}
|
config:
|
||||||
|
# -- set to false to use emptyDir
|
||||||
|
enabled: true
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 5Gi
|
||||||
|
# -- Custom annotations to be added to the PVC
|
||||||
|
annotations: {}
|
||||||
|
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner.
|
||||||
|
storageClass: ''
|
||||||
|
## -- Use an existing PVC for this mount
|
||||||
|
# existingClaim: ''
|
||||||
|
media:
|
||||||
|
# -- set to false to use emptyDir
|
||||||
|
enabled: true
|
||||||
|
# -- Type of volume for media storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting.
|
||||||
|
type: pvc
|
||||||
|
# -- Path on the host node for media storage, only used if type is 'hostPath'.
|
||||||
|
hostPath: ""
|
||||||
|
# -- PVC specific settings, only used if type is 'pvc'.
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 25Gi
|
||||||
|
# -- Custom annotations to be added to the PVC
|
||||||
|
annotations: {}
|
||||||
|
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner.
|
||||||
|
storageClass: ''
|
||||||
|
## -- Use an existing PVC for this mount
|
||||||
|
# existingClaim: ''
|
||||||
|
cache:
|
||||||
|
# -- set to false to use emptyDir
|
||||||
|
enabled: false
|
||||||
|
# -- Type of volume for cache storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting.
|
||||||
|
type: pvc
|
||||||
|
# -- Path on the host node for cache storage, only used if type is 'hostPath'.
|
||||||
|
hostPath: ""
|
||||||
|
# -- PVC specific settings, only used if type is 'pvc'.
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 10Gi
|
||||||
|
# -- Custom annotations to be added to the PVC
|
||||||
|
annotations: {}
|
||||||
|
# -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner.
|
||||||
|
storageClass: ''
|
||||||
|
## -- Use an existing PVC for this mount
|
||||||
|
# existingClaim: ''
|
||||||
|
|
||||||
# -- aditional environment variables passed to the pod
|
# -- Configuration for metrics collection and monitoring
|
||||||
extraEnvVars: []
|
metrics:
|
||||||
#- name: MY_ENV_VAR
|
# -- Enable or disable metrics collection
|
||||||
# value: my-env-var-value
|
enabled: false
|
||||||
|
# -- Configuration for the Prometheus ServiceMonitor
|
||||||
|
serviceMonitor:
|
||||||
|
# -- Enable or disable the creation of a ServiceMonitor resource
|
||||||
|
enabled: false
|
||||||
|
# -- Namespace where the ServiceMonitor resource should be created. Defaults to Release.Namespace
|
||||||
|
namespace: ''
|
||||||
|
# -- Labels to add to the ServiceMonitor resource
|
||||||
|
labels: {}
|
||||||
|
# -- Interval at which metrics should be scraped
|
||||||
|
interval: 30s
|
||||||
|
# -- Timeout for scraping metrics
|
||||||
|
scrapeTimeout: 30s
|
||||||
|
# -- Path to scrape for metrics
|
||||||
|
path: /metrics
|
||||||
|
# -- Port to scrape for metrics
|
||||||
|
port: 8096
|
||||||
|
# -- Scheme to use for scraping metrics (http or https)
|
||||||
|
scheme: http
|
||||||
|
# -- TLS configuration for scraping metrics
|
||||||
|
tlsConfig: {}
|
||||||
|
# -- Relabeling rules for the scraped metrics
|
||||||
|
relabelings: []
|
||||||
|
# -- Relabeling rules for the metrics before ingestion
|
||||||
|
metricRelabelings: []
|
||||||
|
# -- Target labels to add to the scraped metrics
|
||||||
|
targetLabels: []
|
||||||
|
|
||||||
# -- additional annotations applied to the pod
|
# -- DEPRECATED: Use extraInitContainers instead. Will be removed after 2030.
|
||||||
extraPodAnnotations: {}
|
# @deprecated - This parameter is deprecated, use extraInitContainers instead
|
||||||
|
initContainers: []
|
||||||
|
|
||||||
# -- additional init containers to run inside the pod.
|
# -- Additional init containers to run inside the pod.
|
||||||
|
# Init containers run before the main application container starts.
|
||||||
|
# See: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
|
||||||
|
# Example:
|
||||||
|
# extraInitContainers:
|
||||||
|
# - name: init-config
|
||||||
|
# image: busybox:1.35
|
||||||
|
# command: ['sh', '-c', 'echo "Initializing..." && sleep 5']
|
||||||
|
# volumeMounts:
|
||||||
|
# - name: config
|
||||||
|
# mountPath: /config
|
||||||
extraInitContainers: []
|
extraInitContainers: []
|
||||||
|
|
||||||
# -- additional sidecar containers to run inside the pod.
|
# -- additional sidecar containers to run inside the pod.
|
||||||
extraContainers: []
|
extraContainers: []
|
||||||
|
|
||||||
# -- SecurityContext configuration for the Jellyfin pod
|
# -- Network Policy configuration for network isolation and security.
|
||||||
podSecurityContext: {}
|
# Requires a CNI plugin that supports NetworkPolicy (Calico, Cilium, Weave, etc.).
|
||||||
# Jellyfin can be run as an unprivileged user with the following settings:
|
# WARNING: NetworkPolicy cannot be enabled when hostNetwork is used (DLNA mode).
|
||||||
# runAsUser: 65534
|
# The chart will fail with an error if both are enabled simultaneously.
|
||||||
# runAsGroup: 65534
|
networkPolicy:
|
||||||
|
# -- Enable NetworkPolicy for the Jellyfin pod.
|
||||||
|
# By default, this is disabled to maintain backward compatibility.
|
||||||
|
# When enabled, you can control which pods can access Jellyfin (ingress)
|
||||||
|
# and what external connections Jellyfin can make (egress).
|
||||||
|
enabled: false
|
||||||
|
|
||||||
# -- SecurityContext configuration for the Jellyfin container
|
# -- Policy types to enforce. Both ingress and egress policies can be enabled.
|
||||||
securityContext: {}
|
# See: https://kubernetes.io/docs/concepts/services-networking/network-policies/#policy-types
|
||||||
# For example, you might need to grant the following capabilities to enable hardware acceleration when mounting a /dev/dri device:
|
policyTypes:
|
||||||
# capabilities:
|
- Ingress
|
||||||
# add:
|
- Egress
|
||||||
# - "SYS_ADMIN"
|
|
||||||
# drop:
|
|
||||||
# - "ALL"
|
|
||||||
|
|
||||||
# -- Larger libraries may need to increase the readinessProbe and livenessProbe timeouts. Start by increasing the initialDelaySeconds.
|
# -- Ingress rules configuration - controls which pods/namespaces can access Jellyfin.
|
||||||
livenessProbe:
|
ingress:
|
||||||
enabled: true
|
# -- Allow external access from any namespace and any pod.
|
||||||
# failureThreshold: 3
|
# When true, any pod in the cluster can access Jellyfin (default behavior).
|
||||||
initialDelaySeconds: 10
|
# When false, only pods matching podSelector/namespaceSelector can access.
|
||||||
# periodSeconds: 10
|
# Set to false for production environments to restrict access.
|
||||||
# successThreshold: 1
|
allowExternal: true
|
||||||
# timeoutSeconds: 1
|
|
||||||
|
|
||||||
# -- Larger libraries may need to increase the readinessProbe and livenessProbe timeouts. Start by increasing the initialDelaySeconds.
|
# -- Custom pod selector for allowed ingress traffic.
|
||||||
readinessProbe:
|
# Only used when allowExternal is false.
|
||||||
enabled: true
|
# Allows you to specify which pods can access Jellyfin based on labels.
|
||||||
# failureThreshold: 3
|
# Example - only allow pods with specific label:
|
||||||
initialDelaySeconds: 10
|
# podSelector:
|
||||||
# periodSeconds: 10
|
# matchLabels:
|
||||||
# successThreshold: 1
|
# jellyfin-client: "true"
|
||||||
# timeoutSeconds: 1
|
podSelector: {}
|
||||||
|
|
||||||
|
# -- Namespace selector to allow cross-namespace ingress.
|
||||||
|
# Only used when allowExternal is false.
|
||||||
|
# Allows you to specify which namespaces can access Jellyfin.
|
||||||
|
# Example - only allow from ingress-nginx namespace:
|
||||||
|
# namespaceSelector:
|
||||||
|
# matchLabels:
|
||||||
|
# name: ingress-nginx
|
||||||
|
namespaceSelector: {}
|
||||||
|
|
||||||
|
# -- Additional custom ingress rules.
|
||||||
|
# Allows for complex scenarios not covered by the standard template.
|
||||||
|
# These rules are added as-is to the NetworkPolicy ingress section.
|
||||||
|
# Example - allow from monitoring namespace:
|
||||||
|
# customRules:
|
||||||
|
# - from:
|
||||||
|
# - namespaceSelector:
|
||||||
|
# matchLabels:
|
||||||
|
# name: monitoring
|
||||||
|
# ports:
|
||||||
|
# - protocol: TCP
|
||||||
|
# port: 8096
|
||||||
|
customRules: []
|
||||||
|
|
||||||
|
# -- Egress rules configuration - controls what external connections Jellyfin can make.
|
||||||
|
egress:
|
||||||
|
# -- Allow DNS resolution (required for Jellyfin to function).
|
||||||
|
# This adds an egress rule for kube-system namespace with kube-dns pods.
|
||||||
|
# DNS is required for resolving metadata provider domains and subtitle services.
|
||||||
|
# It is highly recommended to keep this enabled.
|
||||||
|
allowDNS: true
|
||||||
|
|
||||||
|
# -- DNS namespace where DNS service is running.
|
||||||
|
# Usually "kube-system" but can differ in some Kubernetes distributions.
|
||||||
|
dnsNamespace: kube-system
|
||||||
|
|
||||||
|
# -- DNS pod selector labels.
|
||||||
|
# Default selector is for kube-dns, but CoreDNS or other DNS providers
|
||||||
|
# may use different labels. Adjust if needed.
|
||||||
|
# Common alternatives:
|
||||||
|
# k8s-app: kube-dns (default)
|
||||||
|
# k8s-app: coredns
|
||||||
|
# app.kubernetes.io/name: coredns
|
||||||
|
dnsPodSelector:
|
||||||
|
k8s-app: kube-dns
|
||||||
|
|
||||||
|
# -- Allow all egress traffic (internet access for metadata, subtitles, images).
|
||||||
|
# When true, Jellyfin can connect to any external destination (0.0.0.0/0).
|
||||||
|
# This is the recommended default as Jellyfin needs internet access for:
|
||||||
|
# - Downloading movie/TV show metadata (TMDB, TheTVDB, OMDb)
|
||||||
|
# - Fetching poster images, fanart, and other artwork
|
||||||
|
# - Downloading subtitles (OpenSubtitles)
|
||||||
|
# - Updating plugins
|
||||||
|
# When false, you must configure restrictedEgress or customRules.
|
||||||
|
allowAllEgress: true
|
||||||
|
|
||||||
|
# -- Restricted egress mode for security-conscious deployments.
|
||||||
|
# Only used when allowAllEgress is false.
|
||||||
|
# Provides fine-grained control over outbound connections.
|
||||||
|
restrictedEgress:
|
||||||
|
# -- Allow HTTPS (443/TCP) for metadata providers.
|
||||||
|
# Most metadata providers (TMDB, TheTVDB, OpenSubtitles, Fanart.tv)
|
||||||
|
# use HTTPS, so this covers the majority of use cases.
|
||||||
|
# This allows connections to any IP on port 443.
|
||||||
|
allowMetadata: true
|
||||||
|
|
||||||
|
# -- Allow communication within the cluster (pod-to-pod).
|
||||||
|
# Useful if Jellyfin needs to connect to other services in the cluster.
|
||||||
|
# This allows connections to any pod in any namespace.
|
||||||
|
allowInCluster: true
|
||||||
|
|
||||||
|
# -- Additional IP CIDR blocks to allow egress.
|
||||||
|
# Useful for allowing specific IP ranges for metadata providers
|
||||||
|
# or other external services.
|
||||||
|
# Example - allow entire internet except private networks:
|
||||||
|
# allowedCIDRs:
|
||||||
|
# - 0.0.0.0/0
|
||||||
|
# Example - allow specific metadata provider IP ranges:
|
||||||
|
# allowedCIDRs:
|
||||||
|
# - 13.224.0.0/14 # CloudFront (used by many CDNs)
|
||||||
|
allowedCIDRs: []
|
||||||
|
|
||||||
|
# -- Additional custom egress rules.
|
||||||
|
# Allows for complex scenarios not covered by the standard template.
|
||||||
|
# These rules are added as-is to the NetworkPolicy egress section.
|
||||||
|
# Example - allow connections to specific database:
|
||||||
|
# customRules:
|
||||||
|
# - to:
|
||||||
|
# - podSelector:
|
||||||
|
# matchLabels:
|
||||||
|
# app: postgresql
|
||||||
|
# ports:
|
||||||
|
# - protocol: TCP
|
||||||
|
# port: 5432
|
||||||
|
customRules: []
|
||||||
|
|
||||||
|
# -- Prometheus metrics scraping configuration.
|
||||||
|
# Automatically allows ingress from Prometheus when metrics.serviceMonitor.enabled is true.
|
||||||
|
# This ensures Prometheus can scrape metrics without additional configuration.
|
||||||
|
metrics:
|
||||||
|
# -- Namespace where Prometheus is running.
|
||||||
|
# Leave empty to use the same namespace as Jellyfin.
|
||||||
|
# Set to the monitoring namespace if Prometheus is in a different namespace.
|
||||||
|
# Example: "monitoring" or "prometheus"
|
||||||
|
namespace: ""
|
||||||
|
|
||||||
|
# -- Pod selector for Prometheus pods.
|
||||||
|
# These labels must match your Prometheus deployment.
|
||||||
|
# The chart will automatically add an ingress rule for pods matching these labels.
|
||||||
|
# Default selector works with prometheus-operator and kube-prometheus-stack.
|
||||||
|
# Adjust if your Prometheus uses different labels.
|
||||||
|
podSelector:
|
||||||
|
app.kubernetes.io/name: prometheus
|
||||||
Reference in new issue
Block a user