Compare commits
No files matched your search
@@ -1 +0,0 @@
|
|||||||
.idea
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
{{description}}
|
|
||||||
Copyright (C) {{year}} {{fullname}}
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
{signature of Ty Coon}, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
# Jellyfin Helm Charts Repository
|
|
||||||
|
|
||||||
This repository contains Helm charts for the jellyfin project.
|
|
||||||
|
|
||||||
## Repository Structure
|
|
||||||
|
|
||||||
Each Helm chart is stored in its own directory. Each chart follows the standard Helm chart structure:
|
|
||||||
|
|
||||||
```plaintext
|
|
||||||
jellyfin-helm/
|
|
||||||
├── jellyfin/
|
|
||||||
│ ├── Chart.yaml
|
|
||||||
│ ├── values.yaml
|
|
||||||
│ ├── templates/
|
|
||||||
│ └── ...
|
|
||||||
├── chart2/
|
|
||||||
│ ├── Chart.yaml
|
|
||||||
│ ├── values.yaml
|
|
||||||
│ ├── templates/
|
|
||||||
│ └── ...
|
|
||||||
└── ...
|
|
||||||
```
|
|
||||||
|
|
||||||
- `Chart.yaml`: Contains metadata about the chart (name, version, app version, etc.).
|
|
||||||
- `values.yaml`: Default configuration values for the chart.
|
|
||||||
- `templates/`: The Kubernetes resource templates (YAML files) that Helm uses to deploy the chart.
|
|
||||||
|
|
||||||
## How to Use the Charts
|
|
||||||
|
|
||||||
### 1. Add this Repository
|
|
||||||
|
|
||||||
To use the charts in this repository, first add the repository to Helm:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
|
||||||
helm repo update
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Install a Chart
|
|
||||||
|
|
||||||
To install a chart from this repository, use the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install <release-name> jellyfin/<chart-name>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Customize Installation
|
|
||||||
|
|
||||||
You can customize the installation by passing in custom values via the `--set` flag or by using a `values.yaml` file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install <release-name> jellyfin/<chart-name> --set key=value
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install <release-name> jellyfin/<chart-name> -f custom-values.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Feel free to contribute to this repository by:
|
|
||||||
|
|
||||||
- Submitting new charts.
|
|
||||||
- Fixing bugs or issues.
|
|
||||||
- Improving documentation.
|
|
||||||
|
|
||||||
To contribute, fork this repository, create a new branch, and submit a pull request with your changes.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This repository is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# 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,40 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: jellyfin
|
|
||||||
description: A Helm chart for Jellyfin Media Server
|
|
||||||
type: application
|
|
||||||
home: https://jellyfin.org/
|
|
||||||
icon: https://jellyfin.org/images/logo.svg
|
|
||||||
keywords:
|
|
||||||
- jellyfin
|
|
||||||
- media
|
|
||||||
- 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
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,495 +0,0 @@
|
|||||||
# jellyfin
|
|
||||||
|
|
||||||
  
