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.

Plex behind reverse proxy

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):

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.

IIS ARR settings

From right pane select Server Proxy Settings shown in red rectangle.

IIS ARR settings

Here are proxy settings to configure.

IIS ARR settings

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.

IIS URL Rewrite settings

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.

IIS URL Rewrite - Allowed Server Variables

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:

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.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    10 thoughts on “Plex behind IIS reverse proxy

    • February 16, 2019 at 4:36 pm
      Permalink

      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.

    • February 16, 2019 at 8:29 pm
      Permalink

      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.

    • February 19, 2019 at 10:18 pm
      Permalink

      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.

    • February 20, 2019 at 12:47 am
      Permalink

      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.

    • May 20, 2019 at 4:42 pm
      Permalink

      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!

    • May 20, 2019 at 5:03 pm
      Permalink

      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?

    • January 21, 2022 at 12:58 pm
      Permalink

      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?

    • February 1, 2022 at 9:31 am
      Permalink

      It’s still problematic to get Plex running through reverse proxy. Not much has changed.

    • July 6, 2022 at 12:07 am
      Permalink

      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

    • July 21, 2022 at 9:04 pm
      Permalink

      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?

    Leave a Reply

    Your email address will not be published. Required fields are marked *