Can not connect remotely to Jellyfin instance with Android devices

Hey guys!

1. The problem I’m having:

I own a domain with the following CNAMEs:
Because I have a dynamic IP at the server location I point my domain to DuckDNS which gets updated by a (the offical I guess) DuckDNS container.
Jellyfin as well as Caddy also run in a container on my server.

I can connect to my jellyfin instance remotely via Browser, via IOS. Outside and inside of my network.
But I cannot connect to Jellyfin remotely via Android or AndroidTV. I can only connect to Android devices when I’m inside my network with the local ip (

2. Error messages and/or full log output:

curl -vI

main 0a72092
* Host was resolved.
* IPv6: 2a02:560:5394:1800:a53e:a53e:a53e:a53e
* IPv4:
*   Trying [2a02:560:5394:1800:a53e:a53e:a53e:a53e]:443...
*   Trying
* Connected to ( port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_CHACHA20_POLY1305_SHA256 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject:
*  start date: Jan 17 14:09:36 2024 GMT
*  expire date: Apr 16 14:09:35 2024 GMT
*  subjectAltName: host "" matched cert's ""
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* using HTTP/2
* [HTTP/2] [1] OPENED stream for
* [HTTP/2] [1] [:method: HEAD]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority:]
* [HTTP/2] [1] [:path: /jellyfin/system/info/public]
* [HTTP/2] [1] [user-agent: curl/8.6.0]
* [HTTP/2] [1] [accept: */*]
> HEAD /jellyfin/system/info/public HTTP/2
> Host:
> User-Agent: curl/8.6.0
> Accept: */*
< HTTP/2 404 
HTTP/2 404 
< alt-svc: h3=":443"; ma=2592000
alt-svc: h3=":443"; ma=2592000
< date: Thu, 01 Feb 2024 22:31:43 GMT
date: Thu, 01 Feb 2024 22:31:43 GMT
< server: Caddy
server: Caddy
< server: Kestrel
server: Kestrel
< x-response-time-ms: 5
x-response-time-ms: 5

* Connection #0 to host left intact

Please use the preview pane to ensure it looks nice.

3. Caddy version:


4. How I installed and ran Caddy:

I followed the offical docker installation, this is my docker-compose.yml

  GNU nano 6.2                                                                                                                                                     docker-compose.yml                                                                                                                                                               
version: "3.9"

    image: caddy:latest
    restart: unless-stopped
      - "80:80"
      - "443:443"
      - "443:443/udp"
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config
      - caddy

    external: true

a. System environment:

I run proxmox where this server runs as a VM with ubuntu 22.04.

b. My complete Caddy config:

This is my Caddyfile:

        reverse_proxy portainer:9000
} {
        reverse_proxy gitea:3000
} {
        reverse_proxy nextcloud-nextcloud-app-1:80
} {
        reverse_proxy invidious-invidious-1:3000
        reverse_proxy immich_server:3001
} {
        reverse_proxy searxng:8090
} {
        reverse_proxy jellyfin:8096

I changed my Domain name and my public ip as I don’t feel comfortable sharing it :confused: I hope thats ok even tho it mentioned that it isn’t.

Thanks in advance for taking your time and helping me, really appreciate it!

Are you sure that request path is correct?

On my own Jellyfin instance, /jellyfin/system/info/public is not a thing either. /system/info/public works though.

Where did you get that from?

What error do you see when you try to connect? What’s in Caddy’s logs when trying to connect?

I really don’t know :open_mouth: Where would i change set path? I’m using linuxserver jellyfin:latest and basically didn’t change any default settings.

When I view the logs with docker logs -f --tail 20 jellyfin I get the following when connecting with my brower: [23:09:08] [INF] [69] Emby.Server.Implementations.HttpServer.WebSocketManager: WS request and nothing at all shows up when connection via Android app

You haven’t really described in what way it’s not working. Show the behaviour you’re experiencing. We need specifics.

What happens if you try to use your browser on Android instead of the app?

Enable the debug global option in Caddy and show your Caddy logs.

The only thing that is not working is connecting to jellyfin with Android Apps. Connecting to it with firefox/chrome from an Android device is fine. Connecting with the Jellyfin App on my Android 14 phone or with my AndroidTV and the AndroidTV Jellyfin app is not working.
This is the Error when trying to connect with the Android app (same error on androidTv and Android phone):

Here is the debug log from caddy when connecting to my Jellyfin instance using the Jellyfin App on Android (outside of network/5g):

No entries related to the subdomain or to the jellyfin docker container.
There seems to be zero connectivity.

And here the log when connecting to my Jellyfin instance using the Firefox browser on my Android phone (also outside of network/5g):

caddy-1  | {"level":"debug","ts":1706895282.167535,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"jellyfin:8096","total_upstreams":1}
caddy-1  | {"level":"debug","ts":1706895282.1675587,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"jellyfin:8096","total_upstreams":1}
caddy-1  | {"level":"debug","ts":1706895282.1687992,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"jellyfin:8096","duration":0.001195067,"request":{"remote_ip":"","remote_port":"34299","client_ip":"","proto":"HTTP/2.0","method":"GET","host":"","uri":"/QuickConnect/Enabled","headers":{"Accept":["application/json"],"Sec-Fetch-Dest":["empty"],"User-Agent":["Mozilla/5.0 (Android 14; Mobile; rv:122.0) Gecko/122.0 Firefox/122.0"],"Accept-Language":["de-DE"],"Accept-Encoding":["gzip, deflate, br"],"X-Forwarded-For":[""],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":[""],"Sec-Fetch-Mode":["cors"],"Sec-Fetch-Site":["same-origin"],"Te":["trailers"],"X-Emby-Authorization":["MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox Android\", DeviceId=\"TW96aWxsYS81LjAgKEFuZHJvaWQgMTQ7IE1vYmlsZTsgcnY6MTA5LjApIEdlY2tvLzExOS4wIEZpcmVmb3gvMTE5LjB8MTcwMDMyMzk2NzczNA11\", Version=\"10.8.13\""]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"h2","server_name":""}},"headers":{"Content-Type":["application/json; charset=utf-8"],"Date":["Fri, 02 Feb 2024 17:34:41 GMT"],"Server":["Kestrel"],"X-Response-Time-Ms":["0"]},"status":200}
caddy-1  | {"level":"debug","ts":1706895282.1696348,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"jellyfin:8096","duration":0.001915231,"request":{"remote_ip":"","remote_port":"34299","client_ip":"","proto":"HTTP/2.0","method":"GET","host":"","uri":"/Branding/Configuration","headers":{"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (Android 14; Mobile; rv:122.0) Gecko/122.0 Firefox/122.0"],"X-Forwarded-Host":[""],"X-Emby-Authorization":["MediaBrowser Client=\"Jellyfin Web\", Device=\"Firefox Android\", DeviceId=\"TW96aWxsYS81LjAgKEFuZHJvaWQgMTQ7IE1vYmlsZTsgcnY6MTA5LjApIEdlY2tvLzExOS4wIEZpcmVmb3gvMTE5LjB8MTcwMDMyMzk2NzczNA11\", Version=\"10.8.13\""],"Accept-Encoding":["gzip, deflate, br"],"Sec-Fetch-Dest":["empty"],"Sec-Fetch-Site":["same-origin"],"Te":["trailers"],"X-Forwarded-For":[""],"X-Forwarded-Proto":["https"],"Accept-Language":["de-DE"],"Accept":["application/json"]},"tls":{"resumed":false,"version":772,"cipher_suite":4867,"proto":"h2","server_name":""}},"headers":{"X-Response-Time-Ms":["0"],"Content-Type":["application/json; charset=utf-8"],"Date":["Fri, 02 Feb 2024 17:34:41 GMT"],"Server":["Kestrel"]},"status":200}

