Jellyfin Forum
NGinx Reverse Proxy - Printable Version

+- Jellyfin Forum (https://forum.jellyfin.org)
+-- Forum: Support (https://forum.jellyfin.org/f-support)
+--- Forum: General Questions (https://forum.jellyfin.org/f-general-questions)
+--- Thread: NGinx Reverse Proxy (/t-nginx-reverse-proxy)



NGinx Reverse Proxy - jelly55 - 2024-10-15

I am using jellyfin server behind a NGinx Reverse Proxy so i can use port 80/443 and a http://URI instead of http://URI:8096 / https://URI:8920.

All is working so far but i found this post concerning emby to limit the bandwith for download speed.
-> https://emby.media/community/index.php?/topic/57214-nginx-limit-download-speed/
What is nescessary to adapt this to jellyfin?

Code:
Is it enough to change the path from
 
# Bandwith limit (inside server block) location ~ /emby/Items/(.*)/Download$ {

What is the correct path for the download limits for jellyfin?

This help page
https://jellyfin.org/docs/general/networking/nginx/

does not help with this purpose ...


RE: NGinx Reverse Proxy - foux - 2024-10-15

Why do you want to do it in the reverse proxy? You can set a maximum streaming speed in Jellyfin settings.


RE: NGinx Reverse Proxy - jelly55 - 2024-10-15

I want to limit the download speed not the streaming speed

Jellyfin allows to download files instead of streaming them. I don't know how to set the correct settings in nginx to limit this.

The post from the internet is concerning emnby what is different from jellyfin so i can't use the settings 1:1 for my purpose.


RE: NGinx Reverse Proxy - TheDreadPirate - 2024-10-15

https://jellyfin.org/docs/general/networking/nginx/#rate-limit-downloads

Literally copy and paste that block into your jellyfin server block in the nginx config.

Code:
# Downloads limit (inside server block)
location ~ /Items/(.*)/Download$ {
   proxy_pass http://$jellyfin:8096;
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-Forwarded-Protocol $scheme;
   proxy_set_header X-Forwarded-Host $http_host;

   limit_rate 1700k; # Speed limit (here is on kb/s)
   limit_conn addr 3; # Number of simultaneous downloads per IP
   limit_conn_status 460; # Custom error handling
   # proxy_buffering on; # Be sure buffering is on (it is by default on nginx), otherwise limits won't work
}

As long as $jellyfin is also the name of the variable you used.

Here it is in a full nginx config, based off mine.

Code:
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name jellyfin.domain.tld;

    ## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
    client_max_body_size 20M;

    # 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 127.0.0.1;
    
    ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem; # managed by Certbot
    ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/chain.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # Security / XSS Mitigation Headers
    # NOTE: X-Frame-Options may cause issues with the webOS app
    add_header X-XSS-Protection "0"; # Do NOT enable. This is obsolete/dangerous
    add_header X-Content-Type-Options "nosniff";

    # kill cache
    add_header Last-Modified $date_gmt;
    add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
    if_modified_since off;
    expires off;
    etag off;

    # Permissions policy. May cause issues on some clients
    add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;

    # Tell browsers to use per-origin process isolation
    add_header Origin-Agent-Cluster "?1" always;

    # Content Security Policy
    # See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
    # Enforces https content and restricts JS/CSS to origin
    # External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
    # NOTE: The default CSP headers may cause issues with the webOS app
    add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";

    location / {
        # Proxy main Jellyfin traffic
        proxy_pass http://$jellyfin:8096;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;

        # Disable buffering when the nginx proxy gets very resource heavy upon streaming
        proxy_buffering off;
    }

    location /socket {
        # Proxy Jellyfin Websockets traffic
        proxy_pass http://$jellyfin:8096;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
    }

    # Cache images
    location ~ /Items/(.*)/Images {
        proxy_pass http://$jellyfin:8096;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Forwarded-Host $http_host;

        proxy_cache jellyfin;
        proxy_cache_revalidate on;
        proxy_cache_lock on;
    }

    # Downloads limit (inside server block)
    location ~ /Items/(.*)/Download$ {
      proxy_pass http://$jellyfin:8096;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Protocol $scheme;
      proxy_set_header X-Forwarded-Host $http_host;

      limit_rate 1700k; # Speed limit (here is on kb/s)
      limit_conn addr 3; # Number of simultaneous downloads per IP
      limit_conn_status 460; # Custom error handling
      # proxy_buffering on; # Be sure buffering is on (it is by default on nginx), otherwise limits won't work
    }
}

This line would be placed in /etc/nginx/nginx.conf. It could also be placed in the same config as your jellyfin server, but would be outside of the server block. In my example it would go below the final bracket or above "server {" at the top of the file.

Code:
# Add this outside of you server block (i.e. http block)
limit_conn_zone $binary_remote_addr zone=addr:10m;



RE: NGinx Reverse Proxy - jelly55 - 2024-10-15

Many thanks for your help

I will try this tomorrow and give Feedback :smile:


Update 16.10.:

In the morning i moved my old *.conf for jellyfin (/etc/nginx/conf.d/*) to *.bak and created a fresh one with yours.

I adapted the file to my needs (letsencrypt, dhparams, server_name, etc.)
I needed an update because in debian bookworm an elderly one is delivered (1.22.*) so e.g. the "hhtp2 on;" directive wasn't recognized.
After switching to the stable repository i updated my nginx to 1.26.* and "http2 on" is OK.

I had to comment out the line

Code:
proxy_cache jellyfin;

I haven't set this variable / parameter so "jellyfin" is unknwon for (my) nginx.

Never the less all other options were set so it is working as far as i could test here.
I tested it by using a vivaldi browser in ZorinOS (ubuntu linux 22.04.x) a jellyfin viewer (desktop for linux) as well and plus a fresh Android 15 (Pixel) device.

All seems to be working so far.

Again i thank you very much for your support  Ok-hand