├── .gitignore ├── .env.default ├── scripts ├── package-app.sh ├── install-app.sh └── extract-cert.sh ├── install-jellyfin.sh ├── cert └── Dockerfile ├── README.md └── Dockerfile /.gitignore: -------------------------------------------------------------------------------- 1 | *.p12 2 | -------------------------------------------------------------------------------- /.env.default: -------------------------------------------------------------------------------- 1 | CERT_ALIAS=Jellyfin 2 | CERT_PASSWORD=1234 3 | CERT_COUNTRY=PL 4 | CERT_NAME=Jellyfin 5 | CERT_FILENAME=Jellyfin 6 | 7 | JELLYFIN_BRANCH=release-10.9.z 8 | -------------------------------------------------------------------------------- /scripts/package-app.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | set timeout -1 3 | spawn tizen package -t wgt -o . -- .buildResult 4 | expect "Author password: " 5 | send -- "1234\r" 6 | expect "Yes: (Y), No: (N) ?" 7 | send -- "Y\r" 8 | expect eof 9 | -------------------------------------------------------------------------------- /scripts/install-app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | if [ -z "$TV_IP" ] 6 | then 7 | echo "TV_IP environment varaible is empty. Add it or overwrite the container entrypoint." 8 | exit 1 9 | fi 10 | 11 | sdb connect ${TV_IP} 12 | 13 | DEVICE_ID=$(sdb devices | grep ${TV_IP} | awk '{ print $3 }') 14 | 15 | if [ -z "$DEVICE_ID" ] 16 | then 17 | echo "Device ID not found. Perhaps TV_IP is invalid." 18 | exit 1 19 | fi 20 | 21 | tizen install -n Jellyfin.wgt -t ${DEVICE_ID} 22 | -------------------------------------------------------------------------------- /install-jellyfin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ -z "$TV_IP" ]; then 6 | echo "TV_IP variable is required!" 7 | exit 1 8 | fi 9 | 10 | source .env.default 11 | 12 | if [ ! -f "cert/${CERT_FILENAME}.p12" ]; then 13 | echo "Creating new Tizen certificate" 14 | ./scripts/extract-cert.sh 15 | else 16 | echo "Using cert/${CERT_FILENAME}.p12 as Tizen certificate" 17 | fi 18 | 19 | echo "Building docker image" 20 | docker build \ 21 | --build-arg CERT_PASSWORD="$CERT_PASSWORD" \ 22 | --build-arg CERT_NAME="$CERT_NAME" \ 23 | --build-arg CERT_FILENAME="$CERT_FILENAME" \ 24 | --build-arg JELLYFIN_BRANCH="$JELLYFIN_BRANCH" \ 25 | -t jellyfin-tizen-installer . 26 | 27 | echo "Installing Jellyfin" 28 | docker run --rm --env TV_IP="$TV_IP" jellyfin-tizen-installer 29 | 30 | -------------------------------------------------------------------------------- /scripts/extract-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | source .env.default 6 | 7 | if [ -f "cert/${CERT_FILENAME}.p12" ]; then 8 | read -rp "Certificate file will be overwritten. Do you want to proceed? (y/n) " yn 9 | case $yn in 10 | y ) echo Continuing...;; 11 | n ) echo Exiting...; 12 | exit;; 13 | * ) echo Invalid choice; 14 | exit 1;; 15 | esac 16 | fi 17 | 18 | echo "Building docker image for certificate" 19 | docker build \ 20 | --build-arg CERT_ALIAS="$CERT_ALIAS" \ 21 | --build-arg CERT_PASSWORD="$CERT_PASSWORD" \ 22 | --build-arg CERT_COUNTRY="$CERT_COUNTRY" \ 23 | --build-arg CERT_NAME="$CERT_NAME" \ 24 | --build-arg CERT_FILENAME="$CERT_FILENAME" \ 25 | -t tizen-cert cert 26 | 27 | echo "Starting docker container" 28 | docker run -dit --rm --name tizen-cert tizen-cert 29 | 30 | echo "Copying certificate file to cert/${CERT_FILENAME}.p12" 31 | docker cp tizen-cert:/home/jellyfin/tizen-studio-data/keystore/author/"$CERT_FILENAME".p12 cert/"$CERT_FILENAME".p12 32 | 33 | echo "Discarding container" 34 | docker stop tizen-cert 35 | -------------------------------------------------------------------------------- /cert/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 as build 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | ENV TZ=Poland 5 | 6 | RUN apt-get update && apt-get upgrade -y && apt-get install -y tzdata && apt-get install -y wget git expect 7 | 8 | # Create user 9 | RUN useradd -m jellyfin -s /bin/bash 10 | USER jellyfin 11 | 12 | # Install tizen-studio 13 | RUN wget https://download.tizen.org/sdk/Installer/tizen-studio_5.5/web-cli_Tizen_Studio_5.5_ubuntu-64.bin -P /home/jellyfin 14 | RUN chmod a+x /home/jellyfin/web-cli_Tizen_Studio_5.5_ubuntu-64.bin 15 | RUN ./home/jellyfin/web-cli_Tizen_Studio_5.5_ubuntu-64.bin --accept-license /home/jellyfin/tizen-studio 16 | ENV PATH=${PATH}:/home/jellyfin/tizen-studio/tools/ide/bin:/home/jellyfin/tizen-studio/tools 17 | 18 | ARG CERT_ALIAS 19 | ARG CERT_PASSWORD 20 | ARG CERT_COUNTRY 21 | ARG CERT_NAME 22 | ARG CERT_FILENAME 23 | 24 | # Create certificates 25 | RUN tizen certificate \ 26 | -a ${CERT_ALIAS} \ 27 | -p ${CERT_PASSWORD} \ 28 | -c ${CERT_COUNTRY} \ 29 | -ct ${CERT_COUNTRY} \ 30 | -n ${CERT_NAME} \ 31 | -f ${CERT_FILENAME} 32 | 33 | CMD [ "/bin/bash" ] 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | Looking for maintainers to take over!! 3 | 4 | # Jellyfin installer for Tizen OS through Docker 5 | Made this single container to build and deploy jellyfin to Samsung TVs. 6 | 7 | ## Credits 8 | Credits go to the following: 9 | - https://github.com/jellyfin/jellyfin-tizen 10 | - https://www.reddit.com/r/jellyfin/comments/s0438d/build_and_deploy_jellyfin_app_to_samsung_tizen/ 11 | 12 | ## Prequisites 13 | - Docker 14 | - Internet connection for the Docker images 15 | 16 | ## How to use 17 | 18 | ### TV preparation 19 | 1. Enable developer mode on the TV (adapted from [official tizen guide](https://developer.samsung.com/tv/develop/getting-started/using-sdk/tv-device)): 20 | - Turn on the TV 21 | - Go to the apps page 22 | - Press `12345` on the remote 23 | - Enable `Developer mode` in the dialog that pops up, and write the IP of the host running docker 24 | - Shut down and restart the TV as instructed by the information screen, re-enter the apps page 25 | - There should be (or could be, depending on the model) a big red text in the top bar saying `Developer mode` 26 | - Keep the TV on 27 | 28 | ### Jellyfin - the easy way 29 | Simply run: 30 | ``` 31 | TV_IP= ./install-jellyfin.sh 32 | ``` 33 | 34 | Example: 35 | ``` 36 | TV_IP=192.168.0.10 ./install-jellyfin.sh 37 | ``` 38 | 39 | ### Jellyfin - the custom way 40 | 41 | 1. Create your custom tizen certificate. In order to change certificate details you may edit the .env.default file. 42 | ``` 43 | ./scripts/extract-cert.sh 44 | ``` 45 | 46 | 2. Build the image providing required build arguments. 47 | ``` 48 | docker build \ 49 | --build-arg CERT_PASSWORD="$CERT_PASSWORD" \ 50 | --build-arg CERT_NAME="$CERT_NAME" \ 51 | --build-arg CERT_FILENAME="$CERT_FILENAME" \ 52 | --build-arg JELLYFIN_BRANCH="$JELLYFIN_BRANCH" \ 53 | -t jellyfin-tizen-installer . 54 | ``` 55 | 3. Deploy the application to the TV: 56 | - Run the container passing IP of the TV as an environment variable 57 | ``` 58 | docker run --rm --env TV_IP= jellyfin-tizen-installer 59 | ``` 60 | - OR run the container overwriting the entrypoint for more control over the installation 61 | ``` 62 | docker run -it --rm --entrypoint "/bin/bash" jellyfin-tizen-installer 63 | ``` 64 | 65 | ### Certificate 66 | 67 | To allow reinstalling the app without removing it first you need to reuse the Tizen certificate. 68 | You may generate your own by running: 69 | 70 | ``` 71 | ./scripts/extract-cert.sh 72 | ``` 73 | 74 | *Note:* you may overwrite default certificate data by amending values in `.env.default`. 75 | 76 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build jellyfin-web 2 | FROM node:20 as jellyfin-web 3 | 4 | ARG JELLYFIN_BRANCH 5 | 6 | RUN git clone -b ${JELLYFIN_BRANCH} https://github.com/jellyfin/jellyfin-web.git /home/jellyfin/jellyfin-web 7 | 8 | WORKDIR /home/jellyfin/jellyfin-web 9 | 10 | RUN SKIP_PREPARE=1 npm ci --no-audit 11 | RUN USE_SYSTEM_FONTS=1 npm run build:production 12 | 13 | # Build jellyfin-tizen 14 | FROM node:18 as jellyfin-tizen 15 | 16 | RUN useradd -m jellyfin -s /bin/bash 17 | USER jellyfin 18 | 19 | RUN git clone https://github.com/jellyfin/jellyfin-tizen.git /home/jellyfin/jellyfin-tizen 20 | 21 | WORKDIR /home/jellyfin/jellyfin-tizen 22 | 23 | COPY --from=jellyfin-web --chown=jellyfin /home/jellyfin/jellyfin-web/dist/ ./dist/ 24 | 25 | ENV JELLYFIN_WEB_DIR=./dist 26 | 27 | RUN npm ci --no-audit 28 | 29 | # Tizen stage 30 | FROM ubuntu:22.04 as build 31 | 32 | ENV DEBIAN_FRONTEND=noninteractive 33 | ENV TZ=Poland 34 | 35 | RUN apt-get update && apt-get upgrade -y && apt-get install -y tzdata && apt-get install -y wget git expect 36 | 37 | # Create user 38 | RUN useradd -m jellyfin -s /bin/bash 39 | USER jellyfin 40 | 41 | # Install tizen-studio 42 | RUN wget https://download.tizen.org/sdk/Installer/tizen-studio_5.5/web-cli_Tizen_Studio_5.5_ubuntu-64.bin -P /home/jellyfin 43 | RUN chmod a+x /home/jellyfin/web-cli_Tizen_Studio_5.5_ubuntu-64.bin 44 | RUN ./home/jellyfin/web-cli_Tizen_Studio_5.5_ubuntu-64.bin --accept-license /home/jellyfin/tizen-studio 45 | ENV PATH=${PATH}:/home/jellyfin/tizen-studio/tools/ide/bin:/home/jellyfin/tizen-studio/tools 46 | 47 | # Copy built app 48 | WORKDIR /home/jellyfin/build 49 | COPY --from=jellyfin-tizen --chown=jellyfin /home/jellyfin/jellyfin-tizen/config.xml ./config.xml 50 | COPY --from=jellyfin-tizen --chown=jellyfin /home/jellyfin/jellyfin-tizen/icon.png ./icon.png 51 | COPY --from=jellyfin-tizen --chown=jellyfin /home/jellyfin/jellyfin-tizen/index.html ./index.html 52 | COPY --from=jellyfin-tizen --chown=jellyfin /home/jellyfin/jellyfin-tizen/tizen.js ./tizen.js 53 | COPY --from=jellyfin-tizen --chown=jellyfin /home/jellyfin/jellyfin-tizen/www/ ./www/ 54 | 55 | ARG CERT_PASSWORD 56 | ARG CERT_FILENAME 57 | ARG CERT_NAME 58 | 59 | # Create certificates 60 | COPY cert/${CERT_FILENAME}.p12 /home/jellyfin/tizen-studio-data/keystore/author/Jellyfin.p12 61 | 62 | # Load profile 63 | RUN tizen security-profiles add -n ${CERT_NAME} -a /home/jellyfin/tizen-studio-data/keystore/author/Jellyfin.p12 -p ${CERT_PASSWORD} 64 | 65 | # Switch passwords 66 | RUN sed -i 's/\/home\/jellyfin\/tizen-studio-data\/keystore\/author\/Jellyfin.pwd//' /home/jellyfin/tizen-studio-data/profile/profiles.xml 67 | RUN sed -i 's/\/home\/jellyfin\/tizen-studio-data\/tools\/certificate-generator\/certificates\/distributor\/tizen-distributor-signer.pwd/tizenpkcs12passfordsigner/' /home/jellyfin/tizen-studio-data/profile/profiles.xml 68 | 69 | # Build Tizen App 70 | RUN tizen build-web 71 | 72 | COPY --chown=jellyfin --chmod=744 ./scripts/package-app.sh ./package-app.sh 73 | COPY --chown=jellyfin --chmod=744 ./scripts/install-app.sh ./install-app.sh 74 | 75 | RUN ./package-app.sh 76 | 77 | ENTRYPOINT [ "./install-app.sh" ] 78 | --------------------------------------------------------------------------------