2025-04-14, 08:21 PM
Hi everybody,
I'm quiet desperate. Let's begin from my configuration. I run a Jellyfin and Caddy istance in docker on a Ubuntu 24.10 machine, no firewall for now, I'm troubleshooting. I will write down my docker compose for reference:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
network_mode: 'host'
group_add:
- "992" #render
- "44" #video
volumes:
- /home/andrea/Docker/jellyfin/config
config
- /home/andrea/Docker/jellyfin/cache
cache
- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/Movies
movies
- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/AnimationMovies
animovies
- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/Cartoons
cartoons
- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/TVShows
tvshows
devices:
- /dev/dri
dev/dri
environment:
- PUID=1000
- GUID=1000
- JELLYFIN_PublishedServerUrl=https://jellyfin.serveroneago.eu/
extra_hosts:
- 'host.docker.internal:host-gateway'
restart: 'unless-stopped'
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- /home/andrea/Docker/Caddy/Caddyfile
etc/caddy/Caddyfile
- /home/andrea/Docker/Caddy/config
config
- /home/andrea/Docker/Caddy/data
data
networks:
caddy_net:
ipv4_address: 172.19.0.10
environment:
- PUID=1000
- GUID=1000
depends_on:
- hetzner-ddns
Hetzner ddns is what I use to update my dynamic ip to hetnzer via API. I gave caddy a static ip in its bridge network for some troubleshooting but I could remove that without any change. I will paste here my caddy file:
jellyfin.serveroneago.eu {
reverse_proxy 192.168.68.62:8096
}
easy peasy.
In Jellyfin I wrote 192.168.68.62 in the known proxys section.
Now let's come to my problem, whener I try to stream something outside my LAN, like on my phone in 5G on the jellyfin android app, the stream blocks almost instantly. I have a 30Mpbs upload so I ruled that one out. I went to look at caddy logs and I found two kinds of errors:
First one is:
{"level":"warn","ts":1744661377.3292377,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"192.168.68.62:8096","duration":0.003041625,"request":{"remote_ip":"78.210.11.124","remote_port":"58754","client_ip":"78.210.11.124","proto":"HTTP/3.0","method":"GET","host":"jellyfin.serveroneago.eu","uri":"/Playback/BitrateTest?Size=1000000","headers":{"Sec-Fetch-Dest":["empty"],"Priority":["u=1, i"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7"],"Authorization":["REDACTED"],"Sec-Ch-Ua":["\"Android WebView\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\""],"Sec-Ch-Ua-Mobile":["?1"],"X-Forwarded-For":["78.210.11.124"],"Accept":["*/*"],"X-Requested-With":["org.jellyfin.mobile"],"Sec-Fetch-Site":["same-origin"],"Sec-Ch-Ua-Platform":["\"Android\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache, no-store"],"User-Agent":["Mozilla/5.0 (Linux; Android 15; Pixel 9 Build/BP1A.250305.020.A2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.38 Mobile Safari/537.36"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jellyfin.serveroneago.eu"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h3","server_name":"jellyfin.serveroneago.eu"}},"error":"writing: H3_REQUEST_CANCELLED"}
Second one is:
{"level":"warn","ts":1744661378.9086902,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"192.168.68.62:8096","duration":0.033417364,"request":{"remote_ip":"78.210.11.124","remote_port":"59216","client_ip":"78.210.11.124","proto":"HTTP/2.0","method":"GET","host":"jellyfin.serveroneago.eu","uri":"/Videos/db177dc4-cdb9-eea6-4aec-5162e214e4c0/stream?static=true&playSessionId=1807704d4dc542678781f281e7850815&mediaSourceId=db177dc4cdb9eea64aec5162e214e4c0&deviceId=cfc7d0e9dcd7dfc06d37fd4ce5744bf0bd57ba549d000a72&streamOptions=%7B%7D","headers":{"Accept-Encoding":["gzip, deflate, br"],"X-Forwarded-For":["78.210.11.124"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jellyfin.serveroneago.eu"],"Icy-Metadata":["1"],"User-Agent":["Jellyfin Android/2.6.2 (Linux;Android 15) ExoPlayerLib/2.19.1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"jellyfin.serveroneago.eu"}},"error":"writing: http2: stream closed"}
I even tried limiting caddy to http1.1, but if I do that the error will change to tcp writing broken pipe.
The file I'm trying to stream is being directly played, no transcoding. Here are the jellyfin logs:
[20:17:19] [INF] [43] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 78.210.11.124 request
[20:17:21] [INF] [32] Jellyfin.Api.Helpers.MediaInfoHelper: User policy for Andrea. EnablePlaybackRemuxing: True EnableVideoPlaybackTranscoding: True EnableAudioPlaybackTranscoding: True
[20:17:50] [INF] [30] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
[20:17:53] [INF] [33] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 closed
[20:17:54] [INF] [34] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
[20:18:03] [INF] [33] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 closed
[20:18:03] [INF] [34] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
What's stranger is if I try to transcode to something very compressed like 420kbps, caddy will still output those warns, but the stream will go through.
I will be eternally thankful to anyone who can help.
I'm quiet desperate. Let's begin from my configuration. I run a Jellyfin and Caddy istance in docker on a Ubuntu 24.10 machine, no firewall for now, I'm troubleshooting. I will write down my docker compose for reference:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
network_mode: 'host'
group_add:
- "992" #render
- "44" #video
volumes:
- /home/andrea/Docker/jellyfin/config

- /home/andrea/Docker/jellyfin/cache

- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/Movies

- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/AnimationMovies

- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/Cartoons

- /mnt/0d2de316-4f48-4c8d-b4bf-a9d8a8eeaf5f/Media/TVShows

devices:
- /dev/dri

environment:
- PUID=1000
- GUID=1000
- JELLYFIN_PublishedServerUrl=https://jellyfin.serveroneago.eu/
extra_hosts:
- 'host.docker.internal:host-gateway'
restart: 'unless-stopped'
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- /home/andrea/Docker/Caddy/Caddyfile

- /home/andrea/Docker/Caddy/config

- /home/andrea/Docker/Caddy/data

networks:
caddy_net:
ipv4_address: 172.19.0.10
environment:
- PUID=1000
- GUID=1000
depends_on:
- hetzner-ddns
Hetzner ddns is what I use to update my dynamic ip to hetnzer via API. I gave caddy a static ip in its bridge network for some troubleshooting but I could remove that without any change. I will paste here my caddy file:
jellyfin.serveroneago.eu {
reverse_proxy 192.168.68.62:8096
}
easy peasy.
In Jellyfin I wrote 192.168.68.62 in the known proxys section.
Now let's come to my problem, whener I try to stream something outside my LAN, like on my phone in 5G on the jellyfin android app, the stream blocks almost instantly. I have a 30Mpbs upload so I ruled that one out. I went to look at caddy logs and I found two kinds of errors:
First one is:
{"level":"warn","ts":1744661377.3292377,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"192.168.68.62:8096","duration":0.003041625,"request":{"remote_ip":"78.210.11.124","remote_port":"58754","client_ip":"78.210.11.124","proto":"HTTP/3.0","method":"GET","host":"jellyfin.serveroneago.eu","uri":"/Playback/BitrateTest?Size=1000000","headers":{"Sec-Fetch-Dest":["empty"],"Priority":["u=1, i"],"Sec-Fetch-Mode":["cors"],"Accept-Language":["it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7"],"Authorization":["REDACTED"],"Sec-Ch-Ua":["\"Android WebView\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\""],"Sec-Ch-Ua-Mobile":["?1"],"X-Forwarded-For":["78.210.11.124"],"Accept":["*/*"],"X-Requested-With":["org.jellyfin.mobile"],"Sec-Fetch-Site":["same-origin"],"Sec-Ch-Ua-Platform":["\"Android\""],"Accept-Encoding":["gzip, deflate, br, zstd"],"Cache-Control":["no-cache, no-store"],"User-Agent":["Mozilla/5.0 (Linux; Android 15; Pixel 9 Build/BP1A.250305.020.A2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.7049.38 Mobile Safari/537.36"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jellyfin.serveroneago.eu"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h3","server_name":"jellyfin.serveroneago.eu"}},"error":"writing: H3_REQUEST_CANCELLED"}
Second one is:
{"level":"warn","ts":1744661378.9086902,"logger":"http.handlers.reverse_proxy","msg":"aborting with incomplete response","upstream":"192.168.68.62:8096","duration":0.033417364,"request":{"remote_ip":"78.210.11.124","remote_port":"59216","client_ip":"78.210.11.124","proto":"HTTP/2.0","method":"GET","host":"jellyfin.serveroneago.eu","uri":"/Videos/db177dc4-cdb9-eea6-4aec-5162e214e4c0/stream?static=true&playSessionId=1807704d4dc542678781f281e7850815&mediaSourceId=db177dc4cdb9eea64aec5162e214e4c0&deviceId=cfc7d0e9dcd7dfc06d37fd4ce5744bf0bd57ba549d000a72&streamOptions=%7B%7D","headers":{"Accept-Encoding":["gzip, deflate, br"],"X-Forwarded-For":["78.210.11.124"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["jellyfin.serveroneago.eu"],"Icy-Metadata":["1"],"User-Agent":["Jellyfin Android/2.6.2 (Linux;Android 15) ExoPlayerLib/2.19.1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"jellyfin.serveroneago.eu"}},"error":"writing: http2: stream closed"}
I even tried limiting caddy to http1.1, but if I do that the error will change to tcp writing broken pipe.
The file I'm trying to stream is being directly played, no transcoding. Here are the jellyfin logs:
[20:17:19] [INF] [43] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 78.210.11.124 request
[20:17:21] [INF] [32] Jellyfin.Api.Helpers.MediaInfoHelper: User policy for Andrea. EnablePlaybackRemuxing: True EnableVideoPlaybackTranscoding: True EnableAudioPlaybackTranscoding: True
[20:17:50] [INF] [30] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
[20:17:53] [INF] [33] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 closed
[20:17:54] [INF] [34] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
[20:18:03] [INF] [33] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 closed
[20:18:03] [INF] [34] Emby.Server.Implementations.HttpServer.WebSocketManager: WS 151.59.72.186 request
What's stranger is if I try to transcode to something very compressed like 420kbps, caddy will still output those warns, but the stream will go through.
I will be eternally thankful to anyone who can help.