Created
May 30, 2021 12:19
-
-
Save shubhamoli/bed1b959705f74256aa2223fc76e3205 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Put this file in /etc/nginx/conf.d/ directory | |
# This will listen for media.<domain>.<tld> | |
# as it listens on 443 HTTPS Port so you'll also need SSL certificate for your domain. | |
server { | |
listen 80; | |
listen [::]:80; | |
server_name media.<domain>.<tld>; | |
return 301 https://$host$request_uri; | |
} | |
server { | |
listen 443 ssl http2; | |
listen [::]:443 ssl http2; | |
server_name media.<domain>.<tld>; | |
access_log /var/log/nginx/media.access.log; | |
error_log /var/log/nginx/media.error.log; | |
set $jellyfin jellyfin; | |
resolver 127.0.0.1 valid=30; | |
ssl_certificate <path/to/cert.crt>; | |
ssl_certificate_key <path/to/cert.key>; | |
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; | |
ssl_ciphers HIGH:!aNULL:!MD5; | |
# Security / XSS Mitigation Headers | |
add_header X-Frame-Options "SAMEORIGIN"; | |
add_header X-XSS-Protection "1; mode=block"; | |
add_header X-Content-Type-Options "nosniff"; | |
# 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. | |
add_header Content-Security-Policy "default-src https: data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'"; | |
location = / { | |
return 302 https://$host/web/; | |
} | |
location / { | |
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_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_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 video streaming | |
location /videos/ { | |
proxy_cache jf_video; | |
proxy_cache_valid 200 301 302 30d; | |
proxy_ignore_headers Expires Cache-Control Set-Cookie X-Accel-Expires; | |
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; | |
proxy_connect_timeout 10s; | |
proxy_http_version 1.1; | |
proxy_set_header Connection ""; | |
proxy_pass http://$jellyfin:8096; | |
proxy_cache_key "<domain>.<tld>$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"; | |
proxy_cache_valid 200 301 302 30d; | |
} | |
# Cache images | |
location ~ /Items/(.*)/Images { | |
proxy_cache jf_image; | |
proxy_cache_revalidate on; | |
proxy_cache_lock on; | |
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; | |
} | |
# Rate limit downloads | |
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, otherwise limits won't work | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment