diff --git a/rpm-package/.gitignore b/rpm-package/.gitignore new file mode 100644 index 0000000000..6019b98c22 --- /dev/null +++ b/rpm-package/.gitignore @@ -0,0 +1,3 @@ +*.rpm +*.zip +*.tar.gz \ No newline at end of file diff --git a/rpm-package/Dockerfile.fedora_package b/rpm-package/Dockerfile.fedora_package new file mode 100644 index 0000000000..35650106d1 --- /dev/null +++ b/rpm-package/Dockerfile.fedora_package @@ -0,0 +1,17 @@ +FROM fedora:29 +ARG HOME=/build +RUN mkdir /build && \ + dnf install -y @buildsys-build rpmdevtools dnf-plugins-core && \ + dnf copr enable -y @dotnet-sig/dotnet && \ + rpmdev-setuptree + +WORKDIR /build/rpmbuild +COPY jellyfin.spec SPECS +COPY . SOURCES + +RUN spectool -g -R SPECS/jellyfin.spec && \ + rpmbuild -bs SPECS/jellyfin.spec && \ + dnf build-dep -y SRPMS/jellyfin-*.src.rpm && \ + rpmbuild -bb SPECS/jellyfin.spec && \ + mkdir /jellyfin && \ + find . -name 'jellyfin-*.rpm' -print -exec cp {} /jellyfin \; \ No newline at end of file diff --git a/rpm-package/README.md b/rpm-package/README.md new file mode 100644 index 0000000000..7ed6f7efc6 --- /dev/null +++ b/rpm-package/README.md @@ -0,0 +1,43 @@ +# Jellyfin RPM + +## Build Fedora Package with docker + +Change into this directory `cd rpm-package` +Run the build script `./build-fedora-rpm.sh`. +Resulting RPM and src.rpm will be in `../../jellyfin-*.rpm` + +## ffmpeg + +The RPM package for Fedora/CentOS requires some additional repositories as ffmpeg is not in the main repositories. + +```shell +# ffmpeg from RPMfusion free +# Fedora +$ sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm +# CentOS 7 +$ sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm +``` + +## ISO mounting + +To allow Jellyfin to mount/umount ISO files uncomment these two lines in `/etc/sudoers.d/jellyfin-sudoers` +``` +# %jellyfin ALL=(ALL) NOPASSWD: /bin/mount +# %jellyfin ALL=(ALL) NOPASSWD: /bin/umount +``` + +## Building with dotnet + +Jellyfin is build with `--self-contained` so no dotnet required for runtime. + +```shell +# dotnet required for building the RPM +# Fedora +$ sudo dnf copr enable @dotnet-sig/dotnet +# CentOS +$ sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm +``` + +## TODO + +- [ ] OpenSUSE \ No newline at end of file diff --git a/rpm-package/build-fedora-rpm.sh b/rpm-package/build-fedora-rpm.sh new file mode 100755 index 0000000000..87c94e0812 --- /dev/null +++ b/rpm-package/build-fedora-rpm.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env sh + +# Build a Jellyfin .rpm file with Docker on Linux +# Places the output .rpm file in the parent directory + +set -o errexit +set -o xtrace +set -o nounset + +package_temporary_dir="`mktemp -d`" +current_user="`whoami`" +image_name="jellyfin-rpmbuild" + +cleanup() { + set +o errexit + docker image rm $image_name --force + rm -rf "$package_temporary_dir" +} +trap cleanup EXIT INT + +docker build . -t "$image_name" -f ./Dockerfile.fedora_package +docker run --rm -v "$package_temporary_dir:/temp" "$image_name" cp -r /jellyfin /temp/ +sudo chown -R "$current_user" "$package_temporary_dir" +mv "$package_temporary_dir"/jellyfin/*.rpm ../../ diff --git a/rpm-package/jellyfin-firewalld.xml b/rpm-package/jellyfin-firewalld.xml new file mode 100644 index 0000000000..062db370da --- /dev/null +++ b/rpm-package/jellyfin-firewalld.xml @@ -0,0 +1,9 @@ + + + Jellyfin + The Free Software Media System. + + + + + \ No newline at end of file diff --git a/rpm-package/jellyfin.env b/rpm-package/jellyfin.env new file mode 100644 index 0000000000..827a33f468 --- /dev/null +++ b/rpm-package/jellyfin.env @@ -0,0 +1,27 @@ +# Jellyfin default configuration options + +# Use this file to override the default configurations; add additional +# options with JELLYFIN_ADD_OPTS. + +# To override the user or this config file's location, use +# /etc/systemd/system/jellyfin.service.d/override.conf + +# +# This is a POSIX shell fragment +# + +# +# General options +# + +# Tell jellyfin wich ffmpeg/ffprobe to use +# JELLYFIN_FFMPEG="-ffmpeg /usr/bin/ffmpeg -ffprobe /usr/bin/ffprobe" + +# Program directories +JELLYFIN_DATA_DIRECTORY="/var/lib/jellyfin" +JELLYFIN_CONFIG_DIRECTORY="/etc/jellyfin" +JELLYFIN_LOG_DIRECTORY="/var/log/jellyfin" +# In-App service control +JELLYFIN_RESTART_OPT="-restartpath /usr/libexec/jellyfin/restart.sh" +# Additional options for the binary +JELLYFIN_ADD_OPTS="" \ No newline at end of file diff --git a/rpm-package/jellyfin.override.conf b/rpm-package/jellyfin.override.conf new file mode 100644 index 0000000000..8652450bb4 --- /dev/null +++ b/rpm-package/jellyfin.override.conf @@ -0,0 +1,7 @@ +# Jellyfin systemd configuration options + +# Use this file to override the user or environment file location. + +[Service] +#User = jellyfin +#EnvironmentFile = /etc/sysconfig/jellyfin diff --git a/rpm-package/jellyfin.service b/rpm-package/jellyfin.service new file mode 100644 index 0000000000..0ece5b57f4 --- /dev/null +++ b/rpm-package/jellyfin.service @@ -0,0 +1,15 @@ +[Unit] +After=network.target +Description=Jellyfin is a free software media system that puts you in control of managing and streaming your media. + +[Service] +EnvironmentFile=/etc/sysconfig/jellyfin +WorkingDirectory=/var/lib/jellyfin +ExecStart=/usr/bin/jellyfin -programdata ${JELLYFIN_DATA_DIRECTORY} -configdir ${JELLYFIN_CONFIG_DIRECTORY} -logdir ${JELLYFIN_LOG_DIRECTORY} ${JELLYFIN_RESTART_OPT} ${JELLYFIN_ADD_OPTS} ${JELLYFIN_FFMPEG} +TimeoutSec=15 +Restart=on-failure +User=jellyfin +Group=jellyfin + +[Install] +WantedBy=multi-user.target diff --git a/rpm-package/jellyfin.spec b/rpm-package/jellyfin.spec new file mode 100644 index 0000000000..ff5725f871 --- /dev/null +++ b/rpm-package/jellyfin.spec @@ -0,0 +1,147 @@ +%global debug_package %{nil} +# jellyfin tag to package +%global gittag v10.0.2 +# Taglib-sharp commit of the submodule since github archive doesn't include submodules +%global taglib_commit ee5ab21742b71fd1b87ee24895582327e9e04776 +%global taglib_shortcommit %(c=%{taglib_commit}; echo ${c:0:7}) + +Name: jellyfin +Version: 10.0.2 +Release: 1%{?dist} +Summary: The Free Software Media Browser. +License: GPLv2 +URL: https://jellyfin.media +Source0: https://github.com/%{name}/%{name}/archive/%{gittag}.tar.gz +Source1: jellyfin.service +Source2: jellyfin.env +Source3: jellyfin.sudoers +Source4: restart.sh +Source5: https://github.com/mono/taglib-sharp/archive/%{taglib_commit}/taglib-sharp-%{taglib_shortcommit}.tar.gz +Source6: jellyfin.override.conf +Source7: jellyfin-firewalld.xml + +%{?systemd_requires} +BuildRequires: systemd +Requires(pre): shadow-utils +BuildRequires: libcurl-devel, fontconfig-devel, freetype-devel, openssl-devel, glibc-devel, libicu-devel +Requires: libcurl, fontconfig, freetype, openssl, glibc libicu +# Requirements not packaged in main repos +# COPR @dotnet-sig/dotnet +BuildRequires: dotnet-sdk-2.2 +# RPMfusion free +Requires: ffmpeg + +# For the update-db-paths.sh script to fix emby paths to jellyfin +%{?fedora:Recommends: sqlite} + +# Fedora has openssl1.1 which is incompatible with dotnet +%{?fedora:Requires: compat-openssl10} +# Disable Automatic Dependency Processing for Centos +%{?el7:AutoReqProv: no} + +%description +Jellyfin is a free software media system that puts you in control of managing and streaming your media. + + +%prep +%autosetup -n %{name}-%{version} +pushd ThirdParty + tar xf %{S:5} + rm -rf taglib-sharp + mv taglib-sharp-%{taglib_commit} taglib-sharp +popd + +%build +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +dotnet build --runtime linux-x64 + +%install +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +dotnet publish --configuration Release --output='%{buildroot}%{_libdir}/jellyfin' --self-contained --runtime linux-x64 +%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/%{name}/LICENSE +%{__install} -D -m 0644 %{SOURCE6} %{buildroot}%{_sysconfdir}/systemd/system/%{name}.service.d/override.conf +%{__install} -D -m 0644 Jellyfin.Server/Resources/Configuration/logging.json %{buildroot}%{_sysconfdir}/%{name}/logging.json +%{__mkdir} -p %{buildroot}%{_bindir} +tee %{buildroot}%{_bindir}/jellyfin << EOF +#!/bin/sh +exec %{_libdir}/%{name}/%{name} \${@} +EOF +%{__mkdir} -p %{buildroot}%{_sharedstatedir}/jellyfin +%{__mkdir} -p %{buildroot}%{_sysconfdir}/%{name} +%{__mkdir} -p %{buildroot}%{_var}/log/jellyfin + +%{__install} -D -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/%{name}.service +%{__install} -D -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name} +%{__install} -D -m 0600 %{SOURCE3} %{buildroot}%{_sysconfdir}/sudoers.d/%{name}-sudoers +%{__install} -D -m 0755 %{SOURCE4} %{buildroot}%{_libexecdir}/%{name}/restart.sh +%{__install} -D -m 0644 %{SOURCE7} %{buildroot}%{_prefix}/lib/firewalld/service/%{name}.xml + +%files +%{_libdir}/%{name}/dashboard-ui/* +%attr(755,root,root) %{_bindir}/%{name} +%{_libdir}/%{name}/*.json +%{_libdir}/%{name}/*.pdb +%{_libdir}/%{name}/*.dll +%{_libdir}/%{name}/*.so +%{_libdir}/%{name}/*.a +%{_libdir}/%{name}/createdump +# Needs 755 else only root can run it since binary build by dotnet is 722 +%attr(755,root,root) %{_libdir}/%{name}/jellyfin +%{_libdir}/%{name}/sosdocsunix.txt +%{_unitdir}/%{name}.service +%{_libexecdir}/%{name}/restart.sh +%{_prefix}/lib/firewalld/service/%{name}.xml +%attr(755,jellyfin,jellyfin) %dir %{_sysconfdir}/%{name} +%config %{_sysconfdir}/sysconfig/%{name} +%config(noreplace) %attr(600,root,root) %{_sysconfdir}/sudoers.d/%{name}-sudoers +%config(noreplace) %{_sysconfdir}/systemd/system/%{name}.service.d/override.conf +%config(noreplace) %attr(644,jellyfin,jellyfin) %{_sysconfdir}/%{name}/logging.json +%attr(-,jellyfin,jellyfin) %dir %{_sharedstatedir}/jellyfin +%attr(-,jellyfin,jellyfin) %dir %{_var}/log/jellyfin +%if 0%{?fedora} +%license LICENSE +%else +%{_datadir}/licenses/%{name}/LICENSE +%endif + +%pre +getent group jellyfin >/dev/null || groupadd -r jellyfin +getent passwd jellyfin >/dev/null || \ + useradd -r -g jellyfin -d %{_sharedstatedir}/jellyfin -s /sbin/nologin \ + -c "Jellyfin default user" jellyfin +exit 0 + +%post +# Move existing configuration to /etc/jellyfin and symlink config to /etc/jellyfin +if [ $1 -gt 1 ] ; then + service_state=$(systemctl is-active jellyfin.service) + if [ "${service_state}" = "active" ]; then + systemctl stop jellyfin.service + fi + if [ ! -L %{_sharedstatedir}/%{name}/config ]; then + mv %{_sharedstatedir}/%{name}/config/* %{_sysconfdir}/%{name}/ + rmdir %{_sharedstatedir}/%{name}/config + ln -sf %{_sysconfdir}/%{name} %{_sharedstatedir}/%{name}/config + fi + if [ ! -L %{_sharedstatedir}/%{name}/logs ]; then + mv %{_sharedstatedir}/%{name}/logs/* %{_var}/log/jellyfin + rmdir %{_sharedstatedir}/%{name}/logs + ln -sf %{_var}/log/jellyfin %{_sharedstatedir}/%{name}/logs + fi + if [ "${service_state}" = "active" ]; then + systemctl start jellyfin.service + fi +fi +%systemd_post jellyfin.service + +%preun +%systemd_preun jellyfin.service + +%postun +%systemd_postun_with_restart jellyfin.service + +%changelog +* Fri Jan 11 2019 Thomas Büttner - 10.0.2-1 +- TODO Changelog for 10.0.2 diff --git a/rpm-package/jellyfin.sudoers b/rpm-package/jellyfin.sudoers new file mode 100644 index 0000000000..b31d52f7ec --- /dev/null +++ b/rpm-package/jellyfin.sudoers @@ -0,0 +1,19 @@ +# Allow jellyfin group to start, stop and restart itself +Cmnd_Alias RESTARTSERVER_SYSTEMD = /usr/bin/systemctl restart jellyfin, /bin/systemctl restart jellyfin +Cmnd_Alias STARTSERVER_SYSTEMD = /usr/bin/systemctl start jellyfin, /bin/systemctl start jellyfin +Cmnd_Alias STOPSERVER_SYSTEMD = /usr/bin/systemctl stop jellyfin, /bin/systemctl stop jellyfin + + +%jellyfin ALL=(ALL) NOPASSWD: RESTARTSERVER_SYSTEMD +%jellyfin ALL=(ALL) NOPASSWD: STARTSERVER_SYSTEMD +%jellyfin ALL=(ALL) NOPASSWD: STOPSERVER_SYSTEMD + +Defaults!RESTARTSERVER_SYSTEMD !requiretty +Defaults!STARTSERVER_SYSTEMD !requiretty +Defaults!STOPSERVER_SYSTEMD !requiretty + +# Uncomment to allow the server to mount iso images +# %jellyfin ALL=(ALL) NOPASSWD: /bin/mount +# %jellyfin ALL=(ALL) NOPASSWD: /bin/umount + +Defaults:%jellyfin !requiretty diff --git a/rpm-package/restart.sh b/rpm-package/restart.sh new file mode 100755 index 0000000000..e84dca587f --- /dev/null +++ b/rpm-package/restart.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +NAME=jellyfin +restart_cmd="/usr/bin/systemctl restart ${NAME}" +echo "sleep 2; sudo $restart_cmd > /dev/null 2>&1" | at now > /dev/null 2>&1 +exit 0 \ No newline at end of file