diff --git a/.dockerignore b/.dockerignore
index fc4d8ed26d..54b0aa3a7e 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -3,3 +3,6 @@
Dockerfile
CONTRIBUTORS.md
README.md
+deployment/*/dist
+deployment/*/pkg-dist
+deployment/collect-dist/
diff --git a/.gitignore b/.gitignore
index 880e63a7f9..ec683f38f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-!*
-
.directory
#################
@@ -49,6 +47,8 @@ ProgramData-UI*/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+.vs/
+
# User-specific files
*.suo
*.user
@@ -204,7 +204,6 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
-
#############
## Python
#############
@@ -234,23 +233,33 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
-/.vs
##########
# Rider
##########
.idea/
+##########
+# Visual Studio Code
+##########
+.vscode/
+
#########################
-# Debian build artifacts
+# Build artifacts
#########################
-debian/.debhelper/
-debian/*.debhelper
-debian/debhelper-build-stamp
-debian/files
-debian/jellyfin.substvars
-debian/jellyfin/
-
+# Artifacts for debian-x64
+deployment/debian-package-x64/pkg-src/.debhelper/
+deployment/debian-package-x64/pkg-src/*.debhelper
+deployment/debian-package-x64/pkg-src/debhelper-build-stamp
+deployment/debian-package-x64/pkg-src/files
+deployment/debian-package-x64/pkg-src/jellyfin.substvars
+deployment/debian-package-x64/pkg-src/jellyfin/
# Don't ignore the debian/bin folder
-!debian/bin/
+!deployment/debian-package-x64/pkg-src/bin/
+
+deployment/**/dist/
+deployment/**/pkg-dist/
+deployment/**/pkg-dist-tmp/
+deployment/collect-dist/
+
diff --git a/Dockerfile b/Dockerfile
index e4cbede80c..02332d40b4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,6 +26,6 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=ffmpeg /ffmpeg-bin/* /usr/bin/
EXPOSE 8096
VOLUME /config /media
-RUN apt update \
- && apt install -y libfontconfig1 # needed for Skia
+RUN apt-get update \
+ && apt-get install -y libfontconfig1 --no-install-recommends # needed for Skia
ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config
diff --git a/Dockerfile.aarch64 b/Dockerfile.arm
similarity index 81%
rename from Dockerfile.aarch64
rename to Dockerfile.arm
index cc70ef32f2..a0b3d0e1da 100644
--- a/Dockerfile.aarch64
+++ b/Dockerfile.arm
@@ -3,6 +3,7 @@ ARG DOTNET_VERSION=3.0
FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder
WORKDIR /repo
COPY . .
+#TODO Remove or update the sed line when we update dotnet version.
RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
&& find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \
&& dotnet clean \
@@ -14,7 +15,7 @@ RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \
FROM microsoft/dotnet:${DOTNET_VERSION}-runtime
COPY --from=builder /jellyfin /jellyfin
EXPOSE 8096
-RUN apt update \
- && apt install -y ffmpeg
+RUN apt-get update \
+ && apt-get install -y ffmpeg
VOLUME /config /media
ENTRYPOINT dotnet /jellyfin/jellyfin.dll -programdata /config
diff --git a/build-deb.sh b/build-deb.sh
deleted file mode 100755
index fd14fc17db..0000000000
--- a/build-deb.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env sh
-
-# Build a Jellyfin .deb file with Docker on Linux
-# Places the output .deb 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-debuild"
-
-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.debian_package
-docker run --rm -v "$package_temporary_dir:/temp" "$image_name" cp -r /dist /temp/
-sudo chown -R "$current_user" "$package_temporary_dir"
-mv "$package_temporary_dir"/dist/*.deb ../
diff --git a/debian/source/options b/debian/source/options
deleted file mode 100644
index 45bef47641..0000000000
--- a/debian/source/options
+++ /dev/null
@@ -1 +0,0 @@
-tar-ignore = ".git*"
diff --git a/deployment/README.md b/deployment/README.md
new file mode 100644
index 0000000000..3400fd8400
--- /dev/null
+++ b/deployment/README.md
@@ -0,0 +1,8 @@
+# Build scripts
+
+All `build.sh` and `package.sh` scripts are for *nix platforms (or WSL on Windows 10).
+
+After running both, check the `*/pkg-dist/` folders for the archives and packages.
+
+`build_all.sh` will invoke every build and package script.
+Use `collect_all.sh` to copy all artifact to one directory for easy uploading.
diff --git a/deployment/clean.sh b/deployment/clean.sh
new file mode 100755
index 0000000000..7517cf8493
--- /dev/null
+++ b/deployment/clean.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+set -e
+
+# Execute every clean.sh scripts in every folder.
+echo "Running for platforms '$@'."
+for directory in */ ; do
+ platform=`basename "${directory}"`
+ if [[ $@ == *"$platform"* || $@ = *"all"* ]]; then
+ echo "Processing ${platform}"
+ pushd "$platform"
+ if [ -f clean.sh ]; then
+ echo ./clean.sh
+ fi
+ popd
+ else
+ echo "Skipping $platform."
+ fi
+done
+
+rm -rf ./collect-dist
diff --git a/deployment/collect_all.sh b/deployment/collect_all.sh
new file mode 100755
index 0000000000..69babe55e1
--- /dev/null
+++ b/deployment/collect_all.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+source common.build.sh
+
+VERSION=`get_version ..`
+
+COLLECT_DIR="./collect-dist"
+
+mkdir -p ./collect-dist
+
+DIRS=`find . -type d -name "pkg-dist"`
+
+while read directory
+do
+ echo "Collecting everything from '$directory'.."
+ PLATFORM=$(basename "$(dirname "$directory")")
+ # Copy all artifacts with extensions tar.gz, deb, exe, zip, rpm and add the platform name to resolve any duplicates.
+ find $directory \( -name "jellyfin*.tar.gz" -o -name "jellyfin*.deb" -o -name "jellyfin*.rpm" -o -name "jellyfin*.zip" -o -name "jellyfin*.exe" \) -exec sh -c 'cp "$1" "'${COLLECT_DIR}'/jellyfin_'${PLATFORM}'_${1#*jellyfin}"' _ {} \;
+
+done <<< "${DIRS}"
diff --git a/deployment/common.build.sh b/deployment/common.build.sh
new file mode 100755
index 0000000000..a368928bab
--- /dev/null
+++ b/deployment/common.build.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+set -o errexit
+set -o nounset
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+CYAN='\033[0;36m'
+NC='\033[0m' # No Color
+
+DEFAULT_BUILD_CONTEXT="../.."
+DEFAULT_ROOT="."
+DEFAULT_DOTNETRUNTIME="framework"
+DEFAULT_CONFIG="Release"
+DEFAULT_OUTPUT_DIR="dist/jellyfin-git"
+DEFAULT_PKG_DIR="pkg-dist"
+DEFAULT_DOCKERFILE="Dockerfile"
+DEFAULT_IMAGE_TAG="jellyfin:"`git rev-parse --abbrev-ref HEAD`
+
+# Run a build
+build_jellyfin()
+(
+ ROOT=${1-$DEFAULT_ROOT}
+ CONFIG=${2-$DEFAULT_CONFIG}
+ DOTNETRUNTIME=${3-$DEFAULT_DOTNETRUNTIME}
+ OUTPUT_DIR=${4-$DEFAULT_OUTPUT_DIR}
+
+ echo -e "${CYAN}Building jellyfin in '${ROOT}' for ${DOTNETRUNTIME} with configuration ${CONFIG} and output directory '${OUTPUT_DIR}'.${NC}"
+ if [[ $DOTNETRUNTIME == 'framework' ]]; then
+ dotnet publish "${ROOT}" --configuration "${CONFIG}" --output="${OUTPUT_DIR}"
+ else
+ dotnet publish "${ROOT}" --configuration "${CONFIG}" --output="${OUTPUT_DIR}" --self-contained --runtime ${DOTNETRUNTIME}
+ fi
+ EXIT_CODE=$?
+ if [ $EXIT_CODE -eq 0 ]; then
+ echo -e "${GREEN}[DONE] Build jellyfin in '${ROOT}' for ${DOTNETRUNTIME} with configuration ${CONFIG} and output directory '${OUTPUT_DIR}' complete.${NC}"
+ else
+ echo -e "${RED}[FAIL] Build jellyfin in '${ROOT}' for ${DOTNETRUNTIME} with configuration ${CONFIG} and output directory '${OUTPUT_DIR}' FAILED.${NC}"
+ fi
+)
+
+# Run a docker
+build_jellyfin_docker()
+(
+ BUILD_CONTEXT=${1-$DEFAULT_BUILD_CONTEXT}
+ DOCKERFILE=${2-$DEFAULT_DOCKERFILE}
+ IMAGE_TAG=${3-$DEFAULT_IMAGE_TAG}
+
+ echo -e "${CYAN}Building jellyfin docker image in '${BUILD_CONTEXT}' with Dockerfile '${DOCKERFILE}' and tag '${IMAGE_TAG}'.${NC}"
+ docker build -t ${IMAGE_TAG} -f ${DOCKERFILE} ${BUILD_CONTEXT}
+ EXIT_CODE=$?
+ if [ $EXIT_CODE -eq 0 ]; then
+ echo -e "${GREEN}[DONE] Building jellyfin docker image in '${BUILD_CONTEXT}' with Dockerfile '${DOCKERFILE}' and tag '${IMAGE_TAG}' complete.${NC}"
+ else
+ echo -e "${RED}[FAIL] Building jellyfin docker image in '${BUILD_CONTEXT}' with Dockerfile '${DOCKERFILE}' and tag '${IMAGE_TAG}' FAILED.${NC}"
+ fi
+)
+
+# Clean a build
+clean_jellyfin()
+(
+ local ROOT=${1-$DEFAULT_ROOT}
+ local CONFIG=${2-$DEFAULT_CONFIG}
+ local OUTPUT_DIR=${3-$DEFAULT_OUTPUT_DIR}
+ local PKG_DIR=${4-$DEFAULT_PKG_DIR}
+ echo -e "${CYAN}Cleaning jellyfin in '${ROOT}'' with configuration ${CONFIG} and output directory '${OUTPUT_DIR}'.${NC}"
+ echo -e "${CYAN}Deleting '${OUTPUT_DIR}'${NC}"
+ rm -rf "$OUTPUT_DIR"
+ echo -e "${CYAN}Deleting '${PKG_DIR}'${NC}"
+ rm -rf "$PKG_DIR"
+ dotnet clean "${ROOT}" -maxcpucount:1 --configuration ${CONFIG}
+ local EXIT_CODE=$?
+ if [ $EXIT_CODE -eq 0 ]; then
+ echo -e "${GREEN}[DONE] Clean jellyfin in '${ROOT}' with configuration ${CONFIG} and output directory '${OUTPUT_DIR}' complete.${NC}"
+ else
+ echo -e "${RED}[FAIL] Clean jellyfin in '${ROOT}' with configuration ${CONFIG} and output directory '${OUTPUT_DIR}' failed.${NC}"
+ fi
+)
+
+# Parse the version from the AssemblyVersion
+get_version()
+(
+ local ROOT=${1-$DEFAULT_ROOT}
+ grep "AssemblyVersion" ${ROOT}/SharedVersion.cs | sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/' | sed -E 's/.0$//'
+)
+
+# Packages the output folder into an archive.
+package_portable()
+(
+ local ROOT=${1-$DEFAULT_ROOT}
+ local OUTPUT_DIR=${2-$DEFAULT_OUTPUT_DIR}
+ local PKG_DIR=${3-$DEFAULT_PKG_DIR}
+ # Package portable build result
+ if [ -d ${OUTPUT_DIR} ]; then
+ echo -e "${CYAN}Packaging build in '${OUTPUT_DIR}' for `basename "${OUTPUT_DIR}"` to '${PKG_DIR}' with root '${ROOT}'.${NC}"
+ mkdir -p ${PKG_DIR}
+ tar -zcvf "${PKG_DIR}/`basename "${OUTPUT_DIR}"`.portable.tar.gz" -C "`dirname "${OUTPUT_DIR}"`" "`basename "${OUTPUT_DIR}"`"
+ local EXIT_CODE=$?
+ if [ $EXIT_CODE -eq 0 ]; then
+ echo -e "${GREEN}[DONE] Packaging build in '${OUTPUT_DIR}' for `basename "${OUTPUT_DIR}"` to '${PKG_DIR}' with root '${ROOT}' complete.${NC}"
+ else
+ echo -e "${RED}[FAIL] Packaging build in '${OUTPUT_DIR}' for `basename "${OUTPUT_DIR}"` to '${PKG_DIR}' with root '${ROOT}' FAILED.${NC}"
+ fi
+ else
+ echo -e "${RED}[FAIL] Build artifacts do not exist for ${OUTPUT_DIR}. Run build.sh first.${NC}"
+ fi
+)
+
diff --git a/Dockerfile.debian_package b/deployment/debian-package-x64/Dockerfile
similarity index 75%
rename from Dockerfile.debian_package
rename to deployment/debian-package-x64/Dockerfile
index c5c631b71a..2afe6c1d37 100644
--- a/Dockerfile.debian_package
+++ b/deployment/debian-package-x64/Dockerfile
@@ -1,4 +1,6 @@
FROM debian:9
+ARG SOURCEDIR=/repo
+ENV DEB_BUILD_OPTIONS=noddebs
# https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current
RUN apt-get update \
@@ -11,12 +13,11 @@ RUN apt-get update \
&& chown root:root /etc/apt/sources.list.d/microsoft-prod.list \
&& apt-get update
-WORKDIR /repo
+WORKDIR ${SOURCEDIR}
COPY . .
+COPY ./deployment/debian-package-x64/pkg-src ./debian
-RUN yes|mk-build-deps -i \
- && dpkg-buildpackage -us -uc \
- && mkdir /dist \
- && mv /jellyfin*deb /dist
+RUN yes | mk-build-deps -i debian/control \
+ && dpkg-buildpackage -us -uc
-WORKDIR /dist
+WORKDIR /
diff --git a/deployment/debian-package-x64/clean.sh b/deployment/debian-package-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/debian-package-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/debian-package-x64/package.sh b/deployment/debian-package-x64/package.sh
new file mode 100755
index 0000000000..dec953961f
--- /dev/null
+++ b/deployment/debian-package-x64/package.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+# TODO get the version in the package automatically. And using the changelog to decide the debian package suffix version.
+
+# Build a Jellyfin .deb file with Docker on Linux
+# Places the output .deb file in the parent directory
+
+package_temporary_dir="`pwd`/pkg-dist-tmp"
+output_dir="`pwd`/pkg-dist"
+current_user="`whoami`"
+image_name="jellyfin-debuild"
+
+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 --build-arg SOURCEDIR="/jellyfin-${VERSION}"
+mkdir -p "$package_temporary_dir"
+mkdir -p "$output_dir"
+docker run --rm -v "$package_temporary_dir:/temp" "$image_name" sh -c 'find / -maxdepth 1 -type f -name "jellyfin*" -exec mv {} /temp \;'
+chown -R "$current_user" "$package_temporary_dir" \
+|| sudo chown -R "$current_user" "$package_temporary_dir"
+
+mv "$package_temporary_dir"/* "$output_dir"
diff --git a/debian/bin/jellyfin-sudoers b/deployment/debian-package-x64/pkg-src/bin/jellyfin-sudoers
similarity index 100%
rename from debian/bin/jellyfin-sudoers
rename to deployment/debian-package-x64/pkg-src/bin/jellyfin-sudoers
diff --git a/debian/bin/restart.sh b/deployment/debian-package-x64/pkg-src/bin/restart.sh
similarity index 100%
rename from debian/bin/restart.sh
rename to deployment/debian-package-x64/pkg-src/bin/restart.sh
diff --git a/debian/changelog b/deployment/debian-package-x64/pkg-src/changelog
similarity index 100%
rename from debian/changelog
rename to deployment/debian-package-x64/pkg-src/changelog
diff --git a/debian/compat b/deployment/debian-package-x64/pkg-src/compat
similarity index 100%
rename from debian/compat
rename to deployment/debian-package-x64/pkg-src/compat
diff --git a/debian/conf/jellyfin b/deployment/debian-package-x64/pkg-src/conf/jellyfin
similarity index 100%
rename from debian/conf/jellyfin
rename to deployment/debian-package-x64/pkg-src/conf/jellyfin
diff --git a/debian/conf/jellyfin.service.conf b/deployment/debian-package-x64/pkg-src/conf/jellyfin.service.conf
similarity index 100%
rename from debian/conf/jellyfin.service.conf
rename to deployment/debian-package-x64/pkg-src/conf/jellyfin.service.conf
diff --git a/debian/conf/logging.json b/deployment/debian-package-x64/pkg-src/conf/logging.json
similarity index 100%
rename from debian/conf/logging.json
rename to deployment/debian-package-x64/pkg-src/conf/logging.json
diff --git a/debian/control b/deployment/debian-package-x64/pkg-src/control
similarity index 100%
rename from debian/control
rename to deployment/debian-package-x64/pkg-src/control
diff --git a/debian/copyright b/deployment/debian-package-x64/pkg-src/copyright
similarity index 100%
rename from debian/copyright
rename to deployment/debian-package-x64/pkg-src/copyright
diff --git a/debian/gbp.conf b/deployment/debian-package-x64/pkg-src/gbp.conf
similarity index 63%
rename from debian/gbp.conf
rename to deployment/debian-package-x64/pkg-src/gbp.conf
index f131b973c2..60b3d28723 100644
--- a/debian/gbp.conf
+++ b/deployment/debian-package-x64/pkg-src/gbp.conf
@@ -3,4 +3,4 @@ pristine-tar = False
cleaner = fakeroot debian/rules clean
[import-orig]
-filter = [ ".git*", ".hg*" ]
+filter = [ ".git*", ".hg*", ".vs*", ".vscode*" ]
diff --git a/debian/install b/deployment/debian-package-x64/pkg-src/install
similarity index 100%
rename from debian/install
rename to deployment/debian-package-x64/pkg-src/install
diff --git a/debian/jellyfin.init b/deployment/debian-package-x64/pkg-src/jellyfin.init
similarity index 100%
rename from debian/jellyfin.init
rename to deployment/debian-package-x64/pkg-src/jellyfin.init
diff --git a/debian/jellyfin.service b/deployment/debian-package-x64/pkg-src/jellyfin.service
similarity index 100%
rename from debian/jellyfin.service
rename to deployment/debian-package-x64/pkg-src/jellyfin.service
diff --git a/debian/jellyfin.upstart b/deployment/debian-package-x64/pkg-src/jellyfin.upstart
similarity index 100%
rename from debian/jellyfin.upstart
rename to deployment/debian-package-x64/pkg-src/jellyfin.upstart
diff --git a/debian/po/POTFILES.in b/deployment/debian-package-x64/pkg-src/po/POTFILES.in
similarity index 100%
rename from debian/po/POTFILES.in
rename to deployment/debian-package-x64/pkg-src/po/POTFILES.in
diff --git a/debian/po/templates.pot b/deployment/debian-package-x64/pkg-src/po/templates.pot
similarity index 100%
rename from debian/po/templates.pot
rename to deployment/debian-package-x64/pkg-src/po/templates.pot
diff --git a/debian/postinst b/deployment/debian-package-x64/pkg-src/postinst
similarity index 100%
rename from debian/postinst
rename to deployment/debian-package-x64/pkg-src/postinst
diff --git a/debian/postrm b/deployment/debian-package-x64/pkg-src/postrm
similarity index 100%
rename from debian/postrm
rename to deployment/debian-package-x64/pkg-src/postrm
diff --git a/debian/preinst b/deployment/debian-package-x64/pkg-src/preinst
similarity index 100%
rename from debian/preinst
rename to deployment/debian-package-x64/pkg-src/preinst
diff --git a/debian/prerm b/deployment/debian-package-x64/pkg-src/prerm
similarity index 100%
rename from debian/prerm
rename to deployment/debian-package-x64/pkg-src/prerm
diff --git a/debian/rules b/deployment/debian-package-x64/pkg-src/rules
old mode 100755
new mode 100644
similarity index 67%
rename from debian/rules
rename to deployment/debian-package-x64/pkg-src/rules
index 10a3a84864..ce98cb8f86
--- a/debian/rules
+++ b/deployment/debian-package-x64/pkg-src/rules
@@ -2,7 +2,7 @@
CONFIG := Release
TERM := xterm
SHELL := /bin/bash
-DOTNETRUNTIME := linux-x64
+DOTNETRUNTIME := debian-x64
export DH_VERBOSE=1
export DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -16,8 +16,8 @@ override_dh_auto_test:
override_dh_clistrip:
override_dh_auto_build:
- dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME)
+ dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME) Jellyfin.Server
override_dh_auto_clean:
- dotnet clean -maxcpucount:1 --configuration $(CONFIG) || true
+ dotnet clean -maxcpucount:1 --configuration $(CONFIG) Jellyfin.Server || true
rm -rf '$(CURDIR)/usr'
diff --git a/debian/source.lintian-overrides b/deployment/debian-package-x64/pkg-src/source.lintian-overrides
similarity index 100%
rename from debian/source.lintian-overrides
rename to deployment/debian-package-x64/pkg-src/source.lintian-overrides
diff --git a/debian/source/format b/deployment/debian-package-x64/pkg-src/source/format
similarity index 100%
rename from debian/source/format
rename to deployment/debian-package-x64/pkg-src/source/format
diff --git a/deployment/debian-package-x64/pkg-src/source/options b/deployment/debian-package-x64/pkg-src/source/options
new file mode 100644
index 0000000000..17b5373d5e
--- /dev/null
+++ b/deployment/debian-package-x64/pkg-src/source/options
@@ -0,0 +1,11 @@
+tar-ignore='.git*'
+tar-ignore='**/.git'
+tar-ignore='**/.hg'
+tar-ignore='**/.vs'
+tar-ignore='**/.vscode'
+tar-ignore='deployment'
+tar-ignore='**/bin'
+tar-ignore='**/obj'
+tar-ignore='**/.nuget'
+tar-ignore='*.deb'
+tar-ignore='ThirdParty'
diff --git a/deployment/debian-x64/build.sh b/deployment/debian-x64/build.sh
new file mode 100755
index 0000000000..47cfb53270
--- /dev/null
+++ b/deployment/debian-x64/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release debian-x64 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/debian-x64/clean.sh b/deployment/debian-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/debian-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/debian-x64/package.sh b/deployment/debian-x64/package.sh
new file mode 100755
index 0000000000..13b943ea8f
--- /dev/null
+++ b/deployment/debian-x64/package.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/docker/build.sh b/deployment/docker/build.sh
new file mode 100755
index 0000000000..444208c85c
--- /dev/null
+++ b/deployment/docker/build.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin_docker ../.. ../../Dockerfile jellyfin:amd64-${VERSION}
+
+build_jellyfin_docker ../.. ../../Dockerfile.arm jellyfin:arm-${VERSION}
+
+#build_jellyfin_docker ../.. ../../Dockerfile.arm64v8 jellyfin:arm64v8-${VERSION}
+#build_jellyfin_docker ../.. ../../Dockerfile.arm32v7 jellyfin:arm32v7-${VERSION}
diff --git a/deployment/docker/package.sh b/deployment/docker/package.sh
new file mode 100755
index 0000000000..d74426e2fe
--- /dev/null
+++ b/deployment/docker/package.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+docker manifest create jellyfin:${VERSION} jellyfin:amd64-${VERSION} jellyfin:arm32v7-${VERSION} jellyfin:arm64v8-${VERSION}
+docker manifest annotate jellyfin:amd64-${VERSION} --os linux --arch amd64
+#docker manifest annotate jellyfin:arm32v7-${VERSION} --os linux --arch arm --variant armv7
+#docker manifest annotate jellyfin:arm64v8-${VERSION} --os linux --arch arm64 --variant armv8
+
+#TODO publish.sh - docker manifest push jellyfin:${VERSION}
diff --git a/deployment/fedora-package-x64/Dockerfile b/deployment/fedora-package-x64/Dockerfile
new file mode 100644
index 0000000000..e5deac29fb
--- /dev/null
+++ b/deployment/fedora-package-x64/Dockerfile
@@ -0,0 +1,15 @@
+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 ./deployment/fedora-package-x64/pkg-src/jellyfin.spec SPECS
+COPY ./deployment/fedora-package-x64/pkg-src/ 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;
\ No newline at end of file
diff --git a/deployment/fedora-package-x64/clean.sh b/deployment/fedora-package-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/fedora-package-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/fedora-package-x64/package.sh b/deployment/fedora-package-x64/package.sh
new file mode 100755
index 0000000000..416c8213b9
--- /dev/null
+++ b/deployment/fedora-package-x64/package.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env sh
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+# TODO get the version in the package automatically. And using the changelog to decide the debian package suffix version.
+
+# 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="`pwd`/pkg-dist-tmp"
+output_dir="`pwd`/pkg-dist"
+pkg_src_dir="`pwd`/pkg-src"
+current_user="`whoami`"
+image_name="jellyfin-rpmbuild"
+
+cleanup() {
+ set +o errexit
+ docker image rm $image_name --force
+ rm -rf "$package_temporary_dir"
+ rm -rf "$pkg_src_dir/jellyfin-${VERSION}.tar.gz"
+}
+trap cleanup EXIT INT
+GNU_TAR=1
+mkdir -p "$package_temporary_dir"
+echo "Bundling all sources for RPM build."
+tar \
+--transform "s,^\.,jellyfin-${VERSION}" \
+--exclude='.git*' \
+--exclude='**/.git' \
+--exclude='**/.hg' \
+--exclude='**/.vs' \
+--exclude='**/.vscode' \
+--exclude='deployment' \
+--exclude='**/bin' \
+--exclude='**/obj' \
+--exclude='**/.nuget' \
+--exclude='*.deb' \
+--exclude='*.rpm' \
+-Jcvf \
+"$package_temporary_dir/jellyfin-${VERSION}.tar.xz" \
+-C "../.." \
+./ || true && GNU_TAR=0
+
+if [ $GNU_TAR -eq 0 ]; then
+ echo "The installed tar binary did not support --transform. Using workaround."
+ mkdir -p "$package_temporary_dir/jellyfin-${VERSION}"
+ # Not GNU tar
+ tar \
+ --exclude='.git*' \
+ --exclude='**/.git' \
+ --exclude='**/.hg' \
+ --exclude='**/.vs' \
+ --exclude='**/.vscode' \
+ --exclude='deployment' \
+ --exclude='**/bin' \
+ --exclude='**/obj' \
+ --exclude='**/.nuget' \
+ --exclude='*.deb' \
+ --exclude='*.rpm' \
+ -zcf \
+ "$package_temporary_dir/jellyfin-${VERSION}/jellyfin.tar.gz" \
+ -C "../.." \
+ ./
+ echo "Extracting filtered package."
+ tar -xzf "$package_temporary_dir/jellyfin-${VERSION}/jellyfin.tar.gz" -C "$package_temporary_dir/jellyfin-${VERSION}"
+ echo "Removing filtered package."
+ rm "$package_temporary_dir/jellyfin-${VERSION}/jellyfin.tar.gz"
+ echo "Repackaging package into final tarball."
+ tar -zcf "$pkg_src_dir/jellyfin-${VERSION}.tar.gz" -C "$package_temporary_dir" "jellyfin-${VERSION}"
+fi
+
+docker build ../.. -t "$image_name" -f ./Dockerfile
+mkdir -p "$output_dir"
+docker run --rm -v "$package_temporary_dir:/temp" "$image_name" sh -c 'find /build/rpmbuild -maxdepth 3 -type f -name "jellyfin*.rpm" -exec mv {} /temp \;'
+chown -R "$current_user" "$package_temporary_dir" \
+|| sudo chown -R "$current_user" "$package_temporary_dir"
+mv "$package_temporary_dir"/*.rpm "$output_dir"
diff --git a/deployment/fedora-package-x64/pkg-src/.gitignore b/deployment/fedora-package-x64/pkg-src/.gitignore
new file mode 100644
index 0000000000..6019b98c22
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/.gitignore
@@ -0,0 +1,3 @@
+*.rpm
+*.zip
+*.tar.gz
\ No newline at end of file
diff --git a/deployment/fedora-package-x64/pkg-src/README.md b/deployment/fedora-package-x64/pkg-src/README.md
new file mode 100644
index 0000000000..7ed6f7efc6
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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/deployment/fedora-package-x64/pkg-src/jellyfin-firewalld.xml b/deployment/fedora-package-x64/pkg-src/jellyfin-firewalld.xml
new file mode 100644
index 0000000000..062db370da
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/jellyfin-firewalld.xml
@@ -0,0 +1,9 @@
+
+
+ Jellyfin
+ The Free Software Media System.
+
+
+
+
+
\ No newline at end of file
diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.env b/deployment/fedora-package-x64/pkg-src/jellyfin.env
new file mode 100644
index 0000000000..827a33f468
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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/deployment/fedora-package-x64/pkg-src/jellyfin.override.conf b/deployment/fedora-package-x64/pkg-src/jellyfin.override.conf
new file mode 100644
index 0000000000..8652450bb4
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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/deployment/fedora-package-x64/pkg-src/jellyfin.service b/deployment/fedora-package-x64/pkg-src/jellyfin.service
new file mode 100644
index 0000000000..0ece5b57f4
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec
new file mode 100644
index 0000000000..acab6b13bd
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec
@@ -0,0 +1,139 @@
+%global debug_package %{nil}
+# jellyfin tag to package
+%global gittag v10.0.1
+# 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})
+
+AutoReq: no
+Name: jellyfin
+Version: 10.0.1
+Release: 1%{?dist}
+Summary: The Free Software Media Browser
+License: GPLv2
+URL: https://jellyfin.media
+Source0: %{name}-%{version}.tar.gz
+Source1: jellyfin.service
+Source2: jellyfin.env
+Source3: jellyfin.sudoers
+Source4: restart.sh
+Source5: jellyfin.override.conf
+Source6: 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}
+
+%build
+
+%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 fedora-x64 Jellyfin.Server
+%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/%{name}/LICENSE
+%{__install} -D -m 0644 %{SOURCE5} %{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 %{SOURCE6} %{buildroot}%{_prefix}/lib/firewalld/service/%{name}.xml
+
+%files
+%{_libdir}/%{name}/jellyfin-web/*
+%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/deployment/fedora-package-x64/pkg-src/jellyfin.sudoers b/deployment/fedora-package-x64/pkg-src/jellyfin.sudoers
new file mode 100644
index 0000000000..b31d52f7ec
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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/deployment/fedora-package-x64/pkg-src/restart.sh b/deployment/fedora-package-x64/pkg-src/restart.sh
new file mode 100644
index 0000000000..e84dca587f
--- /dev/null
+++ b/deployment/fedora-package-x64/pkg-src/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
diff --git a/deployment/framework/build.sh b/deployment/framework/build.sh
new file mode 100755
index 0000000000..4f2e6363ee
--- /dev/null
+++ b/deployment/framework/build.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+#Magic word framework will create a non self contained build
+build_jellyfin ../../Jellyfin.Server Release framework `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/framework/clean.sh b/deployment/framework/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/framework/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/framework/package.sh b/deployment/framework/package.sh
new file mode 100755
index 0000000000..13b943ea8f
--- /dev/null
+++ b/deployment/framework/package.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/linux-x64/build.sh b/deployment/linux-x64/build.sh
new file mode 100755
index 0000000000..1f0fb62d36
--- /dev/null
+++ b/deployment/linux-x64/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release linux-x64 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/linux-x64/clean.sh b/deployment/linux-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/linux-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/linux-x64/package.sh b/deployment/linux-x64/package.sh
new file mode 100755
index 0000000000..13b943ea8f
--- /dev/null
+++ b/deployment/linux-x64/package.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/make.sh b/deployment/make.sh
new file mode 100755
index 0000000000..6b8d8de083
--- /dev/null
+++ b/deployment/make.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+git submodule update --init --recursive
+
+pushd ../Jellyfin.Versioning
+./update-version
+popd
+
+#TODO enabled proper flag parsing for enabling and disabling building, signing, packaging and publishing
+
+# Execute all build.sh, package.sh, sign.sh and publish.sh scripts in every folder. In that order. Script should check for artifacts themselves.
+echo "Running for platforms '$@'."
+for directory in */ ; do
+ platform=`basename "${directory}"`
+ if [[ $@ == *"$platform"* || $@ = *"all"* ]]; then
+ echo "Processing ${platform}"
+ pushd "$platform"
+ if [ -f build.sh ]; then
+ ./build.sh
+ fi
+ if [ -f package.sh ]; then
+ ./package.sh
+ fi
+ if [ -f sign.sh ]; then
+ ./sign.sh
+ fi
+ if [ -f publish.sh ]; then
+ ./publish.sh
+ fi
+ popd
+ else
+ echo "Skipping $platform."
+ fi
+done
diff --git a/deployment/osx-x64/build.sh b/deployment/osx-x64/build.sh
new file mode 100755
index 0000000000..d6bfb9f5e3
--- /dev/null
+++ b/deployment/osx-x64/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release osx-x64 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/osx-x64/clean.sh b/deployment/osx-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/osx-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/osx-x64/package.sh b/deployment/osx-x64/package.sh
new file mode 100755
index 0000000000..13b943ea8f
--- /dev/null
+++ b/deployment/osx-x64/package.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/ubuntu-x64/build.sh b/deployment/ubuntu-x64/build.sh
new file mode 100755
index 0000000000..870bac7805
--- /dev/null
+++ b/deployment/ubuntu-x64/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release ubuntu-x64 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/ubuntu-x64/clean.sh b/deployment/ubuntu-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/ubuntu-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/ubuntu-x64/package.sh b/deployment/ubuntu-x64/package.sh
new file mode 100755
index 0000000000..13b943ea8f
--- /dev/null
+++ b/deployment/ubuntu-x64/package.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/unraid/docker-templates/README.md b/deployment/unraid/docker-templates/README.md
new file mode 100644
index 0000000000..2c268e8b3e
--- /dev/null
+++ b/deployment/unraid/docker-templates/README.md
@@ -0,0 +1,15 @@
+# docker-templates
+
+### Installation:
+
+Open unRaid GUI (at least unRaid 6.5)
+
+Click on the Docker tab
+
+Add the following line under "Template Repositories"
+
+https://github.com/jellyfin/jellyfin/blob/master/deployment/unraid/docker-templates
+
+Click save than click on Add Container and select jellyfin.
+
+Adjust to your paths to your liking and off you go!
diff --git a/deployment/unraid/docker-templates/jellyfin.xml b/deployment/unraid/docker-templates/jellyfin.xml
new file mode 100644
index 0000000000..be11884248
--- /dev/null
+++ b/deployment/unraid/docker-templates/jellyfin.xml
@@ -0,0 +1,51 @@
+
+
+ https://raw.githubusercontent.com/jellyfin/jellyfin/deployment/unraid/docker-templates/jellyfin.xml
+ False
+ MediaApp:Video MediaApp:Music MediaApp:Photos MediaServer:Video MediaServer:Music MediaServer:Photos
+ JellyFin
+
+ JellyFin is The Free Software Media Browser Converted By Community Applications Always verify this template (and values) against the dockerhub support page for the container!![br][br]
+ You can add as many mount points as needed for recordings, movies ,etc. [br][br]
+ [b][span style='color: #E80000;']Directions:[/span][/b][br]
+ [b]/config[/b] : this is where Jellyfin will store it's databases and configuration.[br][br]
+ [b]Port[/b] : This is the default port for Jellyfin. (Will add ssl port later)[br][br]
+ [b]Media[/b] : This is the mounting point of your media. When you access it in Jellyfin it will be /media or whatever you chose for a mount point
+ [b]Tip:[/b] You can add more volume mappings if you wish Jellyfin has access to it.
+
+
+ Jellyfin Server is a home media server built on top of other popular open source technologies such as Service Stack, jQuery, jQuery mobile, and Mono and will remain completely free!
+
+ https://www.reddit.com/r/jellyfin/
+ https://hub.docker.com/r/jellyfin/jellyfin/
+ https://github.com/jellyfin/jellyfin/>
+ jellyfin/jellyfin
+ https://jellyfin.media/
+ true
+ false
+
+ host
+
+
+ 8096
+ 8096
+ tcp
+
+
+
+
+
+ /mnt/cache/appdata/config
+ /config
+ rw
+
+
+ /mnt/user
+ /media
+ rw
+
+
+ http://[IP]:[PORT:8096]/
+ https://raw.githubusercontent.com/binhex/docker-templates/master/binhex/images/emby-icon.png
+
+
diff --git a/build-jellyfin.ps1 b/deployment/win-generic/build-jellyfin.ps1
similarity index 97%
rename from build-jellyfin.ps1
rename to deployment/win-generic/build-jellyfin.ps1
index 2247166211..4f0f925256 100644
--- a/build-jellyfin.ps1
+++ b/deployment/win-generic/build-jellyfin.ps1
@@ -1,110 +1,110 @@
-[CmdletBinding()]
-param(
- [switch]$InstallFFMPEG,
- [switch]$InstallNSSM,
- [switch]$GenerateZip,
- [string]$InstallLocation = "$Env:AppData/Jellyfin-Server/",
- [ValidateSet('Debug','Release')][string]$BuildType = 'Release',
- [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal',
- [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win',
- [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64'
-)
-
-#PowershellCore and *nix check to make determine which temp dir to use.
-if(($PSVersionTable.PSEdition -eq 'Core') -and (-not $IsWindows)){
- $TempDir = mktemp -d
-}else{
- $TempDir = $env:Temp
-}
-
-function Build-JellyFin {
- if(($Architecture -eq 'arm64') -and ($WindowsVersion -ne 'win10')){
- Write-Error "arm64 only supported with Windows10 Version"
- exit
- }
- if(($Architecture -eq 'arm') -and ($WindowsVersion -notin @('win10','win81','win8'))){
- Write-Error "arm only supported with Windows 8 or higher"
- exit
- }
- dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity
-}
-
-function Install-FFMPEG {
- param(
- [string]$InstallLocation,
- [string]$Architecture
- )
- Write-Verbose "Checking Architecture"
- if($Architecture -notin @('x86','x64')){
- Write-Warning "No builds available for your selected architecture of $Architecture"
- Write-Warning "FFMPEG will not be installed"
- }elseif($Architecture -eq 'x64'){
- Write-Verbose "Downloading 64 bit FFMPEG"
- Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
- }else{
- Write-Verbose "Downloading 32 bit FFMPEG"
- Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
- }
-
- Expand-Archive "$tempdir/fmmpeg.zip" -DestinationPath "$tempdir/ffmpeg/" | Write-Verbose
- if($Architecture -eq 'x64'){
- Write-Verbose "Copying Binaries to Jellyfin location"
- Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object {
- Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
- }
- }else{
- Write-Verbose "Copying Binaries to Jellyfin location"
- Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object {
- Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
- }
- }
- Remove-Item "$tempdir/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose
- Remove-Item "$tempdir/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose
-}
-
-function Install-NSSM {
- param(
- [string]$InstallLocation,
- [string]$Architecture
- )
- Write-Verbose "Checking Architecture"
- if($Architecture -notin @('x86','x64')){
- Write-Warning "No builds available for your selected architecture of $Architecture"
- Write-Warning "NSSM will not be installed"
- }else{
- Write-Verbose "Downloading NSSM"
- Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose
- }
-
- Expand-Archive "$tempdir/nssm.zip" -DestinationPath "$tempdir/nssm/" | Write-Verbose
- if($Architecture -eq 'x64'){
- Write-Verbose "Copying Binaries to Jellyfin location"
- Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win64" | ForEach-Object {
- Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
- }
- }else{
- Write-Verbose "Copying Binaries to Jellyfin location"
- Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win32" | ForEach-Object {
- Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
- }
- }
- Remove-Item "$tempdir/nssm/" -Recurse -Force -ErrorAction Continue | Write-Verbose
- Remove-Item "$tempdir/nssm.zip" -Force -ErrorAction Continue | Write-Verbose
-}
-
-Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture"
-Build-JellyFin
-if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){
- Write-Verbose "Starting FFMPEG Install"
- Install-FFMPEG $InstallLocation $Architecture
-}
-if($InstallNSSM.IsPresent -or ($InstallNSSM -eq $true)){
- Write-Verbose "Starting NSSM Install"
- Install-NSSM $InstallLocation $Architecture
-}
-Copy-Item .\install-jellyfin.ps1 $InstallLocation\install-jellyfin.ps1
-Copy-Item .\install.bat $InstallLocation\install.bat
-if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){
- Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force
-}
-Write-Verbose "Finished"
+[CmdletBinding()]
+param(
+ [switch]$InstallFFMPEG,
+ [switch]$InstallNSSM,
+ [switch]$GenerateZip,
+ [string]$InstallLocation = "$Env:AppData/Jellyfin-Server/",
+ [ValidateSet('Debug','Release')][string]$BuildType = 'Release',
+ [ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal',
+ [ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win',
+ [ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64'
+)
+
+#PowershellCore and *nix check to make determine which temp dir to use.
+if(($PSVersionTable.PSEdition -eq 'Core') -and (-not $IsWindows)){
+ $TempDir = mktemp -d
+}else{
+ $TempDir = $env:Temp
+}
+
+function Build-JellyFin {
+ if(($Architecture -eq 'arm64') -and ($WindowsVersion -ne 'win10')){
+ Write-Error "arm64 only supported with Windows10 Version"
+ exit
+ }
+ if(($Architecture -eq 'arm') -and ($WindowsVersion -notin @('win10','win81','win8'))){
+ Write-Error "arm only supported with Windows 8 or higher"
+ exit
+ }
+ dotnet publish -c $BuildType -r "$windowsversion-$Architecture" MediaBrowser.sln -o $InstallLocation -v $DotNetVerbosity
+}
+
+function Install-FFMPEG {
+ param(
+ [string]$InstallLocation,
+ [string]$Architecture
+ )
+ Write-Verbose "Checking Architecture"
+ if($Architecture -notin @('x86','x64')){
+ Write-Warning "No builds available for your selected architecture of $Architecture"
+ Write-Warning "FFMPEG will not be installed"
+ }elseif($Architecture -eq 'x64'){
+ Write-Verbose "Downloading 64 bit FFMPEG"
+ Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1-win64-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
+ }else{
+ Write-Verbose "Downloading 32 bit FFMPEG"
+ Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1-win32-static.zip -UseBasicParsing -OutFile "$tempdir/fmmpeg.zip" | Write-Verbose
+ }
+
+ Expand-Archive "$tempdir/fmmpeg.zip" -DestinationPath "$tempdir/ffmpeg/" | Write-Verbose
+ if($Architecture -eq 'x64'){
+ Write-Verbose "Copying Binaries to Jellyfin location"
+ Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win64-static/bin" | ForEach-Object {
+ Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+ }
+ }else{
+ Write-Verbose "Copying Binaries to Jellyfin location"
+ Get-ChildItem "$tempdir/ffmpeg/ffmpeg-4.1-win32-static/bin" | ForEach-Object {
+ Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+ }
+ }
+ Remove-Item "$tempdir/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose
+ Remove-Item "$tempdir/fmmpeg.zip" -Force -ErrorAction Continue | Write-Verbose
+}
+
+function Install-NSSM {
+ param(
+ [string]$InstallLocation,
+ [string]$Architecture
+ )
+ Write-Verbose "Checking Architecture"
+ if($Architecture -notin @('x86','x64')){
+ Write-Warning "No builds available for your selected architecture of $Architecture"
+ Write-Warning "NSSM will not be installed"
+ }else{
+ Write-Verbose "Downloading NSSM"
+ Invoke-WebRequest -Uri https://nssm.cc/ci/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose
+ }
+
+ Expand-Archive "$tempdir/nssm.zip" -DestinationPath "$tempdir/nssm/" | Write-Verbose
+ if($Architecture -eq 'x64'){
+ Write-Verbose "Copying Binaries to Jellyfin location"
+ Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win64" | ForEach-Object {
+ Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+ }
+ }else{
+ Write-Verbose "Copying Binaries to Jellyfin location"
+ Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win32" | ForEach-Object {
+ Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
+ }
+ }
+ Remove-Item "$tempdir/nssm/" -Recurse -Force -ErrorAction Continue | Write-Verbose
+ Remove-Item "$tempdir/nssm.zip" -Force -ErrorAction Continue | Write-Verbose
+}
+
+Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture"
+Build-JellyFin
+if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){
+ Write-Verbose "Starting FFMPEG Install"
+ Install-FFMPEG $InstallLocation $Architecture
+}
+if($InstallNSSM.IsPresent -or ($InstallNSSM -eq $true)){
+ Write-Verbose "Starting NSSM Install"
+ Install-NSSM $InstallLocation $Architecture
+}
+Copy-Item .\install-jellyfin.ps1 $InstallLocation\install-jellyfin.ps1
+Copy-Item .\install.bat $InstallLocation\install.bat
+if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){
+ Compress-Archive -Path $InstallLocation -DestinationPath "$InstallLocation/jellyfin.zip" -Force
+}
+Write-Verbose "Finished"
diff --git a/install-jellyfin.ps1 b/deployment/win-generic/install-jellyfin.ps1
similarity index 100%
rename from install-jellyfin.ps1
rename to deployment/win-generic/install-jellyfin.ps1
diff --git a/install.bat b/deployment/win-generic/install.bat
similarity index 100%
rename from install.bat
rename to deployment/win-generic/install.bat
diff --git a/deployment/win-x64/build.sh b/deployment/win-x64/build.sh
new file mode 100755
index 0000000000..0b30462038
--- /dev/null
+++ b/deployment/win-x64/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release win-x64 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/win-x64/clean.sh b/deployment/win-x64/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/win-x64/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/win-x64/package.sh b/deployment/win-x64/package.sh
new file mode 100755
index 0000000000..e8410e8c23
--- /dev/null
+++ b/deployment/win-x64/package.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
+
+#TODO setup and maybe change above code to produce the Windows native zip format.
diff --git a/deployment/win-x86/build.sh b/deployment/win-x86/build.sh
new file mode 100755
index 0000000000..610db356a5
--- /dev/null
+++ b/deployment/win-x86/build.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+build_jellyfin ../../Jellyfin.Server Release win-x86 `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/win-x86/clean.sh b/deployment/win-x86/clean.sh
new file mode 100755
index 0000000000..3df2d7796e
--- /dev/null
+++ b/deployment/win-x86/clean.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+clean_jellyfin ../.. Release `pwd`/dist/jellyfin_${VERSION}
diff --git a/deployment/win-x86/package.sh b/deployment/win-x86/package.sh
new file mode 100755
index 0000000000..e8410e8c23
--- /dev/null
+++ b/deployment/win-x86/package.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+source ../common.build.sh
+
+VERSION=`get_version ../..`
+
+package_portable ../.. `pwd`/dist/jellyfin_${VERSION}
+
+#TODO setup and maybe change above code to produce the Windows native zip format.