Problems With Nginx and Jellyfin

I am trying to set up Nginx as a reverse proxy, so I can set up a wildcard cert to host a few services on my local network. The nginx server is a dedicated server I rent to host several things. I have a ZeroTier VPN setup to allow the nginx server to access a vlan on my local network. The first service I tried to set up with nginx is jellyfin. I got the example config from the jellyfin setup guide. it does not work. after a lot of searching I finally got it to the point where it’s giving me a 504 gateway timeout error. I know this config works because I tested it on my local network using a test VM running nginx, and it works fine. It’s only the dedicated server that is having this issue. Anyone else had this issue?

Config:

server {
    listen 80;
    listen [::]:80;
    # server_name mydomain.com;

    # Uncomment to redirect HTTP to HTTPS
    # return 301 https://$host$request_uri;
#}

#server {
    # listen 443 ssl http2;
    # listen [::]:443 ssl http2;
    server_name mydomain.com;

    ## 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 10.30.10.14;

    #ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;
    #ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;
    #include /etc/letsencrypt/options-ssl-nginx.conf;
    #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    #add_header Strict-Transport-Security "max-age=31536000" always;
    #ssl_trusted_certificate /etc/letsencrypt/live/mydomain.com/chain.pem;
    #ssl_stapling on;
    #ssl_stapling_verify on;

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

    # COOP/COEP. Disable if you use external plugins/images/assets
    add_header Cross-Origin-Opener-Policy "same-origin" always;
    add_header Cross-Origin-Embedder-Policy "require-corp" always;
    add_header Cross-Origin-Resource-Policy "same-origin" always;

    # 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: http://image.tmdb.org; 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 = / {
        return 302 http://$host/web/;
        #return 302 https://$host/web/;
    }

    location / {
        # Proxy main Jellyfin traffic
        proxy_bind 10.30.10.16;
        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 block for /web - This is purely for aesthetics so /web/#!/ works instead of having to go to /web/index.html/#!/
    location = /web/ {
        # Proxy main Jellyfin traffic
        proxy_bind 10.30.10.16;
        proxy_pass http://$jellyfin:8096/web/index.html;
        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;
    }

    location /socket {
        # Proxy Jellyfin Websockets traffic
        proxy_bind 10.30.10.16;
        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;
    }
}


I know I should be using ssl. I just want to get it working first before I move on to setting something else up.

what’s the OS NGINX is running on?


get rid of the of X-Forwarded-Protocol since it seems kinda redundant and I have no idea if that actually works or not. Proxy_bind seems a bit unnecessary as well


Is the NGINX proxy able to ping the jellyfin server?

The nginx server is running on Ubuntu server 20.04 LTS. It can ping the jellyfin server, and the jellyfin server can ping the nginx server. Proxy_bind was added on my test vm and that got it working. I copied the config over to see if it would make the dedicated server work. Should I remove just the X-Forwarded-Protocol lines or all of the X-Forwarded lines?

looking at jellyfin’s config, lets leave the x-forwarded lines alone, is jellyfin reachable on port 8096?

also for the socket, I see http_upgrade, did you set that variable in the main nginx config?

I can login to the jellyfin server from another vm on the same vlan using port 8096. I would not know how to verify that on ubuntu server. In regard to the http_upgrade setting I just followed the guide that Jellyfin gave me along with several other videos and articles. What setting would I need to change. It just worked the first time I tried this on my test VM.

at some point, it may not even be an issue with nginx at this rate. I think it might be the VPN. If the NGINX configs work on your local VLan and all, then there is zero reason why it shouldnt work on the dedicated. There is a break down of communication somewhere between the servers.

I just tried to access the nginx default site from a VM through the VPN. I get nothing. I can ping, but no web traffic. The default site is accessible through the internet as well. Well I guess I need to troubleshoot the VPN now. VPNs never work right for me. thank you for your help.

VPN and possibly firewalls.

Maybe. I just switched to using Opensense to bridge the Zerotier network on to my Proxy vlan. I don’t understand why I would be able to ping but not get web traffic though.

(EDIT) I added another device to the Zerotire network and it can ping the jelltfin server, but no web traffic.

@PhaseLockedLoop This maybe your forte as I recall you having firewall issues with your OPNSense and the external server

1 Like

This sounds like a advertised route issue. Does the VPN have a static route (and vice versa) into the specific vlan?

I just put the ZeroTier Interface and the network interface on the vlan in a bridge. It has worked for me in the past for a remote access vpn, but I am a relative novice at this so maybe I messed something up.

Interesting. Can you connect to your zero tier from outside your network ( just testing a couple possibilities)

Are you hosting directly off your ISP ip?

I can ping all the devices on the vlan through the zerotier vpn, but no web traffic. The proxy server is not on my home network. I was trying to avoid having public facing services pointing to my home network.

(EDIT) The Opensence VM is just acting as a bridge between zerotier and the vlan

This is beyond my wheelhouse @Novasty i need your vm knowledge. Is there anything funky biz with opnsense routing when its a vm gateway?

I dont virtualize my router or routing. Ive always found it to be poor in principle thats why I lack that knowkedge

It’s not my main router. I only have it as a bridge between zerotier and the VMs.
I can’t install zerotier on my main router otherwise I would.

My only thought is the firewall rules might not be set to allow as normally it should allow ping, but the rest of the traffic might be blocked. Like when we set allow all for your wireguard tunnel.

I’m also unfamiliar with that sort of network setup where the external device is on the same VLAN

Hmmm I wonder. I seriously wonder if its the routing between his main router and his virtual router

He might try to see if he can make a static route on the main router that advertises the IP he wants to hit via a gateway with the gateway being the virtual router?

Run a trace route from each step higher in your gateway chain. see if you can ping stuff

I just spun up an ubuntu vm and used it to bridge the zerotier VPN to my proxy vlan and everything started working. I must have done something wrong configuring Opensese. It was my first time using it so I just followed a tutorial on setting up a bridge.

Don’t know why ping worked though