diff --git a/.github/workflows/BuildImage.yml b/.github/workflows/BuildImage.yml index 518b0d8..30d7365 100644 --- a/.github/workflows/BuildImage.yml +++ b/.github/workflows/BuildImage.yml @@ -4,8 +4,8 @@ on: [push, pull_request, workflow_dispatch] env: ENDPOINT: "linuxserver/mods" #don't modify - BASEIMAGE: "replace_baseimage" #replace - MODNAME: "replace_modname" #replace + BASEIMAGE: "jellyfin" #replace + MODNAME: "rffmpeg" #replace jobs: build: diff --git a/Dockerfile b/Dockerfile index 4ece5e8..24d85e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM scratch -LABEL maintainer="username" +LABEL maintainer="junkman690" # copy local files COPY root/ / diff --git a/Dockerfile.complex b/Dockerfile.complex deleted file mode 100644 index db4598e..0000000 --- a/Dockerfile.complex +++ /dev/null @@ -1,23 +0,0 @@ -## Buildstage ## -FROM ghcr.io/linuxserver/baseimage-alpine:3.12 as buildstage - -RUN \ - echo "**** install packages ****" && \ - apk add --no-cache \ - curl && \ - echo "**** grab rclone ****" && \ - mkdir -p /root-layer && \ - curl -o \ - /root-layer/rclone.deb -L \ - "https://downloads.rclone.org/v1.47.0/rclone-v1.47.0-linux-amd64.deb" - -# copy local files -COPY root/ /root-layer/ - -## Single layer deployed image ## -FROM scratch - -LABEL maintainer="username" - -# Add files from buildstage -COPY --from=buildstage /root-layer/ / diff --git a/README.md b/README.md index 761c799..97ee113 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,86 @@ -# Rsync - Docker mod for openssh-server +# Jellyfin - Docker mod for rffmpeg support with OPTIONAL Wake On LAN (WOL) Support -This mod adds rsync to openssh-server, to be installed/updated during container start. +This mod adds rffmpeg to Linuxserver.io's Jellyfin https://github.com/linuxserver/docker-jellyfin. -In openssh-server docker arguments, set an environment variable `DOCKER_MODS=linuxserver/mods:openssh-server-rsync` +rffmpeg is a remote FFmpeg wrapper used to execute FFmpeg commands on a remote server via SSH. It is most useful in situations involving media servers such as Jellyfin (our reference user), where one might want to perform transcoding actions with FFmpeg on a remote machine or set of machines which can better handle transcoding, take advantage of hardware acceleration, or distribute transcodes across multiple servers for load balancing. -If adding multiple mods, enter them in an array separated by `|`, such as `DOCKER_MODS=linuxserver/mods:openssh-server-rsync|linuxserver/mods:openssh-server-mod2` +See https://github.com/joshuaboniface/rffmpeg for more details about rffmpeg -# Mod creation instructions +In Jellyfin docker arguments, set an environment variable `DOCKER_MODS=linuxserver/mods:jellyfin-rffmpeg` -* Fork the repo, create a new branch based on the branch `template`. -* Edit the `Dockerfile` for the mod. `Dockerfile.complex` is only an example and included for reference; it should be deleted when done. -* Inspect the `root` folder contents. Edit, add and remove as necessary. -* Edit this readme with pertinent info, delete these instructions. -* Finally edit the `.github/workflows/BuildImage.yml`. Customize the build branch, and the vars for `BASEIMAGE` and `MODNAME`. -* Ask the team to create a new branch named `-`. Baseimage should be the name of the image the mod will be applied to. The new branch will be based on the `template` branch. -* Submit PR against the branch created by the team. +If adding multiple mods, enter them in an array separated by `|`, such as `DOCKER_MODS=linuxserver/mods:jellyfin-rffmpeg|linuxserver/mods:jellyfin-mod2` +This mod requires you to update the rffmpeg.yml located in "Your jellyfin config dir"/rffmpeg/rffmpeg.yml with your remote SSH username. You also need to add your authorized SSH file to "Your jellyfin config dir"/rffmpeg/.ssh/id_rsa" -## Tips and tricks +You can specify the remote SSH username and host using ENV, note currently only supports 1 host and doesn't overwrite values other than defaults: +* RFFMPEG_USER= remote SSH username +* RFFMPEG_HOST= remote server name or IP -* To decrease startup times when multiple mods are used, we have consolidated `apt-get update` down to one file. As seen in the [nodejs mod](https://github.com/linuxserver/docker-mods/tree/code-server-nodejs/root/etc/cont-init.d) -* Some images has helpers built in, these images are currently: - * [Openvscode-server](https://github.com/linuxserver/docker-openvscode-server/pull/10/files) - * [Code-server](https://github.com/linuxserver/docker-code-server/pull/95) +You also need to ensure that /cache inside the container is exported on the host so it can be mapped on the remote host. Eg for docker compose. + volumes: + - "Your jellyfin config dir":/config + - "Your jellyfin config dir"/cache:/cache +See https://github.com/joshuaboniface/rffmpeg/blob/master/SETUP.md NFS setup for more details + +EXAMPLE Docker-Compose file with WOL support via API: + +```yaml +--- +version: "2.1" +services: + jellyfin: + image: lscr.io/linuxserver/jellyfin:latest + container_name: jellyfin + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/London + - RFFMPEG_USER=jellyfin + - RFFMPEG_WOL=api + - RFFMPEG_HOST=transcode + - RFFMPEG_HOST_MAC="12:ab:34:cd:ef:56" + - WOL_API=192.168.1.5 #docker host IP + - WOL_API_PORT=8431 + - WOL_WAIT=10 #time transcode host takes to start + volumes: + - /path/to/jellyfin/config:/config + - /path/to/jellyfin/config/cache:/cache + - /path/to/data:/data/ + ports: + - 8096:8096 + - 8920:8920 #optional + - 7359:7359/udp #optional + - 1900:1900/udp #optional + restart: unless-stopped + depends_on: + - wol_api + wol_api: + image: rix1337/docker-wol_api + container_name: wol_api + environment: + - PORT=8431 + network_mode: host + restart: unless-stopped +``` + +If you want to run rffmpeg commands they must be run as ABC inside the container eg: +* To add new host ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg add --weight 1 remotehost ``` +* To view status ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg status ``` +* To test connection ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/ffmpeg -version ``` +* To test connection ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/ffprobe -version ``` +* To view all commands ``` docker exec -it jellyfin s6-setuidgid abc /usr/local/bin/rffmpeg -h ``` + +You then need to set your FFMPEG binary in Jellyfin to: +* /usr/local/bin/ffmpeg - Normal rffmpeg without WOL support +* /usr/local/bin/wol_rffmpeg/ffmpeg - rffmpeg with WOL support + +WOL Support +Native WOL support is available if you are running in host network mode. If not you can use the WOL_API container https://hub.docker.com/r/rix1337/docker-wol_api. Note the image name is rix1337/docker-wol_api + +WOL ENV: +* RFFMPEG_WOL= native or api +* RFFMPEG_HOST= remote host to wake +* RFFMPEG_HOST_MAC= remote host to wake mac enclosed in " " eg "aa:12:34:bb:cc:56" +* WOL_API = IP of docker host +* WOL_API_PORT= port wol_api is running on +* WOL_WAIT= time in seconds to wait for host to wake diff --git a/root/etc/cont-init.d/95-apt-get b/root/etc/cont-init.d/95-apt-get new file mode 100644 index 0000000..5b1a21c --- /dev/null +++ b/root/etc/cont-init.d/95-apt-get @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv bash + +apt-get update diff --git a/root/etc/cont-init.d/98-rffmpeg b/root/etc/cont-init.d/98-rffmpeg new file mode 100644 index 0000000..b3f8db6 --- /dev/null +++ b/root/etc/cont-init.d/98-rffmpeg @@ -0,0 +1,86 @@ +#!/usr/bin/with-contenv bash + +#Install dependancies +apt install -y python3-click python3-yaml openssh-client + +#Grab Config +mkdir -p /etc/rffmpeg +mkdir -p /config/rffmpeg/.ssh +touch /config/rffmpeg/.ssh/id_rsa +chmod 600 /config/rffmpeg/.ssh/id_rsa +if [ -f /config/rffmpeg/rffmpeg.yml ]; then + echo "**** rffmpeg.yml already present ****" + else + echo "**** Grabbing rffmpeg.yml from upstream ****" + curl -L -o /config/rffmpeg/rffmpeg.yml https://raw.githubusercontent.com/joshuaboniface/rffmpeg/master/rffmpeg.yml.sample +fi +ln -s /config/rffmpeg/rffmpeg.yml /etc/rffmpeg/rffmpeg.yml + +#Grab rffmpeg +mkdir -p /usr/local/bin/ +echo "**** Grabbing rffmpeg from upstream ****" +if [ -f /usr/local/bin/rffmpeg ]; then + rm /usr/local/bin/rffmpeg +fi +curl -L -o /usr/local/bin/rffmpeg https://raw.githubusercontent.com/joshuaboniface/rffmpeg/master/rffmpeg +chmod +x /usr/local/bin/rffmpeg +ln -s /usr/local/bin/rffmpeg /usr/local/bin/ffprobe +ln -s /usr/local/bin/rffmpeg /usr/local/bin/ffmpeg + +#WOL Support +if [ $RFFMPEG_WOL = "native" ] +then +echo "**** Adding WOL Support ****" +apt install -y wakeonlan iputils-ping +mkdir -p /usr/local/bin/wol_rffmpeg +curl -L -o /config/rffmpeg/wol https://raw.githubusercontent.com/junkman690/docker-mods/jellyfin-rffmpeg/wol +chmod +x /config/rffmpeg/wol +ln -s /config/rffmpeg/wol /usr/local/bin/wol_rffmpeg/ffmpeg +ln -s /config/rffmpeg/wol /usr/local/bin/wol_rffmpeg/ffprobe +fi + +if [ $RFFMPEG_WOL = "api" ] +then +echo "**** Adding WOL Support ****" +apt install -y iputils-ping +mkdir -p /usr/local/bin/wol_rffmpeg +curl -L -o /config/rffmpeg/wol https://raw.githubusercontent.com/junkman690/docker-mods/jellyfin-rffmpeg/wol +chmod +x /config/rffmpeg/wol +ln -s /config/rffmpeg/wol /usr/local/bin/wol_rffmpeg/ffmpeg +ln -s /config/rffmpeg/wol /usr/local/bin/wol_rffmpeg/ffprobe +fi + +##Update rffmpeg.yml +sed -i 's~#persist: "/run/shm"~persist: "/dev/shm"~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#state: "/var/lib/rffmpeg"~state: "/config/rffmpeg"~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#logfile: "/var/log/jellyfin/rffmpeg.log"~logfile: "/config/rffmpeg/rffmpeg.log"~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#log_to_file: true~log_to_file: true~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#owner: jellyfin~owner: abc~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#group: sudo~group: abc~' /config/rffmpeg/rffmpeg.yml +sed -i 's~#args:~args:~' /config/rffmpeg/rffmpeg.yml +sed -i 's~# - "-i"~ - "-i"~' /config/rffmpeg/rffmpeg.yml +sed -i 's~# - "/var/lib/jellyfin/id_rsa"~ - "/config/rffmpeg/.ssh/id_rsa"~' /config/rffmpeg/rffmpeg.yml +if [ ! -z "$RFFMPEG_USER" ] +then +sed -i "s~#user: jellyfin~user: $RFFMPEG_USER~" /config/rffmpeg/rffmpeg.yml +fi + +#Fix permissions +chown abc:abc -R /config/rffmpeg + +#Initialize database +if [ -f /config/rffmpeg/rffmpeg.db ]; then + echo "**** DB already inialized ****" +else + echo "**** Initialize database ****" + /usr/local/bin/rffmpeg init --yes + #Add host + if [ ! -z "$RFFMPEG_HOST" ] + then + s6-setuidgid abc /usr/local/bin/rffmpeg add --weight 1 $RFFMPEG_HOST + fi +fi + + + +exit 0 diff --git a/root/etc/cont-init.d/98-vpn-config b/root/etc/cont-init.d/98-vpn-config deleted file mode 100644 index a5f9127..0000000 --- a/root/etc/cont-init.d/98-vpn-config +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/with-contenv bash - -# Determine if setup is needed -if [ ! -f /usr/local/lib/python***/dist-packages/sshuttle ] && \ -[ -f /usr/bin/apt ]; then - ## Ubuntu - apt-get update - apt-get install --no-install-recommends -y \ - iptables \ - openssh-client \ - python3 \ - python3-pip - pip3 install sshuttle -fi -if [ ! -f /usr/lib/python***/site-packages/sshuttle ] && \ -[ -f /sbin/apk ]; then - # Alpine - apk add --no-cache \ - iptables \ - openssh \ - py3-pip \ - python3 - pip3 install sshuttle -fi - -chown -R root:root /root -chmod -R 600 /root/.ssh diff --git a/root/etc/services.d/sshvpn/run b/root/etc/services.d/sshvpn/run deleted file mode 100644 index 7d49e79..0000000 --- a/root/etc/services.d/sshvpn/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/with-contenv bash - -sshuttle --dns --remote root@${HOST}:${PORT} 0/0 -x 172.17.0.0/16 diff --git a/wol b/wol new file mode 100644 index 0000000..895fc9d --- /dev/null +++ b/wol @@ -0,0 +1,44 @@ +#!/usr/bin/bash + +mac="${RFFMPEG_HOST_MAC%\"}" +mac="${mac#\"}" + +if [ -z $WOL_WAIT ] +then +WOL_WAIT=30 +fi + +ping -c1 -W1 $RFFMPEG_HOST >/dev/null 2>&1 && host=up || host=down + +if [ $RFFMPEG_WOL == "native" ] && [ ! -z $RFFMPEG_HOST ] && [ ! -z $RFFMPEG_HOST_MAC ] && [ ! -z $WOL_WAIT ] && [ $host == "down" ]; +then + echo WOL enabled + echo "$RFFMPEG_HOST" is down, sending wakeup to "$mac" + wakeonlan $mac + #wakeonlan -i $RFFMPEG_HOST $mac + echo "waiting $WOL_WAIT seconds for $RFFMPEG_HOST to wake" + sleep $WOL_WAIT +fi + +if [ $RFFMPEG_WOL == "api" ] && [ ! -z $RFFMPEG_HOST ] && [ ! -z $RFFMPEG_HOST_MAC ] && [ $host == "down" ] && [ ! -z $WOL_WAIT ] && [ ! -z $WOL_API ] && [ ! -z $WOL_API_PORT ]; +then + echo WOL enabled + echo "$RFFMPEG_HOST" is down, sending wakeup via WOL_API: curl -X POST $WOL_API:$WOL_API_PORT/wol/"$mac" + curl -X POST $WOL_API:$WOL_API_PORT/wol/$mac + echo "waiting $WOL_WAIT seconds for $RFFMPEG_HOST to wake" + sleep $WOL_WAIT +fi + +if [ ${0##*/} == "ffmpeg" ] +then +#echo ${0##*/} +/usr/local/bin/ffmpeg "$@" +fi + +if [ ${0##*/} == "ffprobe" ]; +then +#echo ${0##*/} +/usr/local/bin/ffprobe "$@" +fi + +exit