jellyfin / jellyfin.org

The Jellyfin website, blog, and user documentation
http://jellyfin.org
Other
83 stars 314 forks source link

Chrome browser getting 302 error ERR_TOO_MANY_REDIRECTS #813

Closed w0nd3r365 closed 9 months ago

w0nd3r365 commented 10 months ago

I exactly followed as documented the example jellyfin nginx config for jellyfin with subpath but I couldn't load the nginx proxied jellyfin page in chrome, getting the error ERR_TOO_MANY_REDIRECTS.

There's an error in the current https://jellyfin.org/docs/general/networking/nginx/ as documented in issue #6610 in jellyfin repo, fixed by comment from CaptainXLAB. I'll provide more info if needed.

felix920506 commented 9 months ago

Hi, the best way to get this addressed would be to edit the file and submit a PR.

The file for nginx is this one: https://github.com/jellyfin/jellyfin.org/blob/master/docs/general/networking/nginx.md

w0nd3r365 commented 9 months ago

@felix920506 I've neither created a pull request before nor do I know how to do it. Can you edit the file and submit the PR?

The changes are indicated by the diff below:

--- original/nginx.md   2024-01-17 20:53:49.732564945 +0300
+++ modified/nginx.md   2024-01-17 21:28:23.542564154 +0300
@@ -158,12 +158,6 @@
     # You can specify multiple domain names if you want
     #server_name jellyfin.local;

-    # use a variable to store the upstream proxy
-    # in this example we are using a hostname which is resolved via DNS
-    # (if you aren't using DNS remove the resolver line and change the variable to point to an IP address e.g `set $jellyfin 127.0.0.1`)
-    set $jellyfin jellyfin;
-    resolver 127.0.0.1 valid=30;
-
     # Uncomment and create directory to also host static content
     #root /srv/http/media;
     index index.html;
@@ -182,8 +176,10 @@

         # The / at the end is significant.
         # https://www.acunetix.com/blog/articles/a-fresh-look-on-reverse-proxy-related-attacks/
+        # Using a variable to store the upstream server address results in endless redirection loop (chromium: "ERR_TOO_MANY_REDIRECTS", Firefox: "The page isn’t redirecting properly"). So don't use a variable.
+        # JELLYFIN_HOST = IP address or hostname of machine running jellyfin server e.g localhost, 127.0.0.1, 192.168.1.2, etc.

-        proxy_pass http://$jellyfin:8096/jellyfin/;
+        proxy_pass http://JELLYFIN_HOST:8096/jellyfin/;

         proxy_pass_request_headers on;

@@ -234,11 +230,6 @@
     ssl_trusted_certificate /etc/letsencrypt/live/DOMAIN_NAME/chain.pem;
     ssl_stapling on;
     ssl_stapling_verify on;
-    # use a variable to store the upstream proxy
-    # in this example we are using a hostname which is resolved via DNS
-    # (if you aren't using DNS remove the resolver line and change the variable to point to an IP address e.g `set $jellyfin 127.0.0.1`)
-    set $jellyfin jellyfin;
-    resolver 127.0.0.1 valid=30;

     # Jellyfin
     location /jellyfin {
@@ -250,8 +241,10 @@

         # The / at the end is significant.
         # https://www.acunetix.com/blog/articles/a-fresh-look-on-reverse-proxy-related-attacks/
+        # Using a variable to store the upstream server address results in endless redirection loop (chromium: "ERR_TOO_MANY_REDIRECTS", Firefox: "The page isn’t redirecting properly"). So don't use a variable.
+        # JELLYFIN_HOST = IP address or hostname of machine running jellyfin server e.g localhost, 127.0.0.1, 192.168.1.2, etc.

-        proxy_pass http://$jellyfin:8096;
+        proxy_pass http://JELLYFIN_HOST:8096/jellyfin/;

         proxy_pass_request_headers on;

@@ -328,7 +321,7 @@
   proxy_cache_lock on;
   proxy_cache_lock_age 60s;

-  proxy_pass http://$jellyfin:8096;
+  proxy_pass http://127.0.0.1:8096;
   proxy_cache_key "jellyvideo$uri?MediaSourceId=$arg_MediaSourceId&VideoCodec=$arg_VideoCodec&AudioCodec=$arg_AudioCodec&AudioStreamIndex=$arg_AudioStreamIndex&VideoBitrate=$arg_VideoBitrate&AudioBitrate=$arg_AudioBitrate&SubtitleMethod=$arg_SubtitleMethod&TranscodingMaxAudioChannels=$arg_TranscodingMaxAudioChannels&RequireAvc=$arg_RequireAvc&SegmentContainer=$arg_SegmentContainer&MinSegments=$arg_MinSegments&BreakOnNonKeyFrames=$arg_BreakOnNonKeyFrames&h264-profile=$h264Profile&h264-level=$h264Level&slicerange=$slice_range";

   # add_header X-Cache-Status $upstream_cache_status; # This is only for debugging cache

git commit description: Don't use a variable to store the jellyfin upstream server address for nginx with subpath Apply the patch with $ patch -u -i endless_redirect.patch docs/general/networking/nginx.md

Extended description: Using a variable to store the upstream server address results in endless redirection loop. On chromium-based browsers, the error is: "This page isn't working. redirected you too many times. ERR_TOO_MANY_REDIRECTS". On firefox-based browsers, the error is :"The page isn’t redirecting properly. The browser has stopped trying to retrieve the requested item. The site is redirecting the request in a way that will never complete"

Interestingly, using a variable for jellyfin from a subdomain on nginx works just fine with no such errors.

JPVenson commented 9 months ago

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request

w0nd3r365 commented 9 months ago

After much testing I've come to realize that the endless redirect loop issue for Nginx with subpath was rather simple to fix. It was caused by the trailing /jellyfin/ in the proxy_pass directive. I've filed PR #830 that fixes it.

Why does this happen? Normally in Nginx if we put trailing slash / at the end of the proxy_pass directive with a variable, it will ONLY proxy / to jellyfin server without the entire URI. Jellyfin then redirects to /jellyfin and nginx redirects /jellyfin to /jellyfin/ location block which contains the which contains the problematic trailing slash in the proxy_pass directive causing the redirection cycle to begin again, endlessly. (source: https://distinctplace.com/2017/04/19/nginx-resolver-explained/)

The potential problem with the solution proposed in this comment is explained in https://distinctplace.com/2017/04/19/nginx-resolver-explained/ which basically says that when you specify hostname for proxy_pass rather than a static IP address, Nginx will resolve it only once on startup or reload and then cache resulting IP address indefinitely until it's restarted or reloaded. This becomes problematic if the IP address of the jellyfin hostname changes frequently, because then the Nginx-cached IP address would be invalid and may end up proxying some other site or replying 502 bad gateway. If using a static IP address, or a hostname with a static IP address, then the solution would work.

felix920506 commented 9 months ago

Now that #830 is merged, can this be closed?

w0nd3r365 commented 9 months ago

Yeah, the issue is fixed.