|
|
||||||
|
|
||||||
A Helm chart for Jellyfin Media Server
|
|
||||||
|
|
||||||
**Homepage:** <https://jellyfin.org/>
|
|
||||||
|
|
||||||
## Steps to Use a Helm Chart
|
|
||||||
|
|
||||||
### 1. Add a Helm Repository
|
|
||||||
|
|
||||||
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Install the Helm Chart
|
|
||||||
|
|
||||||
To install a chart, use the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. View the Installation
|
|
||||||
|
|
||||||
You can check the status of the release using:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm status my-jellyfin
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customizing the Chart
|
|
||||||
|
|
||||||
Helm charts come with default values, but you can customize them by using the --set flag or by providing a custom values.yaml file.
|
|
||||||
|
|
||||||
### 1. Using --set to Override Values
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Using a values.yaml File
|
|
||||||
You can create a custom values.yaml file and pass it to the install command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin -f values.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
## Values
|
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
|
||||||
|-----|------|---------|-------------|
|
|
||||||
| affinity | object | `{}` | Affinity rules for pod scheduling. |
|
|
||||||
| 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. |
|
|
||||||
| 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 |
|
|
||||||
| fullnameOverride | string | `""` | Override the default full name of the chart. |
|
|
||||||
| 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/ |
|
|
||||||
| httpRoute.hostnames | list | `[]` | Hostnames to match for this HTTPRoute |
|
|
||||||
| httpRoute.parentRefs | list | `[]` | Gateway references to attach this HTTPRoute to |
|
|
||||||
| httpRoute.rules | list | `[{"matches":[{"path":{"type":"PathPrefix","value":"/"}}]}]` | Rules for routing traffic |
|
|
||||||
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy (Always, IfNotPresent, or Never). |
|
|
||||||
| image.repository | string | `"docker.io/jellyfin/jellyfin"` | Container image repository for Jellyfin. |
|
|
||||||
| image.tag | string | `""` | Jellyfin container image tag. Leave empty to automatically use the Chart's app version. |
|
|
||||||
| imagePullSecrets | list | `[]` | Image pull secrets to authenticate with private repositories. See: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ |
|
|
||||||
| 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/ |
|
|
||||||
| initContainers | list | `[]` | DEPRECATED: Use extraInitContainers instead. Will be removed after 2030. @deprecated - This parameter is deprecated, use extraInitContainers instead |
|
|
||||||
| jellyfin.args | list | `[]` | Additional arguments for the entrypoint command. |
|
|
||||||
| jellyfin.command | list | `[]` | Custom command to use as container entrypoint. |
|
|
||||||
| jellyfin.enableDLNA | bool | `false` | Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html |
|
|
||||||
| 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 |
|
|
||||||
| 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 | `{"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. |
|
|
||||||
| 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 |
|
|
||||||
| 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.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
|
||||||
| persistence.config.enabled | bool | `true` | set to false to use emptyDir |
|
|
||||||
| persistence.config.size | string | `"5Gi"` | |
|
|
||||||
| 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.media.annotations | object | `{}` | Custom annotations to be added to the PVC |
|
|
||||||
| persistence.media.enabled | bool | `true` | set to false to use emptyDir |
|
|
||||||
| persistence.media.hostPath | string | `""` | Path on the host node for media storage, only used if type is 'hostPath'. |
|
|
||||||
| 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.type | string | `"pvc"` | Type of volume for media storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting. |
|
|
||||||
| podAnnotations | object | `{}` | Annotations to add to the pod. |
|
|
||||||
| podLabels | object | `{}` | Additional labels to add to the pod. |
|
|
||||||
| podPrivileges | object | `{"hostIPC":false,"hostNetwork":false,"hostPID":false}` | Privileged pod settings for advanced use cases |
|
|
||||||
| 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 |
|
|
||||||
| podPrivileges.hostNetwork | bool | `false` | Enable hostNetwork. Allows pod to use the host's network namespace. |
|
|
||||||
| podPrivileges.hostPID | bool | `false` | Enable hostPID namespace. Allows pod to see processes on the host. |
|
|
||||||
| podSecurityContext | object | `{}` | Security context for the pod. |
|
|
||||||
| priorityClassName | string | `""` | Define a priorityClassName for the pod. |
|
|
||||||
| 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. |
|
|
||||||
| replicaCount | int | `1` | Number of Jellyfin replicas to start. Should be left at 1. |
|
|
||||||
| 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)
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
|
||||||
Adding the following Helm values should make it enable you to use hardware acceleration features.
|
|
||||||
Some settings may need to be tweaked depending on the type of device (Intel/AMD/NVIDIA/...) and your container runtime.
|
|
||||||
|
|
||||||
Please refer to the Jellyfin upstream documentation for more information about hardware acceleration: <https://jellyfin.org/docs/general/administration/hardware-acceleration/>
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
securityContext:
|
|
||||||
capabilities:
|
|
||||||
add:
|
|
||||||
- "SYS_ADMIN"
|
|
||||||
drop:
|
|
||||||
- "ALL"
|
|
||||||
privileged: false
|
|
||||||
|
|
||||||
extraVolumes:
|
|
||||||
- name: hwa
|
|
||||||
hostPath:
|
|
||||||
path: /dev/dri
|
|
||||||
|
|
||||||
extraVolumeMounts:
|
|
||||||
- name: hwa
|
|
||||||
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,384 +0,0 @@
|
|||||||
{{ template "chart.header" . }}
|
|
||||||
{{ template "chart.deprecationWarning" . }}
|
|
||||||
|
|
||||||
{{ template "chart.badgesSection" . }}
|
|
||||||
|
|
||||||
{{ template "chart.description" . }}
|
|
||||||
|
|
||||||
{{ template "chart.homepageLine" . }}
|
|
||||||
|
|
||||||
## Steps to Use a Helm Chart
|
|
||||||
|
|
||||||
### 1. Add a Helm Repository
|
|
||||||
|
|
||||||
Helm repositories contain collections of charts. You can add an existing repository using the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Install the Helm Chart
|
|
||||||
|
|
||||||
To install a chart, use the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. View the Installation
|
|
||||||
|
|
||||||
You can check the status of the release using:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm status my-jellyfin
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customizing the Chart
|
|
||||||
|
|
||||||
Helm charts come with default values, but you can customize them by using the --set flag or by providing a custom values.yaml file.
|
|
||||||
|
|
||||||
### 1. Using --set to Override Values
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Using a values.yaml File
|
|
||||||
You can create a custom values.yaml file and pass it to the install command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
helm install my-jellyfin jellyfin/jellyfin -f values.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
{{ template "chart.maintainersSection" . }}
|
|
||||||
|
|
||||||
{{ template "chart.sourcesSection" . }}
|
|
||||||
|
|
||||||
{{ template "chart.requirementsSection" . }}
|
|
||||||
|
|
||||||
{{ template "chart.valuesSection" . }}
|
|
||||||
|
|
||||||
{{ 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
|
|
||||||
|
|
||||||
Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin.
|
|
||||||
Adding the following Helm values should make it enable you to use hardware acceleration features.
|
|
||||||
Some settings may need to be tweaked depending on the type of device (Intel/AMD/NVIDIA/...) and your container runtime.
|
|
||||||
|
|
||||||
Please refer to the Jellyfin upstream documentation for more information about hardware acceleration: <https://jellyfin.org/docs/general/administration/hardware-acceleration/>
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
securityContext:
|
|
||||||
capabilities:
|
|
||||||
add:
|
|
||||||
- "SYS_ADMIN"
|
|
||||||
drop:
|
|
||||||
- "ALL"
|
|
||||||
privileged: false
|
|
||||||
|
|
||||||
extraVolumes:
|
|
||||||
- name: hwa
|
|
||||||
hostPath:
|
|
||||||
path: /dev/dri
|
|
||||||
|
|
||||||
extraVolumeMounts:
|
|
||||||
- name: hwa
|
|
||||||
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,291 +0,0 @@
|
|||||||
{{- 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 }}
|
|
||||||
{{- range $host := .Values.ingress.hosts }}
|
|
||||||
{{- range .paths }}
|
|
||||||
|
|
||||||
Jellyfin is available at:
|
|
||||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- 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_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo "Jellyfin URL: http://$NODE_IP:$NODE_PORT"
|
|
||||||
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
|
|
||||||
Get the Jellyfin URL by running:
|
|
||||||
|
|
||||||
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 }}
|
|
||||||
|
|
||||||
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 CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Jellyfin URL: http://127.0.0.1:8080"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
|
|
||||||
{{- 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,69 +0,0 @@
|
|||||||
{{/*
|
|
||||||
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.
|
|
||||||
*/}}
|
|
||||||
{{- define "jellyfin.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "jellyfin.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "jellyfin.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- 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,217 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "jellyfin.fullname" . }}
|
|
||||||
{{- with .Values.deploymentAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "jellyfin.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.deploymentStrategy }}
|
|
||||||
strategy:
|
|
||||||
{{- toYaml . | trim | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
{{- with .Values.revisionHistoryLimit }}
|
|
||||||
revisionHistoryLimit: {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "jellyfin.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "jellyfin.labels" . | nindent 8 }}
|
|
||||||
{{- with .Values.podLabels }}
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "jellyfin.serviceAccountName" . }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
|
||||||
{{- if or .Values.jellyfin.enableDLNA .Values.podPrivileges.hostNetwork }}
|
|
||||||
hostNetwork: true
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.podPrivileges.hostIPC }}
|
|
||||||
hostIPC: true
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.podPrivileges.hostPID }}
|
|
||||||
hostPID: true
|
|
||||||
{{- end }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
|
||||||
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:
|
|
||||||
- name: http
|
|
||||||
containerPort: 8096
|
|
||||||
protocol: TCP
|
|
||||||
{{- if .Values.jellyfin.enableDLNA }}
|
|
||||||
- name: dlna
|
|
||||||
containerPort: 1900
|
|
||||||
hostPort: 1900
|
|
||||||
protocol: UDP
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.startupProbe }}
|
|
||||||
startupProbe:
|
|
||||||
{{- toYaml . | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
livenessProbe:
|
|
||||||
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
|
||||||
readinessProbe:
|
|
||||||
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /config
|
|
||||||
name: config
|
|
||||||
- mountPath: /media
|
|
||||||
name: media
|
|
||||||
- mountPath: /cache
|
|
||||||
name: cache
|
|
||||||
{{- with .Values.volumeMounts }}
|
|
||||||
{{- toYaml . | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.extraContainers }}
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if or .Values.initContainers .Values.extraInitContainers }}
|
|
||||||
# Support both initContainers (deprecated) and extraInitContainers for backward compatibility.
|
|
||||||
# TODO: Remove initContainers support after 2030
|
|
||||||
initContainers:
|
|
||||||
{{- if .Values.initContainers }}
|
|
||||||
{{- toYaml .Values.initContainers | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.extraInitContainers }}
|
|
||||||
{{- toYaml .Values.extraInitContainers | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
volumes:
|
|
||||||
- name: config
|
|
||||||
{{- if .Values.persistence.config.enabled }}
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: {{ if .Values.persistence.config.existingClaim }}{{ .Values.persistence.config.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-config{{- end }}
|
|
||||||
{{- else }}
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end }}
|
|
||||||
- name: media
|
|
||||||
{{- if .Values.persistence.media.enabled }}
|
|
||||||
{{- if eq .Values.persistence.media.type "pvc" }}
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: {{ if .Values.persistence.media.existingClaim }}{{ .Values.persistence.media.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-media{{- end }}
|
|
||||||
{{- else if eq .Values.persistence.media.type "hostPath" }}
|
|
||||||
hostPath:
|
|
||||||
path: {{ .Values.persistence.media.hostPath }}
|
|
||||||
type: Directory
|
|
||||||
{{- else }}
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end }}
|
|
||||||
{{- else }}
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end }}
|
|
||||||
- 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:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.runtimeClassName }}
|
|
||||||
runtimeClassName: {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.priorityClassName }}
|
|
||||||
priorityClassName: {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.dnsConfig }}
|
|
||||||
dnsConfig:
|
|
||||||
{{- toYaml . | nindent 8}}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.dnsPolicy }}
|
|
||||||
dnsPolicy: {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{{- 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,43 +0,0 @@
|
|||||||
{{- if .Values.ingress.enabled }}
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: {{ include "jellyfin.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "jellyfin.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.ingress.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.ingress.className }}
|
|
||||||
ingressClassName: {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.ingress.tls }}
|
|
||||||
tls:
|
|
||||||
{{- range .Values.ingress.tls }}
|
|
||||||
- hosts:
|
|
||||||
{{- range .hosts }}
|
|
||||||
- {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
secretName: {{ .secretName }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
rules:
|
|
||||||
{{- range .Values.ingress.hosts }}
|
|
||||||
- host: {{ .host | quote }}
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
{{- range .paths }}
|
|
||||||
- path: {{ .path }}
|
|
||||||
{{- with .pathType }}
|
|
||||||
pathType: {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: {{ include "jellyfin.fullname" $ }}
|
|
||||||
port:
|
|
||||||
number: {{ $.Values.service.port }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
{{- 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 }}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
{{- 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,58 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "jellyfin.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "jellyfin.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.service.labels }}
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
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:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else }}
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
{{- end }}
|
|
||||||
{{- 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:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.service.externalTrafficPolicy }}
|
|
||||||
externalTrafficPolicy: {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
ports:
|
|
||||||
- name: {{ .Values.service.name | default "http" }}
|
|
||||||
port: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: http
|
|
||||||
{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
|
|
||||||
nodePort: {{ .Values.service.nodePort }}
|
|
||||||
{{- end }}
|
|
||||||
selector:
|
|
||||||
{{- include "jellyfin.selectorLabels" . | nindent 4 }}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{{- 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 }}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{{- 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 }}
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,297 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
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)
|
|
||||||
@@ -1,506 +0,0 @@
|
|||||||
# Default values for Jellyfin.
|
|
||||||
# This is a YAML-formatted file.
|
|
||||||
|
|
||||||
# -- Number of Jellyfin replicas to start. Should be left at 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: []
|
|
||||||
|
|
||||||
image:
|
|
||||||
# -- Container image repository for Jellyfin.
|
|
||||||
repository: docker.io/jellyfin/jellyfin
|
|
||||||
# -- Jellyfin container image tag. Leave empty to automatically use the Chart's app version.
|
|
||||||
tag: ""
|
|
||||||
# -- Image pull policy (Always, IfNotPresent, or Never).
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
|
|
||||||
# -- Override the default name of the chart.
|
|
||||||
nameOverride: ""
|
|
||||||
# -- Override the default full name of the chart.
|
|
||||||
fullnameOverride: ""
|
|
||||||
|
|
||||||
# -- Service account configuration. See: https://kubernetes.io/docs/concepts/security/service-accounts/
|
|
||||||
serviceAccount:
|
|
||||||
# -- Specifies whether to create a service account.
|
|
||||||
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:
|
|
||||||
# # -- Custom name for the service port
|
|
||||||
# name: http
|
|
||||||
# -- Service type (ClusterIP, NodePort, or LoadBalancer).
|
|
||||||
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
|
|
||||||
# -- Name of the port in the service.
|
|
||||||
portName: service
|
|
||||||
# -- Annotations for the service.
|
|
||||||
annotations: {}
|
|
||||||
# -- Labels for the service.
|
|
||||||
labels: {}
|
|
||||||
# -- External traffic policy (Cluster or Local).
|
|
||||||
# externalTrafficPolicy: Cluster
|
|
||||||
# -- NodePort for the service (if applicable).
|
|
||||||
# nodePort:
|
|
||||||
|
|
||||||
# -- Ingress configuration. See: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
|
||||||
ingress:
|
|
||||||
enabled: false
|
|
||||||
className: ""
|
|
||||||
annotations: {}
|
|
||||||
# kubernetes.io/ingress.class: nginx
|
|
||||||
# kubernetes.io/tls-acme: "true"
|
|
||||||
hosts:
|
|
||||||
- host: chart-example.local
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: ImplementationSpecific
|
|
||||||
tls: []
|
|
||||||
# - secretName: chart-example-tls
|
|
||||||
# hosts:
|
|
||||||
# - chart-example.local
|
|
||||||
|
|
||||||
# -- HTTPRoute configuration for Gateway API. See: https://gateway-api.sigs.k8s.io/
|
|
||||||
httpRoute:
|
|
||||||
enabled: false
|
|
||||||
annotations: {}
|
|
||||||
# -- Gateway references to attach this HTTPRoute to
|
|
||||||
parentRefs: []
|
|
||||||
# - name: my-gateway
|
|
||||||
# namespace: gateway-system
|
|
||||||
# sectionName: https
|
|
||||||
# -- Hostnames to match for this HTTPRoute
|
|
||||||
hostnames: []
|
|
||||||
# - jellyfin.example.com
|
|
||||||
# -- Rules for routing traffic
|
|
||||||
rules:
|
|
||||||
- matches:
|
|
||||||
- path:
|
|
||||||
type: PathPrefix
|
|
||||||
value: /
|
|
||||||
|
|
||||||
# -- Resource requests and limits for the Jellyfin container.
|
|
||||||
resources: {}
|
|
||||||
# limits:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
# requests:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
|
|
||||||
# -- 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.
|
|
||||||
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: {}
|
|
||||||
|
|
||||||
# -- Tolerations for pod scheduling.
|
|
||||||
tolerations: []
|
|
||||||
|
|
||||||
# -- Affinity rules for pod scheduling.
|
|
||||||
affinity: {}
|
|
||||||
|
|
||||||
# -- Privileged pod settings for advanced use cases
|
|
||||||
podPrivileges:
|
|
||||||
# -- Enable hostIPC namespace. Required for NVIDIA MPS (Multi-Process Service) GPU sharing. See: https://docs.nvidia.com/deploy/mps/index.html
|
|
||||||
hostIPC: false
|
|
||||||
# -- 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
|
|
||||||
|
|
||||||
jellyfin:
|
|
||||||
# -- Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html
|
|
||||||
enableDLNA: false
|
|
||||||
# -- 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"
|
|
||||||
|
|
||||||
persistence:
|
|
||||||
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: ''
|
|
||||||
|
|
||||||
# -- Configuration for metrics collection and monitoring
|
|
||||||
metrics:
|
|
||||||
# -- Enable or disable metrics collection
|
|
||||||
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: []
|
|
||||||
|
|
||||||
# -- DEPRECATED: Use extraInitContainers instead. Will be removed after 2030.
|
|
||||||
# @deprecated - This parameter is deprecated, use extraInitContainers instead
|
|
||||||
initContainers: []
|
|
||||||
|
|
||||||
# -- 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: []
|
|
||||||
|
|
||||||
# -- additional sidecar containers to run inside the pod.
|
|
||||||
extraContainers: []
|
|
||||||
|
|
||||||
# -- 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:
|
|
||||||
# -- 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
|
|
||||||
|
|
||||||
# -- Policy types to enforce. Both ingress and egress policies can be enabled.
|
|
||||||
# See: https://kubernetes.io/docs/concepts/services-networking/network-policies/#policy-types
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
- Egress
|
|
||||||
|
|
||||||
# -- Ingress rules configuration - controls which pods/namespaces can access Jellyfin.
|
|
||||||
ingress:
|
|
||||||
# -- 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.
|
|
||||||
allowExternal: true
|
|
||||||
|
|
||||||
# -- 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"
|
|
||||||
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
|
|
||||||
Whitespace-only changes.
+180
@@ -0,0 +1,180 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
entries:
|
||||||
|
jellyfin:
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.11.5
|
||||||
|
created: "2025-12-15T14:25:44.437291154Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: ec7aa59f4379b0ec088f53d764beff7d8453f8546df10d445ec285f96b96b15a
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.7.0/jellyfin-2.7.0.tgz
|
||||||
|
version: 2.7.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.11.4
|
||||||
|
created: "2025-12-02T03:55:35.632837588Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: d0c8b49b5ce5fa3ad9347b80d259ab50d825ddc83905540f847ecf2f263c9038
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.6.0/jellyfin-2.6.0.tgz
|
||||||
|
version: 2.6.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.11.2
|
||||||
|
created: "2025-11-03T03:47:22.070933121Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: 1b3c8ba8f0171904d520211eabd4675acf4817871eaa9f56651dd72e0104b0f5
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.5.0/jellyfin-2.5.0.tgz
|
||||||
|
version: 2.5.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.11.0
|
||||||
|
created: "2025-10-20T03:31:51.607585399Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: 6d1bc4a0819e4d7411cc2e451a98f9abfd631a7327c0d2eb0552f29cd452c4d6
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.4.0/jellyfin-2.4.0.tgz
|
||||||
|
version: 2.4.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.10.6
|
||||||
|
created: "2025-03-20T13:11:30.119149946Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: e99107cc3ec6a8bcad1e8c8861015870a94de325f0c292ba66291747688ebd6f
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.3.0/jellyfin-2.3.0.tgz
|
||||||
|
version: 2.3.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.10.6
|
||||||
|
created: "2025-03-19T13:42:34.879830235Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: 40ff82a31c4c1c90cffd873fda622038ed93b5f354c570ce40ff6df3471ca22f
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.2.0/jellyfin-2.2.0.tgz
|
||||||
|
version: 2.2.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.10.1
|
||||||
|
created: "2024-11-07T15:17:58.950640471Z"
|
||||||
|
description: A Helm chart for Jellyfin Media Server
|
||||||
|
digest: 1211a2e0f0a36d7c98ef0e26ebc741cbdf8fcc5461cf30352662759662b0230a
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-2.1.0/jellyfin-2.1.0.tgz
|
||||||
|
version: 2.1.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.10.1
|
||||||
|
created: "2024-11-05T14:40:55.821270971Z"
|
||||||
|
description: Jellyfin Media Server
|
||||||
|
digest: 1a5882a1a2bedecb97e6e333385d6d77adb4b452ef5ce060988b7e9381ac0de7
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-1.5.0/jellyfin-1.5.0.tgz
|
||||||
|
version: 1.5.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 1.4.0
|
||||||
|
created: "2024-11-04T21:02:54.104315531Z"
|
||||||
|
description: Jellyfin Media Server
|
||||||
|
digest: a48744022153a57d3396f65111d484fc139d39678829320ab3bfa76e4bef4724
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-1.4.0/jellyfin-1.4.0.tgz
|
||||||
|
version: 1.4.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.9.11
|
||||||
|
created: "2024-09-12T19:47:26.839480455Z"
|
||||||
|
description: Jellyfin Media Server
|
||||||
|
digest: 4a862deb0b175fc2dc588ac16558c7702ff51e7b26b1418227853274621a8154
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-1.3.0/jellyfin-1.3.0.tgz
|
||||||
|
version: 1.3.0
|
||||||
|
- apiVersion: v2
|
||||||
|
appVersion: 10.9.11
|
||||||
|
created: "2024-09-10T14:07:12.583254226Z"
|
||||||
|
description: Jellyfin Media Server
|
||||||
|
digest: 4986cb2280709582b6fdb0a7735eb4e91a2343f9bd9968a13a804f7b2ebbfd1e
|
||||||
|
home: https://jellyfin.org/
|
||||||
|
icon: https://jellyfin.org/images/logo.svg
|
||||||
|
keywords:
|
||||||
|
- jellyfin
|
||||||
|
- media
|
||||||
|
- self-hosted
|
||||||
|
name: jellyfin
|
||||||
|
type: application
|
||||||
|
urls:
|
||||||
|
- https://github.com/jellyfin/jellyfin-helm/releases/download/jellyfin-1.2.0/jellyfin-1.2.0.tgz
|
||||||
|
version: 1.2.0
|
||||||
|
generated: "2025-12-15T14:25:44.437338062Z"
|
||||||
Reference in new issue
Block a user