Plex behind IIS reverse proxy
Plex Media Server is ideal free replacement for out-dated Microsoft home media stack. To be honest it’s even more powerful and has some nice features we only dreamed about back in days. One example: remote access to home media. Plex in home network can be available also from public internet and this blog post covers some scenarios where Plex is running behing IIS reverse-proxy.
Before you start. This blog post expects from reader at least basic knowledge about computer networks, web servers and communication protocols used in web. Also skills on configuring routers and Microsoft Internet Information Server (IIS) are must-be. If you are not sure what these things are then instead of trying to do everything by yourself ask help by some good friend who knows computers better.
Introduction
Running Plex at home network and making it public from home network are supported scenarios. Making Plex available through reverse proxy can be challenging. On the following illustration there is Home Server that takes all HTTPS traffic forwarded by router, makes HTTPS offloading and based on rewrite rules proxies request to Plex Server running Plex and Tautulli or File & Download server that hosts some browser based download systems.
There are some scenarios where power users want to go with reverse proxy:
- One entry point to home network. There are multiple different web servers in home network but there’s only one point to access them. It can be the fact that user has regular SSL certificate for secure connections to web server hosted at home. Also it may come down to limits set by ISP.
- Features of big web server. Some users want to use powerful features provided by big servers like Apache, nginx and IIS. This is must be with Tautulli that doesn’t seem to ask any authentication. When exposed to public web then big web server takes care of authentication.
Servers in network
From this point on this writing uses following network addresses:
- 192.168.1.14 – Home Server with IIS installed and configured (media.mydomain.com)
- 192.168.1.22 – Plex server running in default port
Preparing IIS
On IIS we need the following things (IIS 8.0 or higher):
- URL Rewrite extension
- Application Request Routing (ARR) extension
- Valid SSL certificate
- SSL site ready and configured
It’s possible to skip ARR and SSL but I don’t recommend it due to security reasons. SSL certificates doesn’t usually come free, I know. But there are some providers who give free SSL certificates. Often these certificates expire after few months and need renewing. But, of course, security is optional, as we all know.
Enable Anonymous authentication. Plex server uses it’s own authentication and on server level we don’t need to involve here.
Configuring ARR
Open IIS Manager and click on server name in left pane. Click on ARR icon shown in red square.
From right pane select Server Proxy Settings shown in red rectangle.
Here are proxy settings to configure.
Save settings and close ARR settings pages.
Options for external access
Now it’s time to decide how to make Plex available for public. There are two options:
- Plex under domain root. Plex is available directly from https://plex.mydomain.com/. Choose this option if Plex is the only web that is accessible from internet.
- Plex under subfolder. Plex is available from https://home.mydomain.com/plex/. Choose this option if there’s one domain for home network but multiple web sites in that are made accessible from internet.
These two are sample decisions. I expect reader to know his or her home network enough to make some analysis and decide which way to go.
Plex bugs with subfolder! It seems like Plex is not very well prepared to run under subfolder. If user is not authenticated to Plex and root folder is password protected then password dialog prompts for three or four times. Closing it with pressing Escape works and nothing is really broken afterwards. When successfully logged in these prompts go away.
Plex under root domain
In IIS Manager open URL Rewrite settings of site that accepts requests from public web. Register the following server variables:
- HTTP_ACCEPT_ENCODING
- HTTP_X_ORIGINAL_ACCEPT_ENCODING
- Sybsystem
For this click on URL Rewrite icon and select View Server Variables.
Using Add link on right pane it’s possible to add allowed server variables. Without these rewrite rules will not work as all allowed server variables must be registered here.
On hard disk create web.config file to web server root. Copy and paste following XML to web.config and save it.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <httpRuntime requestPathInvalidCharacters="" requestValidationMode="2.0" /> </system.web> <system.webServer> <rewrite> <rules> <clear /> <rule name="ReverseProxyInboundRule1" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false" /> <action type="Rewrite" url="http://192.168.1.22:32400/{R:1}" /> <serverVariables> <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" /> <set name="HTTP_ACCEPT_ENCODING" value="" /> </serverVariables> </rule> </rules> <outboundRules> <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding"> <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="true" /> <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" /> </rule> <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1"> <match filterByTags="A, Form, Img" pattern="^http(s)?://192.168.1.22:32400/(.*)" /> <action type="Rewrite" value="http{R:1}://media.mydomain.com/{R:2}" /> </rule> <preConditions> <preCondition name="ResponseIsHtml1"> <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" /> </preCondition> <preCondition name="NeedsRestoringAcceptEncoding"> <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" /> </preCondition> </preConditions> </outboundRules> </rewrite> <urlCompression doStaticCompression="false" doDynamicCompression="false" /> </system.webServer> </configuration>
Try out if Plex is available through external URL of home network.
Plex under subfolder
On hard disk create subfolder under web root for Plex. Add web.config file and paste following XML to it.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <httpRuntime requestPathInvalidCharacters="" requestValidationMode="2.0" /> </system.web> <system.webServer> <rewrite> <rules> <clear /> <rule name="ReverseProxyInboundRule1" stopProcessing="true"> <match url="(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="false" /> <action type="Rewrite" url="http://192.168.1.22:32400/{R:1}" /> <serverVariables> <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" /> <set name="HTTP_ACCEPT_ENCODING" value="" /> </serverVariables> </rule> </rules> <outboundRules> <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding"> <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" /> <conditions logicalGrouping="MatchAll" trackAllCaptures="true" /> <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" /> </rule> <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1"> <match filterByTags="A, Form, Img, Link, Script" pattern="^http(s)?://192.168.1.22:32400/(.*)" /> <action type="Rewrite" value="http{R:1}://home.mydomain.com/plex/{R:2}" /> </rule> <rule name="ReverseProxyOutboundRule2" preCondition="ResponseIsHtml1"> <match filterByTags="A, Form, Img, Link, Script" pattern="^\/web\/(.*)" /> <action type="Rewrite" value="https://media.mydomain.com/plex/{R:0}" /> </rule> <preConditions> <preCondition name="ResponseIsHtml1"> <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" /> </preCondition> <preCondition name="NeedsRestoringAcceptEncoding"> <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" /> </preCondition> </preConditions> </outboundRules> </rewrite> <urlCompression doStaticCompression="false" doDynamicCompression="false" /> </system.webServer> </configuration>
Save web.config file. In IIS Manager add new application under root web and point it to folder created before. Add same server variables in URL Rewrite settings as shown in previous point. Try out if Plex is available from public web.
Buggy URL-s! Like previously mentioned then due to Plex bugs some URL-s are not generated correctly. My list here:
- web/common/img/backgrounds/preset-dark.64cc1c942221cd2c153244bd8ecfb67a.png
- web/translations/en.json
- web/common/img/backgrounds/noise.8b05ce45d0df59343e206bc9ae78d85d.png
It’s possible to add additional rewrite rule for these URL-s in root site settings and avoid password prompts this way. If all users are known and the number is not big then there’s actually not much reason to bother about it.
Configuring Plex
Under Plex settings there are few things to configure:
- Settings => Remote Access: Set public port to 443 if you are using SSL
- Settings => Network: Set Custom server access URLs to either https://media.mydomain.com/ or https://home.mydomain.com/plex/ depending on which configuration you went.
Troubleshooting
If something goes wrong then information is in one of these places:
- Windows Event Log
- Trace files of IIS (usually c:\inetpub\logs ????)
If trace files are turned on but doesn’t appear then run iisreset.exe from command line as administrator.
I feel like you have taken the simplest piece of software available for home media access and done the most complicated thing possible to get it working. Just buy a plex pass – – if lots of clients are transcoding media from your server you will likely need hardware acceleration to handle the load, and you only get that with the pass anyway. It also comes with user management features that let you easily handle media sharing and permissions for both internet friends and internal users. They handle secure proxying for you through their servers to access yours, all you have to do is enable remote access.
I have enough power for transcoding and I’m sure Plex cloud has at least some annoying limits on this. It was horror experience to watch video when Plex cloud was on the way. It was slow, very laggy, connections timed out etc. After going with direct access these issues disappeared.
Thanks for this article I plan on using this with Emby media server. I thought about wap (web application proxy but I think I’m going with ARR.
If you know how WAP works and it’s good then go with it instead. I’m running Plex on my yesterday’s powerful laptop and it has Windows 10 Pro. So IIS + ARR is my only option when going with Microsoft solutions.
I have read your very helpful article at https://gunnarpeipman.com/various/plex-iis-reverse-proxy/
I run plex on my Windows Server Essentials 2016 with IIS installed.
Something doesnt work… after having finished your instruction, i CAN access
http(s)://www.mydomain.com:32400/plex. If I do not specify the port, I get a 404 not found.
If I set the port in plex to 443, it is no longer reachable. Port 443 and port 32400 are both forwarded to my server inside my router.
Can you help me to figure out what I am missing?
Thanks a lot!
Do you have port 443 allowed in your Plex machine firewall and can you access Plex through 443 when making direct request with no IIS on the way?
Does Plex have more bugs running under subfolder as of 2022?
Using your config results in some odd issues, on a server running Emby through a proxy with no issue, so it has ARR and URL rewrite
Suggestions?
It’s still problematic to get Plex running through reverse proxy. Not much has changed.
Great article, many thanks for that. Since your are an Azure fan and Microsoft MVP, maybe you can give a thought to my setup :-)
I am currently using the Azure AD Application proxy to make Plex available outside my network. From my perspective this has several advantages:
– with the Azure App proxy there is no need to open any port on my router, the app proxy connects outbound to the Azure backend. All external request to plex arrive in the Azure backend and are directed to the proxy server in my network through an open connection initiated by the proxy server itself
– I can use AAD authentication for plex as pre-authentication and could also use other security features like conditional access
So far so good the theory. I set everything and it works fine. I access the external address for plex, have to sign in to AAD and I am. Video streaming works as well in browser. Yet, there is a small but…
In browser it works fine but I would like that also the app works (and not rely on the plex builtin remote access). Yet, when i use the app externally the server is not found (you basically just have the plex.tv online stuff). I tried adding my external Plex DNS name to the plex server config “Custom server access URLs” but that didn’t help. I assume it is the AAD pre-authentication that the app cannot handle (but works of course in the browser) and thus shows the server to be not online/available when I am not in my local network.
Maybe you have an thoughts on that setup
Best regards
I have no experiences with hosting Plex behind app proxy. If it required AAD authentication then mobile apps probably can’t do it as they want to communicate with Plex API-s. AFAIK Plex apps are not wrappers around HTML+JS+CSS.
If there’s some URL pattern that API end-points follow then maybe it’s possible to make separate rules for apps?