Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring toomuchio config into the 21st century #58

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ This configuration will allow you to serve Plex via Nginx.
## Minimal Requirements

Nginx


```bash
# for Debian based systems:
apt-get install -y nginx subversion ssl-cert socat
```

Plex:
* Remote Access - Disable
* Network - Custom server access URLs = `https://<your-domain>:443,http://<your-domain>:80`
Expand Down
277 changes: 190 additions & 87 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -1,104 +1,207 @@
#Must be set in the global scope see: https://forum.nginx.org/read.php?2,152294,152294
#Why this is important especially with Plex as it makes a lot of requests http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html / https://www.peterbe.com/plog/ssl_session_cache-ab
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_names_hash_bucket_size 512;
server_names_hash_max_size 512;
proxy_headers_hash_bucket_size 512;
proxy_headers_hash_max_size 512;
include /etc/nginx/mime.types;
default_type application/octet-stream;

# SSL Config from https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6
ssl_session_cache shared:MozSSL:10m;
ssl_session_timeout 1d;

#Upstream to Plex
upstream plex_backend {
#Set this to the IP address that appears in `ifconfig` (NATTED LAN IP or Public IP address) if you want the bandwidth meter in the server status page to work
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have you removed this comment? The bandwidth charts in dashboard (Plex Pass feature) no longer work when using your exact config. Changing it to point to my local LAN IP (192.168.1.222), the bandwidth charts work again perfectly. (And yes, I'm using the set_real_ip_from and real_ip_header and such correctly)

# Set the port and server to your plex server.
server 127.0.0.1:32400;
keepalive 32;
}

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

# For better Plex logging.
log_format plex '$remote_addr - $remote_user [$time_local]'
'"$request" $status $body_bytes_sent'
'"$http_referer" $host "$http_user_agent"'
'"$request_time" "$upstream_connect_time"'
'"$geoip_city" "$geoip_city_country_code"';

server {
listen 80;
#Enabling http2 can cause some issues with some devices, see #29 - Disable it if you experience issues
listen 443 ssl http2; #http2 can provide a substantial improvement for streaming: https://blog.cloudflare.com/introducing-http2/
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
# Set this A / AAAA / CNAME record prior to starting.
server_name plex.EXAMPLE.COM;

send_timeout 100m; #Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause (e.g. Chrome)

#Faster resolving, improves stapling time. Timeout and nameservers may need to be adjusted for your location Google's have been used here.
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;

#Use letsencrypt.org to get a free and trusted ssl certificate
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
#Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384.
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

#Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/
access_log /var/log/nginx/access.log plex; # You can disable this.
root /srv/;

##
# ACME SSL Cert Generation Method:
#
# curl https://get.acme.sh | sh
# mkdir -p /etc/nginx/ssl/${hostname}
# chmod 700 /etc/nginx/ssl
# /root/.acme.sh/acme.sh --set-default-ca --server letsencrypt # No personal data needed to setup
# Standalone Method
# /root/.acme.sh/acme.sh --force --issue --standalone -d ${hostname}
# DNS API Verification Method
# Reference: https://github.com/acmesh-official/acme.sh/wiki/dnsapi
# /root/.acme.sh/acme.sh --force --issue --dns dns_cf -d ${hostname} -d "*.${hostname}"
# Deploy to nginx
# /root/.acme.sh/acme.sh --force --install-cert -d ${hostname} --key-file /etc/nginx/ssl/${hostname}/key.pem --fullchain-file /etc/nginx/ssl/${hostname}/fullchain.pem --ca-file /etc/nginx/ssl/${hostname}/chain.pem --reloadcmd "systemctl reload nginx"
# Change the below.
##

ssl_certificate /etc/nginx/ssl/plex.EXAMPLE.COM/fullchain.pem;
ssl_key /etc/nginx/ssl/plex.EXAMPLE.COM/key.pem;
ssl_trusted_certificate /etc/nginx/ssl/plex.EXAMPLE.COM/fullchain.pem;
# Generate by doing openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&guideline=5.6
ssl_session_cache shared:MozSSL:10m;
ssl_session_timeout 1d;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
#For letsencrypt.org you can get your chain like this: https://esham.io/2016/01/ocsp-stapling
ssl_trusted_certificate /path/to/chain.pem;

#Reuse ssl sessions, avoids unnecessary handshakes
#Turning this on will increase performance, but at the cost of security. Read below before making a choice.
#https://github.com/mozilla/server-side-tls/issues/135
#https://wiki.mozilla.org/Security/Server_Side_TLS#TLS_tickets_.28RFC_5077.29
#ssl_session_tickets on;
ssl_session_tickets off;

#Use: openssl dhparam -out dhparam.pem 2048 - 4096 is better but for overhead reasons 2048 is enough for Plex.
ssl_dhparam /path/to/dhparam.pem;
ssl_ecdh_curve secp384r1;

#Will ensure https is always used by supported browsers which prevents any server-side http > https redirects, as the browser will internally correct any request to https.
#Recommended to submit to your domain to https://hstspreload.org as well.
#!WARNING! Only enable this if you intend to only serve Plex over https, until this rule expires in your browser it WONT BE POSSIBLE to access Plex via http, remove 'includeSubDomains;' if you only want it to effect your Plex (sub-)domain.
#This is disabled by default as it could cause issues with some playback devices it's advisable to test it with a small max-age and only enable if you don't encounter issues. (Haven't encountered any yet)
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

#Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. (Haven't encountered any yet)
gzip on;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you encounter issues having gzip enabled, you accidentally removed it, or just didn't think it helps?

gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
gzip_disable "MSIE [1-6]\.";

#Nginx default client_max_body_size is 1MB, which breaks Camera Upload feature from the phones.
#Increasing the limit fixes the issue. Anyhow, if 4K videos are expected to be uploaded, the size might need to be increased even more
client_max_body_size 100M;

#Forward real ip and host to Plex
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
#When using ngx_http_realip_module change $proxy_add_x_forwarded_for to '$http_x_forwarded_for,$realip_remote_addr'
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;

#Websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

#Disables compression between Plex and Nginx, required if using sub_filter below.
#May also improve loading time by a very marginal amount, as nginx will compress anyway.
#proxy_set_header Accept-Encoding "";

#Buffering off send to the client as soon as the data is received from Plex.
proxy_redirect off;
proxy_buffering off;
ssl_buffer_size 4k;
ssl_early_data on;

# Security
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag "none" always;
add_header Referrer-Policy same-origin always;
proxy_set_header Early-Data $ssl_early_data;

# Set resolver to Cloudflare
resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] valid=300s;
resolver_timeout 5s;
# Some players don't reopen a socket and playback stops totally instead of resuming after an extended pause (e.g. Chrome)
# You should really just be timing out using plex if the stream is inactive this long.
send_timeout 100m;
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_buffers 32 4k;
# Increase body size
client_max_body_size 1G;

# If using cloudflare this will resolve user ips correctly.
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;
real_ip_header X-Forwarded-For;

location / {
#Example of using sub_filter to alter what Plex displays, this disables Plex News.
#sub_filter ',news,' ',';
#sub_filter_once on;
#sub_filter_types text/xml;
# Example of using sub_filter to alter what Plex displays, this disables Plex News.
# sub_filter ',news,' ',';
# sub_filter_once on;
# sub_filter_types text/xml;
# Websockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_redirect off;
proxy_buffering off;
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
# Plex Headers
proxy_set_header X-Plex-Client-Identifier $http_x_plex_client_identifier;
proxy_set_header X-Plex-Container-Size $http_x_plex_container_size;
proxy_set_header X-Plex-Container-Start $http_x_plex_container_start;
proxy_set_header X-Plex-Device $http_x_plex_device;
proxy_set_header X-Plex-Device-Name $http_x_plex_device_name;
proxy_set_header X-Plex-Platform $http_x_plex_platform;
proxy_set_header X-Plex-Platform-Version $http_x_plex_platform_version;
proxy_set_header X-Plex-Product $http_x_plex_product;
proxy_set_header X-Plex-Token $http_x_plex_token;
proxy_set_header X-Plex-Version $http_x_plex_version;
proxy_set_header X-Plex-Nocache $http_x_plex_nocache;
proxy_set_header X-Plex-Provides $http_x_plex_provides;
proxy_set_header X-Plex-Device-Vendor $http_x_plex_device_vendor;
proxy_set_header X-Plex-Model $http_x_plex_model;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Allows All Encodings
proxy_set_header Accept-Encoding "";
proxy_ssl_verify off;
proxy_http_version 1.1;
proxy_read_timeout 86400;
proxy_pass http://plex_backend;
}

#PlexPy forward example, works the same for other services.
#location /plexpy {
# proxy_pass http://127.0.0.1:8181;
#}

##
# Forward Tautulli over same domain
##

# location /tautulli {
# proxy_pass http://127.0.0.1:24200/tautulli;
# # Advanced Proxy Config
# proxy_read_timeout 240;
# proxy_send_timeout 240;
# proxy_connect_timeout 240;
# proxy_headers_hash_bucket_size 128;
# proxy_headers_hash_max_size 1024;
# proxy_buffers 32 4k;
# # Basic Proxy Config
# 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 https;
# #proxy_redirect http:// $scheme://;
# proxy_http_version 1.1;
# proxy_set_header Connection "";
# proxy_cache_bypass $cookie_session;
# proxy_no_cache $cookie_session;
# }

##
# Host Librespeed on same domain
# If you want librespeed, install php-fpm libfcgi0ldbl php-cli php-dev php-xml php-curl php-xmlrpc php-json php-mbstring php-opcache php-geoip php-xml
# Check your php version and modify below accordingly.
##
# location /librespeed {
# alias /srv/librespeed;
# client_max_body_size 50M;
# client_body_buffer_size 128k;

# location ~ \.php$ {
# include snippets/fastcgi-php.conf;
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# fastcgi_param SCRIPT_FILENAME $request_filename;
# include fastcgi_params;
# }
# }
}