Plex behind Reverse Proxy

I have the following configuration that is set on my reverse proxy (NGiNX) which converts all port 80 traffic to 443 and enforces SSL connection.

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

#Upstream to Plex
upstream plex_backend {
    server 192.168.7.102:32400;
    keepalive 32;
}

server {
    listen 80;
    listen [::]:80;
    server_name plex.server.com;
    return 301 https://plex.server.com$request_uri;
}

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/
	server_name plex.server.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 /etc/letsencrypt/live/plex.server.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/plex.server.com/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/
	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 /etc/letsencrypt/live/plex.server.com/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 /etc/ssl/certs/plex.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;
	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;

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

	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;
		proxy_pass http://plex_backend;
	}

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

What I want to accomplish is for all client apps to connect directly to my server (through the reverse proxy) on the port of 32400 rather than go through Plex’s relay.

Is this possible? If so, what do I have to do here with the NGiNX config? What do I have to do on the backend?

This is what I have on the backend:

Can anyone assist here?

What exactly is the problem? For Plex to not connect to port 32400 (which is what you usually want when setting up an Nginx proxy and have Plex connect over it on port 443) you need to disable the remote access option in Plex Media Server. If you did that, the rest of your configuration and settings looks correct.

If you want to use the Nginx reverse proxy, but with port 32400 instead of 443:

  • you can’t have Nginx running on the same box as your Plex Media Server (because port 32400 will be taken by Plex);
  • you have to disable remote access in Plex Media Server (otherwise it will try to connect to a plex.direct domain);
  • you have to change the Nginx configuration and replace port 443 with 32400;
  • you have to change the Custom server access URLs value to https://plex.server.com:32400;
  • and (less important) you have to decide what you want to do with port 443 (and 80): close them and not use them, or forward them to 32400.
1 Like

What I want is for all Plex clients to connect directly to my server (not through Plex relays) and ensure that the connection is secure. Right now for example I see this:

plex

I do not have any custom SSL certs installed or anything yet there is an green lock icon, which shows that somehow I am secure. Either this is a bug or Plex is connecting through a relay. Same goes for clients/apps, where it shows a secure communication even though my Plex install has no certs installed.

The ‘not secure’ in the browser address bar is only indicating that you have loaded the web app into your browser ‘unsecured’.
What that means: you either loaded it from your own server by using its IP address or by using a custom domain name.
In both of the above situations there is no fitting cryptographic certificate available. (there is no way to have a certificate for an IP address and you very probably don’t have a fitting certificate for your custom domain name either.)

But this doesn’t really matter, because once the web app has been loaded into the web browser, it is still communicating securely with your server(s). Which is indicated by the green padlock icon.

If you want to see a green ‘secured’ in the address bar of your browser, load the web app from here https://app.plex.tv/desktop
(And no, loading the web app from there won’t change anything about the way how it communicates directly with your server.)

This is no bug. Your server is getting a subdomain on the .plex.direct domain and a fitting, “pinned” TLS certificate free of charge. Automatically, as soon as you sign it into your plex.tv account.

If it were using a relay connection, you’d see this indicated by the work (Indirect) under the server name.

If you want to know more about how secure connections are done in Plex, read https://support.plex.tv/articles/206225077-how-to-use-secure-server-connections/

1 Like

I think what you’re trying to do is have the ability to connect to your Plex Media Server & have the Web Gui accessible from a custom domain name.

EX: https://mydomain.com

Are you looking to connect to your External Facing Domain Name & access the PMS from that domain name instead of accessing it through the Public Plex Web Gui?

If so, this should be fairly simple. You must obtain a custom Domain Name & Certificate, your domain name must be pointed to your public IP address & your SSL Certificate must be publicly trusted & match the domain name you’re listening on


Then all it would require is a PAT Rule/Port Forward to allow SSL traffic on the port you’re Plex Media Server is listening (Default:32400)

It would look like this https://mydomain.com - Public IP Address (0.0.0.0) - Router/Firewall - PAT Rule/Port Forward - LAN IP on Port 32400


In your above Custom Server access URL’s, you have https://plex.server.com where you would need https://mydomain.com that resolves to a Public IP along with a Custom Certificate in your screenshot above the one previously mentioned.

If you don’t have a Trusted Public Certificate & Domain Name, this will route your connections through Plex’s servers & provide you with a plex.direct domain name that comes pre-loaded with a DigiCert Certificate.

Hope this helps!

Here is another Plex Pass User using a Let’s Encrypt SSL Certificate with a Ubuntu Server!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.