Closed agittins closed 12 months ago
Thank you for the detailed report. I think we can fix it by adding using some args and changing ownership of these files in our container (they are currently just built with the container root user).
I am not a docker expert, but I'm pretty sure that can be done. We do something similar in other images (https://github.com/LizardByte/Sunshine/blob/cea9f152d8a73aca2fcef30205afc8fb3389a258/docker/ubuntu-22.04.dockerfile#L148-L171). I think it could be a simpler version of that. Can you share your docker compose configuration (strip anything sensitive)?
Also, just putting this here for my own reference: https://docs.linuxserver.io/images/docker-jellyfin#environment-variables-e
This is the relevant parts of my docker-compose.yaml
. The media shares etc are all owned by uid/gid 1000:1000
.
I think with the docker-mods the actual docker image is built by your github workflow pipeline, and what gets downloaded by the docker client is a pre-built layer that gets laid on top. This means (I think) that anything put into Dockerfile
here will happen at the build/release stage and not happen on the user's machine.
During startup, the linuxserverio containers use s6 init scripts to set the ownership of files to match whatever the system is running as (it looks like they always map the user:group abc:abc
to the uid/gid). They have an alias they install called lsiown
for doing this.
I suspect the right way (but perhaps not the only way) to do it is to create an s6 script to run lsiown abc:abc /config
at some point during startup. They describe how to set up init scripts for dockermods here - I don't know s6 but it looks fairly straightforward (famous last words!).
Oddly I am finding that my install isn't actually downloading any mp3's, even though the logs say it worked and it creates the themerr.json file. I wonder if the version of YoutubeExploder needs bumping?
---
version: '3.4'
services:
# <-- other stuff like caddy etc --> #
jellyfin:
image: linuxserver/jellyfin
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=Australia/Sydney
- UMASK_SET=022
- JELLYFIN_PublishedServerUrl=https://redacted.example.com/
- DOCKER_MODS=lizardbyte/themerr-jellyfin:latest
volumes:
- /etc/localtime:/etc/localtime:ro
- ./jellyfin-config:/config
- /shared/media/tvshows:/data/tvshows
- /shared/media/movies:/data/movies
- /shared/media/music:/data/music
- /shared/media/operas:/data/operas
- /shared/media/books:/data/books
ports:
- 8096:8096
#- 8920:8920 #HTTPS port (we proxy via caddy instead)
- 7359:7359/udp #optional - discovery
- 1900:1900/udp #optional - dlna discovery
This means (I think) that anything put into Dockerfile here will happen at the build/release stage and not happen on the user's machine.
Now that I think about it, I think you're right. I'm going to make an attempt at setting up the s6 init script. It doesn't seem that complex from the example you shared. I'll let you know when I have the PR up if you'd want to give it a review.
@agittins This was easier than I thought it would be. Would you mind looking over my PR? I don't normally ask the people who open an issue to do so, but you seem to have a pretty good grasp of this issue.
That was quick! π I'm only on my phone but I've done a review and I think the approach looks good.
This issue has been fixed and will be available in the next release.
@agittins Thanks for the review. It was a pretty simple change all things considered. I'll need to remember this in the future if there's actually anything architecture specific in our build as the docker mod doesn't actually try to pull the architecture that matches the base image.
Anyway, this is merged into nightly and available on docker hub and ghcr. Do you mind trying with the :nightly
tag?
Ok, that's interesting! I stopped the container, removed the /config/data/plugins/Themerr
folder and applied the :nightly
tag to my config.
When it started up it gave me:
jellyfin_1 | [00:09:13] [ERR] [1] Emby.Server.Implementations.Plugins.PluginManager: Error creating Jellyfin.Plugin.Themerr.Plugin
jellyfin_1 | System.UnauthorizedAccessException: Access to the path '/config/data/plugins/themerr-jellyfin/meta.json' is denied.
jellyfin_1 | ---> System.IO.IOException: Permission denied
which again caused jellyfin to continually restart.
Two things of note - the plugin config path is indeed now themerr-jellyfin
per your original PR, while my previous installation was definitely at ..plugins/Themerr
not ..plugins/themerr-jellyfin
. (I see now that I was using what was in the main branch, while the nightly branch has a new path per your PR). The other thing is that the files are owned by root:root
instead of uid/gid 1000:
root@dockerhost:/srv/docker# ls -alFn jellyfin-config/data/plugins/themerr-jellyfin/
total 336
drwxr-xr-x 2 0 0 4096 Aug 26 00:08 ./
drwxr-xr-x 17 1000 1000 4096 Aug 26 00:08 ../
-rw-r--r-- 1 0 0 20992 Aug 26 00:08 Jellyfin.Plugin.Themerr.dll
-rw-r--r-- 1 0 0 294400 Aug 26 00:08 YoutubeExplode.dll
-rw-r--r-- 1 0 0 480 Aug 26 00:08 meta.json
-rw-r--r-- 1 0 0 8281 Aug 26 00:08 themerr-jellyfin.png
So it seems the s6 script isn't running. Maybe adding some echo statements to get some output in the logs might help to diagnose, but I suspect it's probably a naming issue (run.sh vs run?), file mode (maybe the init files need to be +x) and also taking a look at the /docker-mods
script that is in the root of the jellyfin image might give some hints. Oh, also possible that the way s6 works you might need to nudge a dependency somewhere in there to ensure the init gets called, but I don't know.
The good news though is that once I manually fixed the permissions the actual downloads worked for me :-)
Happy to give it another shot once you've got a tested nightly. ππΌ
I wanted to use run.sh
so my IDE would know that it's a shell script and run shell check against it. I will try again by adding a run
file that calls the run.sh
.
Unfortunately I don't think there is a way to use a local image for a docker mod (at least not that I'm aware of)... so I have to merge it before it can actually be tested.
Although, I was under the impression it could be named something else, as the name is defined in the up
file.
Can you confirm the location is in /etc/s6=overlay/s6-rc.d/init-mod-universal-themerr-jellyfin
?
And did you not get this output?
Initializing Themerr-jellyfin, as a mod for Linuxserver.io Jellyfin container
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β Themerr-jellyfin, a LizardByte application β
β β
β Docs: https://docs.lizardbyte.dev/projects/themerr-jellyfin β
β Support center: https://app.lizardbyte.dev/#Support β
β Donate: https://app.lizardbyte.dev/#Donate β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Put up another PR. This time I think it will work. I previously forgot to chmod +x
the run script. That was probably the only issue with it... but also made a few other tweaks, such as.
run.sh
to run
(looks like my IDE still knows it's a shell script)init-mod-jellyfin-themerr
(I believe the universal meant it should apply to any Linuxserver.io image, where jellyfin means it would apply to just Jellyfin)@agittins Do you mind trying nightly again?
Have you been able to replicate the issue on your end, and verify that it's fixed?
I am still getting the exact same issue.
What happens on your system when you test your changes?
Logs from run just now:
root@dockerhost:/srv/docker# rm -rf jellyfin-config/data/plugins/themerr-jellyfin/
root@dockerhost:/srv/docker# dc up jellyfin
Starting docker_jellyfin_1 ... done
Attaching to docker_jellyfin_1
jellyfin_1 | [mod-init] Attempting to run Docker Modification Logic
jellyfin_1 | [mod-init] Applying lizardbyte/themerr-jellyfin:nightly files to container
jellyfin_1 | [mod-init] lizardbyte/themerr-jellyfin:nightly applied to container
jellyfin_1 | [migrations] started
jellyfin_1 | [migrations] no migrations found
jellyfin_1 | usermod: no changes
jellyfin_1 | βββββββββββββββββββββββββββββββββββββββ
jellyfin_1 |
jellyfin_1 | βββ βββββββββββ βββββββ
jellyfin_1 | βββ ββββββββββββββββββββ
jellyfin_1 | βββ ββββββββββββββ βββ
jellyfin_1 | βββ ββββββββββββββ βββ
jellyfin_1 | ββββββββββββββββββββββββββββ
jellyfin_1 | βββββββββββββββββββ βββββββ
jellyfin_1 |
jellyfin_1 | Brought to you by linuxserver.io
jellyfin_1 | βββββββββββββββββββββββββββββββββββββββ
jellyfin_1 |
jellyfin_1 | To support the app dev(s) visit:
jellyfin_1 | Jellyfin: https://opencollective.com/jellyfin
jellyfin_1 |
jellyfin_1 | To support LSIO projects visit:
jellyfin_1 | https://www.linuxserver.io/donate/
jellyfin_1 |
jellyfin_1 | βββββββββββββββββββββββββββββββββββββββ
jellyfin_1 | GID/UID
jellyfin_1 | βββββββββββββββββββββββββββββββββββββββ
jellyfin_1 |
jellyfin_1 | User UID: 1000
jellyfin_1 | User GID: 1000
jellyfin_1 | βββββββββββββββββββββββββββββββββββββββ
jellyfin_1 |
jellyfin_1 | [custom-init] No custom files found, skipping...
jellyfin_1 | [02:10:38] [INF] [1] Main: Jellyfin version: 10.8.10
jellyfin_1 | [02:10:38] [INF] [1] Main: Environment Variables: ["[JELLYFIN_DATA_DIR, /config/data]", "[JELLYFIN_PublishedServerUrl, https://media.example.com/]", "[JELLYFIN_CONFIG_DIR, /config]", "[JELLYFIN_WEB_DIR, /usr/share/jellyfin/web]", "[JELLYFIN_CACHE_DIR, /config/cache]", "[JELLYFIN_LOG_DIR, /config/log]"]
jellyfin_1 | [02:10:38] [INF] [1] Main: Arguments: ["/usr/lib/jellyfin/bin/jellyfin.dll", "--ffmpeg=/usr/lib/jellyfin-ffmpeg/ffmpeg"]
jellyfin_1 | [02:10:38] [INF] [1] Main: Operating system: Linux
jellyfin_1 | [02:10:38] [INF] [1] Main: Architecture: X64
jellyfin_1 | [02:10:38] [INF] [1] Main: 64-Bit Process: True
jellyfin_1 | [02:10:38] [INF] [1] Main: User Interactive: True
jellyfin_1 | [02:10:38] [INF] [1] Main: Processor count: 32
jellyfin_1 | [02:10:38] [INF] [1] Main: Program data path: /config/data
jellyfin_1 | [02:10:38] [INF] [1] Main: Web resources path: /usr/share/jellyfin/web
jellyfin_1 | [02:10:38] [INF] [1] Main: Application directory: /usr/lib/jellyfin/bin/
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.AppBase.BaseConfigurationManager: Setting cache path: /config/cache
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.ApplicationHost: Loading assemblies
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Bookshelf, Version=9.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/Bookshelf_9.0.0.0/Jellyfin.Plugin.Bookshelf.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.CoverArtArchive, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/Cover Art Archive_7.0.0.0/Jellyfin.Plugin.CoverArtArchive.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly MetaBrainz.Common.Json, Version=5.0.0.0, Culture=neutral, PublicKeyToken=be12cbb629c03021 from /config/data/plugins/Cover Art Archive_7.0.0.0/MetaBrainz.Common.Json.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly MetaBrainz.MusicBrainz.CoverArt, Version=4.0.0.0, Culture=neutral, PublicKeyToken=be12cbb629c03021 from /config/data/plugins/Cover Art Archive_7.0.0.0/MetaBrainz.MusicBrainz.CoverArt.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Fanart, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/Fanart_10.0.0.0/Jellyfin.Plugin.Fanart.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Opds, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/OPDS_4.0.0.0/Jellyfin.Plugin.Opds.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.OpenSubtitles, Version=19.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/Open Subtitles_19.0.0.0/Jellyfin.Plugin.OpenSubtitles.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Themerr, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/themerr-jellyfin/Jellyfin.Plugin.Themerr.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly YoutubeExplode, Version=6.3.2.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/themerr-jellyfin/YoutubeExplode.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Tvdb, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/TheTVDB_10.0.0.0/Jellyfin.Plugin.Tvdb.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly TvDbSharper, Version=3.2.2.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/TheTVDB_10.0.0.0/TvDbSharper.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.TMDbBoxSets, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/TMDb Box Sets_10.0.0.0/Jellyfin.Plugin.TMDbBoxSets.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Handlebars, Version=2.1.0.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661 from /config/data/plugins/Webhook_11.0.0.0/Handlebars.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly MailKit, Version=3.1.0.0, Culture=neutral, PublicKeyToken=4e064fe7c44a8f1b from /config/data/plugins/Webhook_11.0.0.0/MailKit.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly Jellyfin.Plugin.Webhook, Version=11.0.0.0, Culture=neutral, PublicKeyToken=null from /config/data/plugins/Webhook_11.0.0.0/Jellyfin.Plugin.Webhook.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly BouncyCastle.Crypto, Version=1.9.0.0, Culture=neutral, PublicKeyToken=0e99375e54769942 from /config/data/plugins/Webhook_11.0.0.0/BouncyCastle.Crypto.dll
jellyfin_1 | [02:10:39] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded assembly MimeKit, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bede1c8a46c66814 from /config/data/plugins/Webhook_11.0.0.0/MimeKit.dll
jellyfin_1 | [02:10:39] [INF] [1] Jellyfin.Networking.Manager.NetworkManager: Defined LAN addresses : [192.168.0.0/16,10.0.0.0/8]
jellyfin_1 | [02:10:39] [INF] [1] Jellyfin.Networking.Manager.NetworkManager: Defined LAN exclusions : []
jellyfin_1 | [02:10:39] [INF] [1] Jellyfin.Networking.Manager.NetworkManager: Using LAN addresses: [192.168.0.0/16,10.0.0.0/8]
jellyfin_1 | [02:10:39] [INF] [1] Jellyfin.Networking.Manager.NetworkManager: Using bind addresses: []
jellyfin_1 | [02:10:39] [INF] [1] Jellyfin.Networking.Manager.NetworkManager: Using bind exclusions: []
jellyfin_1 | [02:10:52] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: Bookshelf 9.0.0.0
jellyfin_1 | [02:10:52] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: Cover Art Archive 7.0.0.0
jellyfin_1 | [02:10:52] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: Fanart 10.0.0.0
jellyfin_1 | [02:10:52] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: OPDS Feed 4.0.0.0
jellyfin_1 | [02:10:52] [INF] [1] Emby.Server.Implementations.Plugins.PluginManager: Loaded plugin: Open Subtitles 19.0.0.0
jellyfin_1 | [02:10:52] [ERR] [1] Emby.Server.Implementations.Plugins.PluginManager: Error creating Jellyfin.Plugin.Themerr.Plugin
jellyfin_1 | System.UnauthorizedAccessException: Access to the path '/config/data/plugins/themerr-jellyfin/meta.json' is denied.
jellyfin_1 | ---> System.IO.IOException: Permission denied
jellyfin_1 | --- End of inner exception stack trace ---
jellyfin_1 | at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
jellyfin_1 | at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String path, OpenFlags flags, Int32 mode)
jellyfin_1 | at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
jellyfin_1 | at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
jellyfin_1 | at System.IO.Strategies.FileStreamHelpers.ChooseStrategy(FileStream fileStream, String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, Int64 preallocationSize)
The problem is that I don't think the mods accept local docker images... Maybe I'm wrong but I'm pretty sure I tried before with a Plex mod.
Not sure what the problem could be though. Doesn't seem to be printing anything from that run file.
I believe I found the issue. I have pushed the change and test... and I think I will open an issue with the docker mod repo, as I believe there should be the ability to test local images to avoid this situation.
It also did not resolve the issue.
Trying to make sense of this, whatever this s6 system is, is just not logical at all. But I think I have it now.
Template:
Themerr-jellyfin in #77
Still not working. It doesn't appear the s6 init files are added to the image, I don't understand why. The directory is copied to the final stage, the same stage where the plugin files are.
Not sure what else to try.
Made a little progress, there's still an issue though.
2023-08-29 14:51:26 [mod-init] Attempting to run Docker Modification Logic
2023-08-29 14:51:26 [mod-init] Adding lizardbyte/themerr-jellyfin:nightly to container
2023-08-29 14:51:27 [mod-init] Downloading lizardbyte/themerr-jellyfin:nightly from registry-1.docker.io
2023-08-29 14:51:28 [mod-init] Installing lizardbyte/themerr-jellyfin:nightly
2023-08-29 14:51:28 [mod-init] lizardbyte/themerr-jellyfin:nightly applied to container
2023-08-29 14:51:28 s6-rc-compile: fatal: invalid /etc/s6-overlay/s6-rc.d/init-mod-jellyfin-themerr-config/type: must be oneshot, longrun, or bundle
It's already a oneshot
so not sure what might be wrong. I will await a response in the docker mod issue.
Okay, good news... the s6 init logic is working.
But the bad news... There is a new directory that claims it doesn't have correct permissions. In my opinion this should be handled by the Jellyfin image, and I have submitted a PR to fix it there.
https://github.com/linuxserver/docker-jellyfin/pull/214
If they accept the PR, then I believe this issue will be fully resolved. If they do not accept the PR, I will add the fix here.
@agittins do you mind testing this again with latest jellyfin image and our nightly image?
They have merged my fix https://github.com/linuxserver/docker-jellyfin/pull/214
If not, I'll try to get to it soon.
I am no longer getting the permissions error on the jellyfin plugin config directory now. I will publish a new release soon.
Latest release file?
@rohitghali for docker you can use nightly
tag instead of latest
Describe the Bug
TLDR: The DOCKER_MOD installs the config dir and files with root ownership instead of the user that jellyfin runs as, causing jellyfin to crash on startup.
I have jellyfin running in a docker container on linux which has been working well for some time. I'm using the linuxserver/jellyfin image, along with their recommended
PUID
andPGUID
options set to1000
, andUMASK_SET
of022
.Following the install docs, I added
DOCKER_MODS=lizardbyte/themerr-jellyfin:latest
to the environment variables in mydocker-compose.yaml
and issued adocker-compose up -d
.Examining the jellyfin logs reveals that the server repeatedly crashes due to an exception in the Themerr plugin with
System.UnauthorizedAccessException: Access to the path '/config/data/plugins/Themerr/meta.json' is denied.
I noticed that the directory
/config/data/plugins/Themerr
and its files are all owned byroot
instead of the UID configured for the container, hence why the plugin is unable to access them once it starts up in jellyfin.I manually chmod'd the files and everything fired up OK.
From looking at the linuxserver s6 init scripts I am guessing the fix would be to place an init script so that s6 changes ownership to the
abc
user on startup. Their own docker-mods docs don't seem to cover this situation, but maybe some other docker-mods out there have a simple solution.It's likely this only happens if the mod is installed after jellyfin has already been initialised previously.
Expected Behavior
The jellyfin server should start and begin answering network requests instead of crashing.
Additional Context
Complete cycle from the logfile - this pattern repeats as docker restarts the container: