├── .github ├── cr.yaml ├── renovate.json └── workflows │ ├── app_release.yaml │ ├── docs_update.yaml │ └── release.yaml ├── .gitignore ├── LICENSE ├── README.md └── charts └── jellyfin ├── .helmignore ├── Chart.yaml ├── MIGRATION.md ├── README.md ├── README.md.gotmpl ├── templates ├── _helpers.tpl ├── deployment.yaml ├── ingress.yaml ├── persistentVolumeClaim.yaml ├── service.yaml ├── serviceMonitor.yaml └── serviceaccount.yaml └── values.yaml /.github/cr.yaml: -------------------------------------------------------------------------------- 1 | owner: jellyfin 2 | release-name-template: "{{ .Name }}-{{ .Version }}" -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>jellyfin/.github//renovate-presets/default"], 4 | "customManagers": [ 5 | { 6 | "customType": "regex", 7 | "fileMatch": ["charts/jellyfin/Chart.yaml"], 8 | "matchStrings": ["appVersion: (?.*?)\\n"], 9 | "datasourceTemplate": "docker", 10 | "depNameTemplate": "jellyfin/jellyfin" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/app_release.yaml: -------------------------------------------------------------------------------- 1 | name: Bump Helm Chart Version 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | inputs: 9 | jellyfin_version: 10 | description: 'Application version to set in Chart.yaml' 11 | required: true 12 | default: '1.0.0' 13 | 14 | jobs: 15 | bump-version: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 21 | with: 22 | persist-credentials: false 23 | 24 | - name: Set up Python 25 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 26 | with: 27 | python-version: 3.x 28 | 29 | - name: Bump chart version and set appVersion 30 | id: bump_version 31 | run: | 32 | # Read the current version from the Chart.yaml 33 | current_version=$(grep '^version:' charts/jellyfin/Chart.yaml | awk '{print $2}') 34 | echo "Current version: $current_version" 35 | 36 | # Split the version by dot and increment the minor version 37 | major=$(echo "$current_version" | cut -d '.' -f 1) 38 | minor=$(echo "$current_version" | cut -d '.' -f 2) 39 | patch=$(echo "$current_version" | cut -d '.' -f 3) 40 | new_version="$major.$((minor+1)).0" 41 | 42 | echo "New chart version: $new_version" 43 | 44 | # Get the app version passed as an input 45 | jellyfin_version="${{ github.event.inputs.jellyfin_version }}" 46 | echo "Setting appVersion to: $jellyfin_version" 47 | 48 | # Update the Chart.yaml with the new version and appVersion 49 | sed -i "s/^version:.*/version: $new_version/" charts/jellyfin/Chart.yaml 50 | sed -i "s/^appVersion:.*/appVersion: $jellyfin_version/" charts/jellyfin/Chart.yaml 51 | 52 | # Output the new chart version for further use 53 | echo "new_version=$new_version" >> $GITHUB_OUTPUT 54 | 55 | - name: Commit changes 56 | run: | 57 | git config --global user.name "github-actions[bot]" 58 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 59 | git add charts/jellyfin/Chart.yaml 60 | git commit -m "chore(jellyfin): Bump chart version to ${{ steps.bump_version.outputs.new_version }} and set appVersion to ${{ github.event.inputs.jellyfin_version }}" 61 | 62 | - name: Push changes 63 | uses: ad-m/github-push-action@master 64 | with: 65 | github_token: ${{ secrets.JF_BOT_TOKEN }} 66 | 67 | - name: Create Git tag 68 | id: create_tag 69 | run: | 70 | new_version="${{ steps.bump_version.outputs.new_version }}" 71 | git tag "$new_version" 72 | echo "Tag created: $new_version" 73 | 74 | - name: Push changes 75 | uses: ad-m/github-push-action@master 76 | with: 77 | github_token: ${{ secrets.JF_BOT_TOKEN }} 78 | tags: true 79 | -------------------------------------------------------------------------------- /.github/workflows/docs_update.yaml: -------------------------------------------------------------------------------- 1 | name: Docs Update 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | permissions: 9 | contents: write 10 | packages: write 11 | 12 | jobs: 13 | generate-docs: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Helm Docs GitHub Action 22 | uses: losisin/helm-docs-github-action@7b7955b018c87e10abf75fec0e8fe459556aec68 # v1.5.1 23 | with: 24 | git-push: true 25 | git-commit-message: "docs(charts): :memo: write updated reademe" 26 | 27 | - name: Push changes 28 | run: git push -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | permissions: 9 | contents: write 10 | packages: write 11 | 12 | jobs: 13 | release: 14 | # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions 15 | # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token 16 | permissions: 17 | contents: write 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Configure Git 26 | run: | 27 | git config --global user.name "jellyfin-bot" 28 | git config --global user.email "team@jellyfin.org" 29 | 30 | - name: Install Helm 31 | uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4 32 | env: 33 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 34 | 35 | - name: Run chart-releaser 36 | uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0 37 | env: 38 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 39 | with: 40 | config: .github/cr.yaml 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {{description}} 294 | Copyright (C) {{year}} {{fullname}} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jellyfin Helm Charts Repository 2 | 3 | This repository contains Helm charts for the jellyfin project. 4 | 5 | ## Repository Structure 6 | 7 | Each Helm chart is stored in its own directory. Each chart follows the standard Helm chart structure: 8 | 9 | ```plaintext 10 | hellyfin-helm/ 11 | ├── jellyfin/ 12 | │ ├── Chart.yaml 13 | │ ├── values.yaml 14 | │ ├── templates/ 15 | │ └── ... 16 | ├── chart2/ 17 | │ ├── Chart.yaml 18 | │ ├── values.yaml 19 | │ ├── templates/ 20 | │ └── ... 21 | └── ... 22 | ``` 23 | 24 | - `Chart.yaml`: Contains metadata about the chart (name, version, app version, etc.). 25 | - `values.yaml`: Default configuration values for the chart. 26 | - `templates/`: The Kubernetes resource templates (YAML files) that Helm uses to deploy the chart. 27 | 28 | ## How to Use the Charts 29 | 30 | ### 1. Add this Repository 31 | 32 | To use the charts in this repository, first add the repository to Helm: 33 | 34 | ```bash 35 | helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm 36 | helm repo update 37 | ``` 38 | 39 | ### 2. Install a Chart 40 | 41 | To install a chart from this repository, use the following command: 42 | 43 | ```bash 44 | helm install jellyfin/ 45 | ``` 46 | 47 | ### 3. Customize Installation 48 | 49 | You can customize the installation by passing in custom values via the `--set` flag or by using a `values.yaml` file: 50 | 51 | ```bash 52 | helm install jellyfin/ --set key=value 53 | ``` 54 | 55 | or 56 | 57 | ```bash 58 | helm install jellyfin/ -f custom-values.yaml 59 | ``` 60 | 61 | ## Contributing 62 | 63 | Feel free to contribute to this repository by: 64 | 65 | - Submitting new charts. 66 | - Fixing bugs or issues. 67 | - Improving documentation. 68 | 69 | To contribute, fork this repository, create a new branch, and submit a pull request with your changes. 70 | 71 | ## License 72 | 73 | This repository is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. 74 | -------------------------------------------------------------------------------- /charts/jellyfin/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/jellyfin/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: jellyfin 3 | description: A Helm chart for Jellyfin Media Server 4 | type: application 5 | home: https://jellyfin.org/ 6 | icon: https://jellyfin.org/images/logo.svg 7 | keywords: 8 | - jellyfin 9 | - media 10 | - self-hosted 11 | version: 2.3.0 12 | appVersion: 10.10.7 13 | -------------------------------------------------------------------------------- /charts/jellyfin/MIGRATION.md: -------------------------------------------------------------------------------- 1 | # Migration Guide 2 | 3 | ## v1.x to v2.x 4 | 5 | ### General 6 | 7 | 1. The `enableDLNA` key has been moved from the top level to the `jellyfin` subkey. 8 | 2. Some renames have occurred to align with the standard: 9 | ```yaml 10 | extraPodLabels -> podLabels 11 | extraPodAnnotations -> podAnnotations 12 | ``` 13 | 3. The `extraEnvVars` key has been moved and renamed to `jellyfin.env`. 14 | 4. `extraVolumes` has been moved to `volumes`, and `extraVolumeMounts` has been moved to `volumeMounts`. 15 | 5. The `extraExistingClaimMounts` key has been removed, as it can now be represented with `volumes` and `volumeMounts`. 16 | 17 | ### Service 18 | 19 | 1. The `name` field has been renamed to `portName` for consistency. 20 | 2. The following fields have been added: 21 | ```yaml 22 | # -- Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ 23 | ipFamilyPolicy: "" 24 | # -- Supported IP families (IPv4, IPv6). 25 | ipFamilies: [] 26 | # -- Class of the LoadBalancer. 27 | loadBalancerClass: "" 28 | # -- External traffic policy (Cluster or Local). 29 | # externalTrafficPolicy: Cluster 30 | ``` 31 | 32 | ### Ingress 33 | 34 | 1. The `className` field has been added for ingress class, as annotations are deprecated. 35 | 2. The `path` field has been moved under the `hosts` key to better represent the actual CRD, providing more fine-grained control. 36 | 3. The `labels` field has been added for additional labels. 37 | 38 | ### Persistence 39 | 40 | PVC creation is now enabled by default to prevent data loss when the chart is used without a specific configuration. 41 | 42 | ### Probes 43 | 44 | 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. -------------------------------------------------------------------------------- /charts/jellyfin/README.md: -------------------------------------------------------------------------------- 1 | # jellyfin 2 | 3 | ![Version: 2.3.0](https://img.shields.io/badge/Version-2.3.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 10.10.7](https://img.shields.io/badge/AppVersion-10.10.7-informational?style=flat-square) 4 | 5 | A Helm chart for Jellyfin Media Server 6 | 7 | **Homepage:** 8 | 9 | ## Steps to Use a Helm Chart 10 | 11 | ### 1. Add a Helm Repository 12 | 13 | Helm repositories contain collections of charts. You can add an existing repository using the following command: 14 | 15 | ```bash 16 | helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm 17 | ``` 18 | 19 | ### 2. Install the Helm Chart 20 | 21 | To install a chart, use the following command: 22 | 23 | ```bash 24 | helm install my-jellyfin jellyfin/jellyfin 25 | ``` 26 | 27 | ### 3. View the Installation 28 | 29 | You can check the status of the release using: 30 | 31 | ```bash 32 | helm status my-jellyfin 33 | ``` 34 | 35 | ## Customizing the Chart 36 | 37 | Helm charts come with default values, but you can customize them by using the --set flag or by providing a custom values.yaml file. 38 | 39 | ### 1. Using --set to Override Values 40 | ```bash 41 | helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2 42 | ``` 43 | 44 | ### 2. Using a values.yaml File 45 | You can create a custom values.yaml file and pass it to the install command: 46 | 47 | ```bash 48 | helm install my-jellyfin jellyfin/jellyfin -f values.yaml 49 | ``` 50 | 51 | ## Values 52 | 53 | | Key | Type | Default | Description | 54 | |-----|------|---------|-------------| 55 | | affinity | object | `{}` | Affinity rules for pod scheduling. | 56 | | deploymentAnnotations | object | `{}` | Annotations to add to the deployment. | 57 | | deploymentStrategy | object | `{"type":"RollingUpdate"}` | Deployment strategy configuration. See `kubectl explain deployment.spec.strategy`. | 58 | | extraContainers | list | `[]` | additional sidecar containers to run inside the pod. | 59 | | extraInitContainers | list | `[]` | additional init containers to run inside the pod. | 60 | | fullnameOverride | string | `""` | Override the default full name of the chart. | 61 | | image.pullPolicy | string | `"IfNotPresent"` | Image pull policy (Always, IfNotPresent, or Never). | 62 | | image.repository | string | `"docker.io/jellyfin/jellyfin"` | Container image repository for Jellyfin. | 63 | | image.tag | string | `""` | Jellyfin container image tag. Leave empty to automatically use the Chart's app version. | 64 | | imagePullSecrets | list | `[]` | Image pull secrets to authenticate with private repositories. See: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ | 65 | | 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/ | 66 | | jellyfin.args | list | `[]` | Additional arguments for the entrypoint command. | 67 | | jellyfin.command | list | `[]` | Custom command to use as container entrypoint. | 68 | | jellyfin.enableDLNA | bool | `false` | Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html | 69 | | jellyfin.env | list | `[]` | Additional environment variables for the container. | 70 | | livenessProbe | object | `{"initialDelaySeconds":10,"tcpSocket":{"port":"http"}}` | Configure liveness probe for Jellyfin. | 71 | | 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 | 72 | | metrics.enabled | bool | `false` | Enable or disable metrics collection | 73 | | 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 | 74 | | metrics.serviceMonitor.enabled | bool | `false` | Enable or disable the creation of a ServiceMonitor resource | 75 | | metrics.serviceMonitor.interval | string | `"30s"` | Interval at which metrics should be scraped | 76 | | metrics.serviceMonitor.labels | object | `{}` | Labels to add to the ServiceMonitor resource | 77 | | metrics.serviceMonitor.metricRelabelings | list | `[]` | Relabeling rules for the metrics before ingestion | 78 | | metrics.serviceMonitor.namespace | string | `""` | Namespace where the ServiceMonitor resource should be created. Defaults to Release.Namespace | 79 | | metrics.serviceMonitor.path | string | `"/metrics"` | Path to scrape for metrics | 80 | | metrics.serviceMonitor.port | int | `8096` | Port to scrape for metrics | 81 | | metrics.serviceMonitor.relabelings | list | `[]` | Relabeling rules for the scraped metrics | 82 | | metrics.serviceMonitor.scheme | string | `"http"` | Scheme to use for scraping metrics (http or https) | 83 | | metrics.serviceMonitor.scrapeTimeout | string | `"30s"` | Timeout for scraping metrics | 84 | | metrics.serviceMonitor.targetLabels | list | `[]` | Target labels to add to the scraped metrics | 85 | | metrics.serviceMonitor.tlsConfig | object | `{}` | TLS configuration for scraping metrics | 86 | | nameOverride | string | `""` | Override the default name of the chart. | 87 | | nodeSelector | object | `{}` | Node selector for pod scheduling. | 88 | | persistence.config.accessMode | string | `"ReadWriteOnce"` | | 89 | | persistence.config.annotations | object | `{}` | Custom annotations to be added to the PVC | 90 | | persistence.config.enabled | bool | `true` | set to false to use emptyDir | 91 | | persistence.config.size | string | `"5Gi"` | | 92 | | persistence.config.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. | 93 | | persistence.media.accessMode | string | `"ReadWriteOnce"` | PVC specific settings, only used if type is 'pvc'. | 94 | | persistence.media.annotations | object | `{}` | Custom annotations to be added to the PVC | 95 | | persistence.media.enabled | bool | `true` | set to false to use emptyDir | 96 | | persistence.media.hostPath | string | `""` | Path on the host node for media storage, only used if type is 'hostPath'. | 97 | | persistence.media.size | string | `"25Gi"` | | 98 | | persistence.media.storageClass | string | `""` | If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. | 99 | | 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. | 100 | | podAnnotations | object | `{}` | Annotations to add to the pod. | 101 | | podLabels | object | `{}` | Additional labels to add to the pod. | 102 | | podSecurityContext | object | `{}` | Security context for the pod. | 103 | | priorityClassName | string | `""` | Define a priorityClassName for the pod. | 104 | | readinessProbe | object | `{"initialDelaySeconds":10,"tcpSocket":{"port":"http"}}` | Configure readiness probe for Jellyfin. | 105 | | replicaCount | int | `1` | Number of Jellyfin replicas to start. Should be left at 1. | 106 | | resources | object | `{}` | Resource requests and limits for the Jellyfin container. | 107 | | runtimeClassName | string | `""` | Define a custom runtimeClassName for the pod. | 108 | | securityContext | object | `{}` | Security context for the container. | 109 | | service.annotations | object | `{}` | Annotations for the service. | 110 | | service.ipFamilies | list | `[]` | Supported IP families (IPv4, IPv6). | 111 | | service.ipFamilyPolicy | string | `""` | Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | 112 | | service.labels | object | `{}` | Labels for the service. | 113 | | service.loadBalancerClass | string | `""` | Class of the LoadBalancer. | 114 | | service.loadBalancerIP | string | `""` | Specific IP address for the LoadBalancer. | 115 | | service.loadBalancerSourceRanges | list | `[]` | Source ranges allowed to access the LoadBalancer. | 116 | | service.port | int | `8096` | Port for the Jellyfin service. | 117 | | service.portName | string | `"service"` | Name of the port in the service. | 118 | | service.type | string | `"ClusterIP"` | Service type (ClusterIP, NodePort, or LoadBalancer). | 119 | | serviceAccount | object | `{"annotations":{},"automount":true,"create":true,"name":""}` | Service account configuration. See: https://kubernetes.io/docs/concepts/security/service-accounts/ | 120 | | serviceAccount.annotations | object | `{}` | Annotations for the service account. | 121 | | serviceAccount.automount | bool | `true` | Automatically mount API credentials for the service account. | 122 | | serviceAccount.create | bool | `true` | Specifies whether to create a service account. | 123 | | serviceAccount.name | string | `""` | Custom name for the service account. If left empty, the name will be autogenerated. | 124 | | tolerations | list | `[]` | Tolerations for pod scheduling. | 125 | | volumeMounts | list | `[]` | Additional volume mounts for the Jellyfin container. | 126 | | volumes | list | `[]` | Additional volumes to mount in the Jellyfin pod. | 127 | 128 | ---------------------------------------------- 129 | Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) 130 | 131 | ## Hardware acceleration 132 | 133 | Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin. 134 | Adding the following Helm values should make it enable you to use hardware acceleration features. 135 | Some settings may need to be tweaked depending on the type of device (Intel/AMD/NVIDIA/...) and your container runtime. 136 | 137 | Please refer to the Jellyfin upstream documentation for more information about hardware acceleration: 138 | 139 | ```yaml 140 | securityContext: 141 | capabilities: 142 | add: 143 | - "SYS_ADMIN" 144 | drop: 145 | - "ALL" 146 | privileged: false 147 | 148 | extraVolumes: 149 | - name: hwa 150 | hostPath: 151 | path: /dev/dri 152 | 153 | extraVolumeMounts: 154 | - name: hwa 155 | mountPath: /dev/dri 156 | ``` 157 | -------------------------------------------------------------------------------- /charts/jellyfin/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | 4 | {{ template "chart.badgesSection" . }} 5 | 6 | {{ template "chart.description" . }} 7 | 8 | {{ template "chart.homepageLine" . }} 9 | 10 | ## Steps to Use a Helm Chart 11 | 12 | ### 1. Add a Helm Repository 13 | 14 | Helm repositories contain collections of charts. You can add an existing repository using the following command: 15 | 16 | ```bash 17 | helm repo add jellyfin https://jellyfin.github.io/jellyfin-helm 18 | ``` 19 | 20 | ### 2. Install the Helm Chart 21 | 22 | To install a chart, use the following command: 23 | 24 | ```bash 25 | helm install my-jellyfin jellyfin/jellyfin 26 | ``` 27 | 28 | ### 3. View the Installation 29 | 30 | You can check the status of the release using: 31 | 32 | ```bash 33 | helm status my-jellyfin 34 | ``` 35 | 36 | ## Customizing the Chart 37 | 38 | Helm charts come with default values, but you can customize them by using the --set flag or by providing a custom values.yaml file. 39 | 40 | ### 1. Using --set to Override Values 41 | ```bash 42 | helm install my-jellyfin jellyfin/jellyfin --set key1=value1,key2=value2 43 | ``` 44 | 45 | ### 2. Using a values.yaml File 46 | You can create a custom values.yaml file and pass it to the install command: 47 | 48 | ```bash 49 | helm install my-jellyfin jellyfin/jellyfin -f values.yaml 50 | ``` 51 | 52 | {{ template "chart.maintainersSection" . }} 53 | 54 | {{ template "chart.sourcesSection" . }} 55 | 56 | {{ template "chart.requirementsSection" . }} 57 | 58 | {{ template "chart.valuesSection" . }} 59 | 60 | {{ template "helm-docs.versionFooter" . }} 61 | 62 | ## Hardware acceleration 63 | 64 | Out of the box the pod does not have the necessary permissions to enable hardware acceleration (HWA) in Jellyfin. 65 | Adding the following Helm values should make it enable you to use hardware acceleration features. 66 | Some settings may need to be tweaked depending on the type of device (Intel/AMD/NVIDIA/...) and your container runtime. 67 | 68 | Please refer to the Jellyfin upstream documentation for more information about hardware acceleration: 69 | 70 | ```yaml 71 | securityContext: 72 | capabilities: 73 | add: 74 | - "SYS_ADMIN" 75 | drop: 76 | - "ALL" 77 | privileged: false 78 | 79 | extraVolumes: 80 | - name: hwa 81 | hostPath: 82 | path: /dev/dri 83 | 84 | extraVolumeMounts: 85 | - name: hwa 86 | mountPath: /dev/dri 87 | ``` 88 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Fail if command and metrics are set 3 | */}} 4 | {{- if and .Values.image.command .Values.metrics.enabled }} 5 | {{- fail "Can't use custom command and metrics in combination. They are exclusive features" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Expand the name of the chart. 10 | */}} 11 | {{- define "jellyfin.name" -}} 12 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 13 | {{- end }} 14 | 15 | {{/* 16 | Create a default fully qualified app name. 17 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 18 | If release name contains chart name it will be used as a full name. 19 | */}} 20 | {{- define "jellyfin.fullname" -}} 21 | {{- if .Values.fullnameOverride }} 22 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 23 | {{- else }} 24 | {{- $name := default .Chart.Name .Values.nameOverride }} 25 | {{- if contains $name .Release.Name }} 26 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 27 | {{- else }} 28 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 29 | {{- end }} 30 | {{- end }} 31 | {{- end }} 32 | 33 | {{/* 34 | Create chart name and version as used by the chart label. 35 | */}} 36 | {{- define "jellyfin.chart" -}} 37 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 38 | {{- end }} 39 | 40 | {{/* 41 | Common labels 42 | */}} 43 | {{- define "jellyfin.labels" -}} 44 | helm.sh/chart: {{ include "jellyfin.chart" . }} 45 | {{ include "jellyfin.selectorLabels" . }} 46 | {{- if .Chart.AppVersion }} 47 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 48 | {{- end }} 49 | app.kubernetes.io/managed-by: {{ .Release.Service }} 50 | {{- end }} 51 | 52 | {{/* 53 | Selector labels 54 | */}} 55 | {{- define "jellyfin.selectorLabels" -}} 56 | app.kubernetes.io/name: {{ include "jellyfin.name" . }} 57 | app.kubernetes.io/instance: {{ .Release.Name }} 58 | {{- end }} 59 | 60 | {{/* 61 | Create the name of the service account to use 62 | */}} 63 | {{- define "jellyfin.serviceAccountName" -}} 64 | {{- if .Values.serviceAccount.create }} 65 | {{- default (include "jellyfin.fullname" .) .Values.serviceAccount.name }} 66 | {{- else }} 67 | {{- default "default" .Values.serviceAccount.name }} 68 | {{- end }} 69 | {{- end }} 70 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "jellyfin.fullname" . }} 5 | {{- with .Values.deploymentAnnotations }} 6 | annotations: 7 | {{- toYaml . | nindent 4 }} 8 | {{- end }} 9 | labels: 10 | {{- include "jellyfin.labels" . | nindent 4 }} 11 | spec: 12 | {{- with .Values.deploymentStrategy }} 13 | strategy: 14 | {{- toYaml . | trim | nindent 4 }} 15 | {{- end }} 16 | replicas: {{ .Values.replicaCount }} 17 | selector: 18 | matchLabels: 19 | {{- include "jellyfin.selectorLabels" . | nindent 6 }} 20 | template: 21 | metadata: 22 | {{- with .Values.podAnnotations }} 23 | annotations: 24 | {{- toYaml . | nindent 8 }} 25 | {{- end }} 26 | labels: 27 | {{- include "jellyfin.labels" . | nindent 8 }} 28 | {{- with .Values.podLabels }} 29 | {{- toYaml . | nindent 8 }} 30 | {{- end }} 31 | spec: 32 | {{- with .Values.imagePullSecrets }} 33 | imagePullSecrets: 34 | {{- toYaml . | nindent 8 }} 35 | {{- end }} 36 | serviceAccountName: {{ include "jellyfin.serviceAccountName" . }} 37 | securityContext: 38 | {{- toYaml .Values.podSecurityContext | nindent 8 }} 39 | {{- if .Values.jellyfin.enableDLNA }} 40 | hostNetwork: true 41 | {{- end }} 42 | containers: 43 | - name: {{ .Chart.Name }} 44 | securityContext: 45 | {{- toYaml .Values.securityContext | nindent 12 }} 46 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 47 | imagePullPolicy: {{ .Values.image.pullPolicy }} 48 | {{- with .Values.jellyfin.command }} 49 | command: 50 | {{- toYaml . | nindent 12 }} 51 | {{- end }} 52 | {{- with .Values.jellyfin.args }} 53 | args: 54 | {{- toYaml . | nindent 12 }} 55 | {{- end }} 56 | {{- with .Values.jellyfin.env }} 57 | env: 58 | {{- toYaml . | nindent 12 }} 59 | {{- end }} 60 | {{- if .Values.metrics.enabled }} 61 | lifecycle: 62 | postStart: 63 | exec: 64 | command: 65 | - /bin/sh 66 | - -c 67 | - | 68 | echo "Waiting for system.xml to enable metrics..." 69 | timeout=300 # 5 minutes timeout 70 | interval=5 # Check every 5 seconds 71 | elapsed=0 72 | while [ ! -f /config/config/system.xml ]; do 73 | if [ $elapsed -ge $timeout ]; then 74 | echo "ERROR: Timed out waiting for /config/config/system.xml" >&2 75 | exit 1 76 | fi 77 | sleep $interval 78 | elapsed=$((elapsed + interval)) 79 | done 80 | echo "Found /config/config/system.xml, enabling metrics..." 81 | # Check if metrics are already enabled before running sed 82 | if ! grep -q 'true' /config/config/system.xml; then 83 | sed 's,false,true,' -i /config/config/system.xml 84 | if [ $? -eq 0 ]; then 85 | echo "Metrics enabled successfully." 86 | else 87 | echo "ERROR: Failed to enable metrics in /config/config/system.xml" >&2 88 | exit 1 89 | fi 90 | else 91 | echo "Metrics already enabled." 92 | fi 93 | exit 0 94 | {{- end }} 95 | ports: 96 | - name: http 97 | containerPort: 8096 98 | protocol: TCP 99 | {{- if .Values.jellyfin.enableDLNA }} 100 | - name: dlna 101 | containerPort: 1900 102 | hostPort: 1900 103 | protocol: UDP 104 | {{- end }} 105 | livenessProbe: 106 | {{- toYaml .Values.livenessProbe | nindent 12 }} 107 | readinessProbe: 108 | {{- toYaml .Values.readinessProbe | nindent 12 }} 109 | resources: 110 | {{- toYaml .Values.resources | nindent 12 }} 111 | volumeMounts: 112 | - mountPath: /config 113 | name: config 114 | - mountPath: /media 115 | name: media 116 | {{- with .Values.volumeMounts }} 117 | {{- toYaml . | nindent 12 }} 118 | {{- end }} 119 | {{- with .Values.extraContainers }} 120 | {{- toYaml . | nindent 8 }} 121 | {{- end }} 122 | {{- with .Values.initContainers }} 123 | initContainers: 124 | {{- toYaml . | nindent 6 }} 125 | {{- end }} 126 | volumes: 127 | - name: config 128 | {{- if .Values.persistence.config.enabled }} 129 | persistentVolumeClaim: 130 | claimName: {{ if .Values.persistence.config.existingClaim }}{{ .Values.persistence.config.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-config{{- end }} 131 | {{- else }} 132 | emptyDir: {} 133 | {{- end }} 134 | - name: media 135 | {{- if .Values.persistence.media.enabled }} 136 | {{- if eq .Values.persistence.media.type "pvc" }} 137 | persistentVolumeClaim: 138 | claimName: {{ if .Values.persistence.media.existingClaim }}{{ .Values.persistence.media.existingClaim }}{{- else }}{{ template "jellyfin.fullname" . }}-media{{- end }} 139 | {{- else if eq .Values.persistence.media.type "hostPath" }} 140 | hostPath: 141 | path: {{ .Values.persistence.media.hostPath }} 142 | type: Directory 143 | {{- else }} 144 | emptyDir: {} 145 | {{- end }} 146 | {{- else }} 147 | emptyDir: {} 148 | {{- end }} 149 | {{- with .Values.volumes }} 150 | {{- toYaml . | nindent 8 }} 151 | {{- end }} 152 | {{- with .Values.nodeSelector }} 153 | nodeSelector: 154 | {{- toYaml . | nindent 8 }} 155 | {{- end }} 156 | {{- with .Values.affinity }} 157 | affinity: 158 | {{- toYaml . | nindent 8 }} 159 | {{- end }} 160 | {{- with .Values.tolerations }} 161 | tolerations: 162 | {{- toYaml . | nindent 8 }} 163 | {{- end }} 164 | {{- with .Values.runtimeClassName }} 165 | runtimeClassName: {{ . | quote }} 166 | {{- end }} 167 | {{- with .Values.priorityClassName }} 168 | priorityClassName: {{ . | quote }} 169 | {{- end }} 170 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled }} 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | name: {{ include "jellyfin.fullname" . }} 6 | labels: 7 | {{- include "jellyfin.labels" . | nindent 4 }} 8 | {{- with .Values.ingress.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | {{- with .Values.ingress.className }} 14 | ingressClassName: {{ . }} 15 | {{- end }} 16 | {{- if .Values.ingress.tls }} 17 | tls: 18 | {{- range .Values.ingress.tls }} 19 | - hosts: 20 | {{- range .hosts }} 21 | - {{ . | quote }} 22 | {{- end }} 23 | secretName: {{ .secretName }} 24 | {{- end }} 25 | {{- end }} 26 | rules: 27 | {{- range .Values.ingress.hosts }} 28 | - host: {{ .host | quote }} 29 | http: 30 | paths: 31 | {{- range .paths }} 32 | - path: {{ .path }} 33 | {{- with .pathType }} 34 | pathType: {{ . }} 35 | {{- end }} 36 | backend: 37 | service: 38 | name: {{ include "jellyfin.fullname" $ }} 39 | port: 40 | number: {{ $.Values.service.port }} 41 | {{- end }} 42 | {{- end }} 43 | {{- end }} 44 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/persistentVolumeClaim.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.persistence.config.enabled (not .Values.persistence.config.existingClaim) }} 2 | --- 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | name: {{ include "jellyfin.fullname" . }}-config 7 | labels: 8 | {{- include "jellyfin.labels" . | nindent 4 }} 9 | {{- with .Values.persistence.config.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | spec: 14 | accessModes: 15 | - {{ .Values.persistence.config.accessMode | quote }} 16 | resources: 17 | requests: 18 | storage: {{ .Values.persistence.config.size | quote }} 19 | {{- with .Values.persistence.config.storageClass }} 20 | storageClassName: {{ . | quote }} 21 | {{- end }} 22 | {{- end }} 23 | 24 | {{- if and .Values.persistence.media.enabled (eq .Values.persistence.media.type "pvc") (not .Values.persistence.media.existingClaim) }} 25 | --- 26 | apiVersion: v1 27 | kind: PersistentVolumeClaim 28 | metadata: 29 | name: {{ include "jellyfin.fullname" . }}-media 30 | labels: 31 | {{- include "jellyfin.labels" . | nindent 4 }} 32 | {{- with .Values.persistence.media.annotations }} 33 | annotations: 34 | {{- toYaml . | nindent 4 }} 35 | {{- end }} 36 | spec: 37 | accessModes: 38 | - {{ .Values.persistence.media.accessMode | quote }} 39 | resources: 40 | requests: 41 | storage: {{ .Values.persistence.media.size | quote }} 42 | {{- with .Values.persistence.media.storageClass }} 43 | storageClassName: {{ . | quote }} 44 | {{- end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "jellyfin.fullname" . }} 5 | labels: 6 | {{- include "jellyfin.labels" . | nindent 4 }} 7 | {{- with .Values.service.labels }} 8 | {{- toYaml . | nindent 4 }} 9 | {{- end }} 10 | {{- with .Values.service.annotations }} 11 | annotations: 12 | {{- toYaml . | nindent 4 }} 13 | {{- end }} 14 | spec: 15 | {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} 16 | type: ClusterIP 17 | {{- with .Values.service.clusterIP }} 18 | clusterIP: {{ . }} 19 | {{- end }} 20 | {{- else if eq .Values.service.type "LoadBalancer" }} 21 | type: LoadBalancer 22 | {{- with .Values.service.loadBalancerIP }} 23 | loadBalancerIP: {{ . }} 24 | {{- end }} 25 | {{- with .Values.service.loadBalancerClass }} 26 | loadBalancerClass: {{ . }} 27 | {{- end }} 28 | {{- with .Values.service.loadBalancerSourceRanges }} 29 | loadBalancerSourceRanges: 30 | {{- toYaml . | nindent 4 }} 31 | {{- end }} 32 | {{- else }} 33 | type: {{ .Values.service.type }} 34 | {{- end }} 35 | {{- if .Values.service.ipFamilyPolicy }} 36 | ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} 37 | {{- end }} 38 | {{- if .Values.service.ipFamilies }} 39 | ipFamilies: 40 | {{- toYaml .Values.service.ipFamilies | nindent 4 }} 41 | {{- end }} 42 | {{- with .Values.service.externalIPs }} 43 | externalIPs: 44 | {{- toYaml . | nindent 4 }} 45 | {{- end }} 46 | {{- with .Values.service.externalTrafficPolicy }} 47 | externalTrafficPolicy: {{ . }} 48 | {{- end }} 49 | ports: 50 | - name: {{ .Values.service.name | default "http" }} 51 | port: {{ .Values.service.port }} 52 | protocol: TCP 53 | targetPort: http 54 | {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} 55 | nodePort: {{ .Values.service.nodePort }} 56 | {{- end }} 57 | selector: 58 | {{- include "jellyfin.selectorLabels" . | nindent 4 }} 59 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/serviceMonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.metrics.serviceMonitor.enabled .Values.metrics.enabled }} 2 | --- 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | name: {{ include "jellyfin.fullname" . }} 7 | {{- if .Values.metrics.serviceMonitor.namespace }} 8 | namespace: {{ tpl .Values.metrics.serviceMonitor.namespace . }} 9 | {{- end }} 10 | labels: 11 | {{- include "jellyfin.labels" . | nindent 4 }} 12 | {{- with .Values.metrics.serviceMonitor.labels }} 13 | {{- tpl (toYaml . | nindent 4) $ }} 14 | {{- end }} 15 | spec: 16 | endpoints: 17 | - port: {{ .Values.service.name | default "http" }} 18 | {{- with .Values.metrics.serviceMonitor.interval }} 19 | interval: {{ . }} 20 | {{- end }} 21 | {{- with .Values.metrics.serviceMonitor.scrapeTimeout }} 22 | scrapeTimeout: {{ . }} 23 | {{- end }} 24 | honorLabels: true 25 | path: {{ .Values.metrics.serviceMonitor.path }} 26 | scheme: {{ .Values.metrics.serviceMonitor.scheme }} 27 | {{- with .Values.metrics.serviceMonitor.tlsConfig }} 28 | tlsConfig: 29 | {{- toYaml . | nindent 8 }} 30 | {{- end }} 31 | {{- with .Values.metrics.serviceMonitor.relabelings }} 32 | relabelings: 33 | {{- toYaml . | nindent 8 }} 34 | {{- end }} 35 | {{- with .Values.metrics.serviceMonitor.metricRelabelings }} 36 | metricRelabelings: 37 | {{- toYaml . | nindent 8 }} 38 | {{- end }} 39 | jobLabel: "{{ .Release.Name }}" 40 | selector: 41 | matchLabels: 42 | app.kubernetes.io/name: {{ include "jellyfin.name" . }} 43 | app.kubernetes.io/instance: {{ .Release.Name }} 44 | {{- with .Values.metrics.serviceMonitor.targetLabels }} 45 | targetLabels: 46 | {{- toYaml . | nindent 4 }} 47 | {{- end }} 48 | {{- end }} 49 | -------------------------------------------------------------------------------- /charts/jellyfin/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "jellyfin.serviceAccountName" . }} 6 | labels: 7 | {{- include "jellyfin.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | automountServiceAccountToken: {{ .Values.serviceAccount.automount }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /charts/jellyfin/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for Jellyfin. 2 | # This is a YAML-formatted file. 3 | 4 | # -- Number of Jellyfin replicas to start. Should be left at 1. 5 | replicaCount: 1 6 | 7 | # -- Image pull secrets to authenticate with private repositories. 8 | # See: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ 9 | imagePullSecrets: [] 10 | 11 | image: 12 | # -- Container image repository for Jellyfin. 13 | repository: docker.io/jellyfin/jellyfin 14 | # -- Jellyfin container image tag. Leave empty to automatically use the Chart's app version. 15 | tag: "" 16 | # -- Image pull policy (Always, IfNotPresent, or Never). 17 | pullPolicy: IfNotPresent 18 | 19 | # -- Override the default name of the chart. 20 | nameOverride: "" 21 | # -- Override the default full name of the chart. 22 | fullnameOverride: "" 23 | 24 | # -- Service account configuration. See: https://kubernetes.io/docs/concepts/security/service-accounts/ 25 | serviceAccount: 26 | # -- Specifies whether to create a service account. 27 | create: true 28 | # -- Automatically mount API credentials for the service account. 29 | automount: true 30 | # -- Annotations for the service account. 31 | annotations: {} 32 | # -- Custom name for the service account. If left empty, the name will be autogenerated. 33 | name: "" 34 | 35 | # -- Annotations to add to the pod. 36 | podAnnotations: {} 37 | # -- Additional labels to add to the pod. 38 | podLabels: {} 39 | 40 | # -- Security context for the pod. 41 | podSecurityContext: {} 42 | # fsGroup: 2000 43 | 44 | # -- Security context for the container. 45 | securityContext: {} 46 | # capabilities: 47 | # drop: 48 | # - ALL 49 | # readOnlyRootFilesystem: true 50 | # runAsNonRoot: true 51 | # runAsUser: 1000 52 | 53 | # -- Define a custom runtimeClassName for the pod. 54 | runtimeClassName: '' 55 | 56 | # -- Define a priorityClassName for the pod. 57 | priorityClassName: "" 58 | 59 | # -- Deployment strategy configuration. See `kubectl explain deployment.spec.strategy`. 60 | deploymentStrategy: 61 | type: RollingUpdate 62 | 63 | # -- Annotations to add to the deployment. 64 | deploymentAnnotations: {} 65 | 66 | service: 67 | # # -- Custom name for the service port 68 | # name: http 69 | # -- Service type (ClusterIP, NodePort, or LoadBalancer). 70 | type: ClusterIP 71 | # -- Configure dual-stack IP family policy. See: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ 72 | ipFamilyPolicy: "" 73 | # -- Supported IP families (IPv4, IPv6). 74 | ipFamilies: [] 75 | # -- Specific IP address for the LoadBalancer. 76 | loadBalancerIP: "" 77 | # -- Class of the LoadBalancer. 78 | loadBalancerClass: "" 79 | # -- Source ranges allowed to access the LoadBalancer. 80 | loadBalancerSourceRanges: [] 81 | # -- Port for the Jellyfin service. 82 | port: 8096 83 | # -- Name of the port in the service. 84 | portName: service 85 | # -- Annotations for the service. 86 | annotations: {} 87 | # -- Labels for the service. 88 | labels: {} 89 | # -- External traffic policy (Cluster or Local). 90 | # externalTrafficPolicy: Cluster 91 | # -- NodePort for the service (if applicable). 92 | # nodePort: 93 | 94 | # -- Ingress configuration. See: https://kubernetes.io/docs/concepts/services-networking/ingress/ 95 | ingress: 96 | enabled: false 97 | className: "" 98 | annotations: {} 99 | # kubernetes.io/ingress.class: nginx 100 | # kubernetes.io/tls-acme: "true" 101 | hosts: 102 | - host: chart-example.local 103 | paths: 104 | - path: / 105 | pathType: ImplementationSpecific 106 | tls: [] 107 | # - secretName: chart-example-tls 108 | # hosts: 109 | # - chart-example.local 110 | 111 | # -- Resource requests and limits for the Jellyfin container. 112 | resources: {} 113 | # limits: 114 | # cpu: 100m 115 | # memory: 128Mi 116 | # requests: 117 | # cpu: 100m 118 | # memory: 128Mi 119 | 120 | # -- Configure liveness probe for Jellyfin. 121 | livenessProbe: 122 | initialDelaySeconds: 10 123 | tcpSocket: 124 | port: http 125 | # successThreshold: 1 126 | # failureThreshold: 3 127 | # timeoutSeconds: 1 128 | # periodSeconds: 10 129 | 130 | # -- Configure readiness probe for Jellyfin. 131 | readinessProbe: 132 | initialDelaySeconds: 10 133 | tcpSocket: 134 | port: http 135 | # successThreshold: 1 136 | # failureThreshold: 3 137 | # timeoutSeconds: 1 138 | # periodSeconds: 10 139 | 140 | # -- Additional volumes to mount in the Jellyfin pod. 141 | volumes: [] 142 | # - name: foo 143 | # secret: 144 | # secretName: mysecret 145 | # optional: false 146 | 147 | # -- Additional volume mounts for the Jellyfin container. 148 | volumeMounts: [] 149 | # - name: foo 150 | # mountPath: "/etc/foo" 151 | # readOnly: true 152 | 153 | # -- Node selector for pod scheduling. 154 | nodeSelector: {} 155 | 156 | # -- Tolerations for pod scheduling. 157 | tolerations: [] 158 | 159 | # -- Affinity rules for pod scheduling. 160 | affinity: {} 161 | 162 | jellyfin: 163 | # -- Enable DLNA. Requires host network. See: https://jellyfin.org/docs/general/networking/dlna.html 164 | enableDLNA: false 165 | # -- Custom command to use as container entrypoint. 166 | command: [] 167 | # -- Additional arguments for the entrypoint command. 168 | args: [] 169 | # -- Additional environment variables for the container. 170 | env: [] 171 | 172 | persistence: 173 | config: 174 | # -- set to false to use emptyDir 175 | enabled: true 176 | accessMode: ReadWriteOnce 177 | size: 5Gi 178 | # -- Custom annotations to be added to the PVC 179 | annotations: {} 180 | # -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. 181 | storageClass: '' 182 | ## -- Use an existing PVC for this mount 183 | # existingClaim: '' 184 | media: 185 | # -- set to false to use emptyDir 186 | enabled: true 187 | # -- Type of volume for media storage (pvc, hostPath, emptyDir). If 'enabled' is false, 'emptyDir' is used regardless of this setting. 188 | type: pvc 189 | # -- Path on the host node for media storage, only used if type is 'hostPath'. 190 | hostPath: "" 191 | # -- PVC specific settings, only used if type is 'pvc'. 192 | accessMode: ReadWriteOnce 193 | size: 25Gi 194 | # -- Custom annotations to be added to the PVC 195 | annotations: {} 196 | # -- If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. 197 | storageClass: '' 198 | ## -- Use an existing PVC for this mount 199 | # existingClaim: '' 200 | 201 | # -- Configuration for metrics collection and monitoring 202 | metrics: 203 | # -- Enable or disable metrics collection 204 | enabled: false 205 | # -- Configuration for the Prometheus ServiceMonitor 206 | serviceMonitor: 207 | # -- Enable or disable the creation of a ServiceMonitor resource 208 | enabled: false 209 | # -- Namespace where the ServiceMonitor resource should be created. Defaults to Release.Namespace 210 | namespace: '' 211 | # -- Labels to add to the ServiceMonitor resource 212 | labels: {} 213 | # -- Interval at which metrics should be scraped 214 | interval: 30s 215 | # -- Timeout for scraping metrics 216 | scrapeTimeout: 30s 217 | # -- Path to scrape for metrics 218 | path: /metrics 219 | # -- Port to scrape for metrics 220 | port: 8096 221 | # -- Scheme to use for scraping metrics (http or https) 222 | scheme: http 223 | # -- TLS configuration for scraping metrics 224 | tlsConfig: {} 225 | # -- Relabeling rules for the scraped metrics 226 | relabelings: [] 227 | # -- Relabeling rules for the metrics before ingestion 228 | metricRelabelings: [] 229 | # -- Target labels to add to the scraped metrics 230 | targetLabels: [] 231 | 232 | # -- additional init containers to run inside the pod. 233 | extraInitContainers: [] 234 | 235 | # -- additional sidecar containers to run inside the pod. 236 | extraContainers: [] 237 | --------------------------------------------------------------------------------