If you’re not seeing any logs in Caddy, then it means there’s a networking issue outside of Caddy you need to resolve.

I can’t read the error message you got in Jellyfin, I can’t read that language. What is it saying?

What issues could that be? I’m a bit out of ideas as all certificates seem to be working perfectly fine. Caddy is doing its job and routing everything under to the jellyfin container but for android apps it doesn’t even respond to? I don’t see how that makes sense.

The Jellyfin error basically just says:
Server not reachable, tried the following 3 addresses.
So also nothing that helps me or gives me any hints.

Did you try on Android in a web browser? Does it also fail?

Your Android device might have some DNS settings turned on which prevent it from resolving your domain name.

Yes the logs above where from Anroid in a web browser. And as stated this works. The only thing that is not working is connecting via Jellyfin APP on Android and AndroidTV.

DNS settings should have nothing to do with it. I tried this with about ~10 different Android Devices in several different locations (friends devices).

It seems this is a caddy-only problem as other folks using nginx/swag don’t seem to have this problem or could at least fix it somehow.

Gonna swap to another reverse proxy and see if I encounter the same problem.

Thanks @francislavoie for trying to help me tho :slight_smile:

I also don’t have this problem, and I run Caddy + Jellyfin.

If there’s no logs from Caddy at all when trying to connect, then there’s no way the problem could be with Caddy. All connections would at least get a debug level log from the TLS handshake.

This means that the problem must be somewhere in front of Caddy, some networking issue that is preventing the connection.

Can you show me how you configured your Caddyfile assuming you reverse proxy to your Jellyfin instance?
Could you also show me your Jellyfin docker settings? Did you configure something in the Jellyfin Network settings?

My config is just like this, except localhost:8096 because I don’t run it in Docker, but that’s not relevant here.

Jellyfin config is the defaults, nothing changed.

Again, I’m 100% convinced this is not a problem with Caddy or Jellyfin, because the connection isn’t reaching Caddy at all. With debug logs enabled, you would see something if it did reach Caddy. But it doesn’t reach Caddy.

Can you share your real domain? There’s not much I can do at this point, if I knew your domain I could try to connect from my own devices and compare behaviour.

It’s working on my Android Phone and AndroidTV right now. I’m testing it on a couple of other android devices today and see if it works reliable.

I literally didn’t changed a thing in the last couple of days.
Could there maybe be a policy on Android that only accepts certs that are older than 24 hours or something like that?

Definitely not, that would be very wrong.

But like I said, we saw no debug logs at all from Caddy according to you, so there’s absolutely no way that the client would have even seen a certificate from Caddy. You would’ve seen a log about Caddy doing certificate selection if it got that far. But it wasn’t even connecting.

Anyway, glad it’s working now