aboutsummaryrefslogtreecommitdiffstats
path: root/roles/jellyfin
diff options
context:
space:
mode:
authorStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:23:43 -0500
committerStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:52:13 -0500
commit0261e875679f1bf63c8d689da7fc7e014597885d (patch)
tree3f19cd74a0c1070944f75437f30b098d6ef2ffcb /roles/jellyfin
downloadselfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.tar.gz
selfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.zip
initial commit
Diffstat (limited to 'roles/jellyfin')
-rw-r--r--roles/jellyfin/defaults/main.yml11
-rw-r--r--roles/jellyfin/handlers/main.yml4
-rw-r--r--roles/jellyfin/meta/main.yml10
-rw-r--r--roles/jellyfin/tasks/freeipa.yml67
-rw-r--r--roles/jellyfin/tasks/main.yml94
-rw-r--r--roles/jellyfin/templates/etc/jellyfin/network.xml.j236
-rw-r--r--roles/jellyfin/templates/etc/sysconfig/jellyfin.j222
-rw-r--r--roles/jellyfin/templates/etc/systemd/system/jellyfin.service.j251
-rw-r--r--roles/jellyfin/templates/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml.j223
-rw-r--r--roles/jellyfin/vars/main.yml34
10 files changed, 352 insertions, 0 deletions
diff --git a/roles/jellyfin/defaults/main.yml b/roles/jellyfin/defaults/main.yml
new file mode 100644
index 0000000..2c3fadb
--- /dev/null
+++ b/roles/jellyfin/defaults/main.yml
@@ -0,0 +1,11 @@
+jellyfin_version: 10.8.9
+jellyfin_port: 8096
+jellyfin_user: s-jellyfin
+
+jellyfin_sysaccount_username: jellyfin
+
+jellyfin_media_access_group: role-media-access
+jellyfin_access_group: role-media-access
+jellyfin_admin_group: role-media-admin
+
+jellyfin_ldap_server: '{{ freeipa_hosts[0] }}'
diff --git a/roles/jellyfin/handlers/main.yml b/roles/jellyfin/handlers/main.yml
new file mode 100644
index 0000000..d6dee75
--- /dev/null
+++ b/roles/jellyfin/handlers/main.yml
@@ -0,0 +1,4 @@
+- name: restart jellyfin
+ systemd:
+ name: jellyfin
+ state: restarted
diff --git a/roles/jellyfin/meta/main.yml b/roles/jellyfin/meta/main.yml
new file mode 100644
index 0000000..f93843f
--- /dev/null
+++ b/roles/jellyfin/meta/main.yml
@@ -0,0 +1,10 @@
+dependencies:
+ - role: yum
+ yum_repositories:
+ - epel
+ - rpmfusion-free
+ tags: yum
+
+ - role: freeipa_system_account
+ system_account_username: '{{ jellyfin_sysaccount_username }}'
+ system_account_password: '{{ jellyfin_sysaccount_password }}'
diff --git a/roles/jellyfin/tasks/freeipa.yml b/roles/jellyfin/tasks/freeipa.yml
new file mode 100644
index 0000000..06cfd25
--- /dev/null
+++ b/roles/jellyfin/tasks/freeipa.yml
@@ -0,0 +1,67 @@
+- name: create user
+ ipauser:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ jellyfin_user }}'
+ loginshell: /sbin/nologin
+ homedir: '{{ jellyfin_home }}'
+ givenname: Jellyfin
+ sn: Service Account
+ state: present
+ run_once: True
+
+- name: retrieve user keytab
+ include_role:
+ name: freeipa_keytab
+ vars:
+ keytab_principal: '{{ jellyfin_user }}'
+ keytab_path: '{{ jellyfin_keytab }}'
+ keytab_owner: '{{ jellyfin_user }}'
+
+- name: create media access group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ jellyfin_media_access_group }}'
+ nonposix: no
+ action: group
+ state: present
+ run_once: True
+
+- name: add user to media access group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ jellyfin_media_access_group }}'
+ user: '{{ jellyfin_user }}'
+ action: member
+ state: present
+ run_once: True
+
+- name: create access group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ jellyfin_access_group }}'
+ action: group
+ state: present
+ run_once: True
+
+- name: create admin group
+ ipagroup:
+ ipaadmin_principal: '{{ ipa_user }}'
+ ipaadmin_password: '{{ ipa_pass }}'
+ name: '{{ jellyfin_admin_group }}'
+ state: present
+ run_once: True
+
+- name: configure gssproxy for kerberized NFS
+ include_role:
+ name: gssproxy_client
+ vars:
+ gssproxy_name: jellyfin
+ gssproxy_section: service/jellyfin
+ gssproxy_keytab: /etc/krb5.keytab
+ gssproxy_client_keytab: '{{ jellyfin_keytab }}'
+ gssproxy_cred_usage: initiate
+ gssproxy_euid: '{{ jellyfin_user }}'
diff --git a/roles/jellyfin/tasks/main.yml b/roles/jellyfin/tasks/main.yml
new file mode 100644
index 0000000..0bb8b91
--- /dev/null
+++ b/roles/jellyfin/tasks/main.yml
@@ -0,0 +1,94 @@
+- name: install packages
+ dnf:
+ name: '{{ jellyfin_packages }}'
+ state: present
+
+- name: create installation directory
+ file:
+ path: '{{ jellyfin_install_dir }}'
+ state: directory
+
+- name: extract tarball
+ unarchive:
+ src: '{{ jellyfin_url }}'
+ remote_src: yes
+ dest: '{{ jellyfin_install_dir }}'
+ extra_opts:
+ - '--strip-components=2'
+ notify: restart jellyfin
+
+- name: generate systemd unit
+ template:
+ src: etc/systemd/system/jellyfin.service.j2
+ dest: /etc/systemd/system/jellyfin.service
+ notify: restart jellyfin
+ register: jellyfin_unit
+
+- name: reload systemd units
+ systemd:
+ daemon_reload: yes
+ when: jellyfin_unit.changed
+
+- name: generate sysconfig file
+ template:
+ src: etc/sysconfig/jellyfin.j2
+ dest: /etc/sysconfig/jellyfin
+ notify: restart jellyfin
+
+- name: create runtime directories
+ file:
+ path: '{{ item.path }}'
+ owner: '{{ jellyfin_user }}'
+ group: '{{ jellyfin_user }}'
+ mode: '{{ item.mode }}'
+ state: directory
+ loop:
+ - { path: '{{ jellyfin_home }}', mode: '0750' }
+ - { path: '{{ jellyfin_home }}/plugins', mode: '0750' }
+ - { path: '{{ jellyfin_home }}/plugins/configurations', mode: '0750' }
+ - { path: /var/cache/jellyfin, mode: '0750' }
+ - { path: /var/log/jellyfin, mode: '0755' }
+ - { path: '{{ jellyfin_conf_dir }}', mode: '0755' }
+
+- name: generate jellyfin network configuration
+ template:
+ src: '{{ jellyfin_conf_dir[1:] }}/network.xml.j2'
+ dest: '{{ jellyfin_conf_dir }}/network.xml'
+ owner: '{{ jellyfin_user }}'
+ group: '{{ jellyfin_user }}'
+ mode: 0644
+ notify: restart jellyfin
+
+- name: generate jellyfin LDAP configuration
+ template:
+ src: '{{ jellyfin_home[1:] }}/plugins/configurations/LDAP-Auth.xml.j2'
+ dest: '{{ jellyfin_home }}/plugins/configurations/LDAP-Auth.xml'
+ owner: '{{ jellyfin_user }}'
+ group: '{{ jellyfin_user }}'
+ mode: 0640
+ notify: restart jellyfin
+
+- import_tasks: freeipa.yml
+
+- name: enable jellyfin
+ systemd:
+ name: jellyfin
+ state: started
+ enabled: yes
+
+- name: allow apache to connect to jellyfin port
+ seport:
+ ports: '{{ jellyfin_port }}'
+ proto: tcp
+ setype: http_port_t
+ state: present
+ tags: selinux
+
+- name: open firewall ports
+ firewalld:
+ port: '{{ item }}'
+ permanent: yes
+ immediate: yes
+ state: enabled
+ loop: '{{ jellyfin_discovery_ports }}'
+ tags: firewalld
diff --git a/roles/jellyfin/templates/etc/jellyfin/network.xml.j2 b/roles/jellyfin/templates/etc/jellyfin/network.xml.j2
new file mode 100644
index 0000000..9b73f6b
--- /dev/null
+++ b/roles/jellyfin/templates/etc/jellyfin/network.xml.j2
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<NetworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <RequireHttps>false</RequireHttps>
+ <BaseUrl />
+ <PublicHttpsPort>0</PublicHttpsPort>
+ <HttpServerPortNumber>{{ jellyfin_port }}</HttpServerPortNumber>
+ <HttpsPortNumber>0</HttpsPortNumber>
+ <EnableHttps>false</EnableHttps>
+ <PublicPort>{{ jellyfin_port }}</PublicPort>
+ <UPnPCreateHttpPortMap>false</UPnPCreateHttpPortMap>
+ <UDPPortRange />
+ <EnableIPV6>false</EnableIPV6>
+ <EnableIPV4>true</EnableIPV4>
+ <EnableSSDPTracing>false</EnableSSDPTracing>
+ <SSDPTracingFilter />
+ <UDPSendCount>2</UDPSendCount>
+ <UDPSendDelay>100</UDPSendDelay>
+ <IgnoreVirtualInterfaces>true</IgnoreVirtualInterfaces>
+ <VirtualInterfaceNames>vEthernet*</VirtualInterfaceNames>
+ <GatewayMonitorPeriod>60</GatewayMonitorPeriod>
+ <TrustAllIP6Interfaces>false</TrustAllIP6Interfaces>
+ <HDHomerunPortRange />
+ <PublishedServerUriBySubnet />
+ <AutoDiscoveryTracing>false</AutoDiscoveryTracing>
+ <AutoDiscovery>true</AutoDiscovery>
+ <RemoteIPFilter />
+ <IsRemoteIPFilterBlacklist>false</IsRemoteIPFilterBlacklist>
+ <EnableUPnP>false</EnableUPnP>
+ <EnableRemoteAccess>true</EnableRemoteAccess>
+ <LocalNetworkSubnets />
+ <LocalNetworkAddresses>
+ <string>127.0.0.1</string>
+ </LocalNetworkAddresses>
+ <KnownProxies />
+ <EnablePublishedServerUriByRequest>false</EnablePublishedServerUriByRequest>
+</NetworkConfiguration>
diff --git a/roles/jellyfin/templates/etc/sysconfig/jellyfin.j2 b/roles/jellyfin/templates/etc/sysconfig/jellyfin.j2
new file mode 100644
index 0000000..75f56ff
--- /dev/null
+++ b/roles/jellyfin/templates/etc/sysconfig/jellyfin.j2
@@ -0,0 +1,22 @@
+# Program directories
+JELLYFIN_DATA_DIR="/var/lib/jellyfin"
+JELLYFIN_CONFIG_DIR="/etc/jellyfin"
+JELLYFIN_LOG_DIR="/var/log/jellyfin"
+JELLYFIN_CACHE_DIR="/var/cache/jellyfin"
+
+# web client path, installed by the jellyfin-web package
+JELLYFIN_WEB_OPT="--webdir={{ jellyfin_install_dir }}/jellyfin-web"
+
+# [OPTIONAL] ffmpeg binary paths, overriding the UI-configured values
+#JELLYFIN_FFMPEG_OPT="--ffmpeg=/usr/bin/ffmpeg"
+
+# [OPTIONAL] run Jellyfin as a headless service
+JELLYFIN_SERVICE_OPT="--service"
+
+# [OPTIONAL] run Jellyfin without the web app
+#JELLYFIN_NOWEBAPP_OPT="--noautorunwebapp"
+
+# [OPTIONAL] run Jellyfin with ASP.NET Server Garbage Collection (uses more RAM and less CPU than Workstation GC)
+# 0 = Workstation
+# 1 = Server
+COMPlus_gcServer=1
diff --git a/roles/jellyfin/templates/etc/systemd/system/jellyfin.service.j2 b/roles/jellyfin/templates/etc/systemd/system/jellyfin.service.j2
new file mode 100644
index 0000000..2b809bb
--- /dev/null
+++ b/roles/jellyfin/templates/etc/systemd/system/jellyfin.service.j2
@@ -0,0 +1,51 @@
+[Unit]
+Description = Jellyfin Media Server
+After=autofs.service network-online.target nss-user-lookup.target
+
+[Service]
+Type = simple
+EnvironmentFile = /etc/sysconfig/jellyfin
+User = {{ jellyfin_user }}
+Group = {{ jellyfin_user }}
+WorkingDirectory = /var/lib/jellyfin
+ExecStart = {{ jellyfin_install_dir }}/jellyfin ${JELLYFIN_WEB_OPT} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_FFMPEG_OPT} ${JELLYFIN_SERVICE_OPT} ${JELLYFIN_NOWEBAPP_OPT} ${JELLYFIN_ADDITIONAL_OPTS}
+Restart = on-failure
+TimeoutSec = 15
+SuccessExitStatus=0 143
+
+NoNewPrivileges=true
+SystemCallArchitectures=native
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
+RestrictNamespaces=false
+RestrictRealtime=true
+RestrictSUIDSGID=true
+ProtectClock=true
+ProtectControlGroups=false
+ProtectHostname=true
+ProtectKernelLogs=false
+ProtectKernelModules=false
+ProtectKernelTunables=false
+LockPersonality=true
+PrivateTmp=false
+PrivateDevices=false
+PrivateUsers=true
+RemoveIPC=true
+SystemCallFilter=~@clock
+SystemCallFilter=~@aio
+SystemCallFilter=~@chown
+SystemCallFilter=~@cpu-emulation
+SystemCallFilter=~@debug
+SystemCallFilter=~@keyring
+SystemCallFilter=~@memlock
+SystemCallFilter=~@module
+SystemCallFilter=~@mount
+SystemCallFilter=~@obsolete
+SystemCallFilter=~@privileged
+SystemCallFilter=~@raw-io
+SystemCallFilter=~@reboot
+SystemCallFilter=~@setuid
+SystemCallFilter=~@swap
+SystemCallErrorNumber=EPERM
+
+[Install]
+WantedBy = multi-user.target
diff --git a/roles/jellyfin/templates/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml.j2 b/roles/jellyfin/templates/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml.j2
new file mode 100644
index 0000000..5326ff2
--- /dev/null
+++ b/roles/jellyfin/templates/var/lib/jellyfin/plugins/configurations/LDAP-Auth.xml.j2
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PluginConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <LdapServer>{{ jellyfin_ldap_server }}</LdapServer>
+ <LdapPort>636</LdapPort>
+ <UseSsl>true</UseSsl>
+ <UseStartTls>false</UseStartTls>
+ <SkipSslVerify>false</SkipSslVerify>
+ <LdapBindUser>uid={{ jellyfin_sysaccount_username }},{{ freeipa_sysaccount_basedn }}</LdapBindUser>
+ <LdapBindPassword>{{ jellyfin_sysaccount_password }}</LdapBindPassword>
+ <LdapBaseDn>{{ freeipa_user_basedn }}</LdapBaseDn>
+ <LdapSearchFilter>(memberOf=cn={{ jellyfin_access_group }},{{ freeipa_group_basedn }})</LdapSearchFilter>
+ <LdapAdminBaseDn />
+ <LdapAdminFilter>(memberOf=cn={{ jellyfin_admin_group }},{{ freeipa_group_basedn }})</LdapAdminFilter>
+ <LdapSearchAttributes>uid</LdapSearchAttributes>
+ <EnableCaseInsensitiveUsername>false</EnableCaseInsensitiveUsername>
+ <CreateUsersFromLdap>true</CreateUsersFromLdap>
+ <AllowPassChange>false</AllowPassChange>
+ <LdapUsernameAttribute>uid</LdapUsernameAttribute>
+ <LdapPasswordAttribute>userPassword</LdapPasswordAttribute>
+ <EnableAllFolders>true</EnableAllFolders>
+ <EnabledFolders />
+ <PasswordResetUrl />
+</PluginConfiguration>
diff --git a/roles/jellyfin/vars/main.yml b/roles/jellyfin/vars/main.yml
new file mode 100644
index 0000000..00b4251
--- /dev/null
+++ b/roles/jellyfin/vars/main.yml
@@ -0,0 +1,34 @@
+jellyfin_url: https://repo.jellyfin.org/releases/server/linux/stable/combined/jellyfin_{{ jellyfin_version }}_amd64.tar.gz
+
+jellyfin_packages:
+ - ffmpeg
+
+jellyfin_home: /var/lib/jellyfin
+jellyfin_conf_dir: /etc/jellyfin
+jellyfin_install_dir: /opt/jellyfin
+jellyfin_keytab: /var/lib/gssproxy/clients/{{ jellyfin_user }}.keytab
+
+jellyfin_discovery_ports:
+ - 1900/udp
+ - 7359/udp
+
+jellyfin_apache_config: |
+ {{ apache_proxy_config }}
+ ProxyPass / http://127.0.0.1:{{ jellyfin_port }}/
+ ProxyPassReverse / http://127.0.0.1:{{ jellyfin_port }}/
+
+ <Location /socket>
+ ProxyPass http://127.0.0.1:{{ jellyfin_port }}/socket/
+ ProxyPassReverse http://127.0.0.1:{{ jellyfin_port }}/socket/
+
+ RewriteEngine on
+ RewriteCond %{HTTP:Upgrade} websocket [NC]
+ RewriteCond %{HTTP:Connection} upgrade [NC]
+ RewriteRule ^/?(.*) "ws://127.0.0.1:{{ jellyfin_port }}/socket/$1" [P,L]
+ </Location>
+
+jellyfin_archive_shell: >-
+ TIMESTAMP=$(date +%Y%m%d%H%M%S);
+ tar czf "jellyfin-${TIMESTAMP}.tar.gz"
+ {{ jellyfin_home | quote }}/{data,metadata,plugins,root}
+ {{ jellyfin_conf_dir | quote }}