Kothar Labs Contact Me

Plex, SSL and Nginx

Sun, 24 Mar 2013 / blog

I've been experimenting with the Plex Media Server, and decided to have a go at securing remote access to the 'Web Client' interface using SSL (by default it runs over an unencrypted HTTP connection).

This post is essentially a gathering of instructions from where I found them on the internet.


My server is set up as follows:

  • Ubuntu 12.04 64-bit
  • Latest Plex Media Server distribution
  • Nginx 1.3.14 development build (more on this later)

Installing Plex

Installing Plex is straightforward - I haven't deviated from the standard instructions at all.

These are the instructions for installing using apt, which will ensure all the necessary dependencies get installed:

For Ubuntu installation, add this to your /etc/apt/sources.list.d/plex.list file:

deb http://www.plexapp.com/repo lucid main

Then add the repository key:

$ wget http://plexapp.com/plex_pub_key.pub
$ sudo apt-key add plex_pub_key.pub
$ rm plex_pub_key.pub

Then install with the following command:

$ sudo apt-get update
$ sudo apt-get install plexmediaserver

Additional information can be found in the Linux PMS forum.

Installing Nginx

The current stable release of Nginx (1.2.x at the time of writing) doesn't support the WebSocket protocol, which is used in the Plex web interface to update the interface in real-time as the media server updates.

Luckily the latest development versions after 1.3.13 do support WebSocket, but they're not in the main Ubuntu package repository, for obvious reasons. You can install the latest version from a development package repository by following these instructions:

On Ubuntu you can install Nginx>=1.3.13 from Chris Lea's development branch PPA, as so,

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/nginx-devel
sudo apt-get update
sudo apt-get install nginx
nginx -v

Configuring Nginx

I have removed the default configuration from /etc/nginx/sites-enabled and created a new configuration called plex.

The first part of the configuration redirects connections on port 80 to the SSL connection on port 443. This is necessary because if you visit https://example.com/web, Plex will redirect you to http://example.com/web/index.html.

server {  
 rewrite ^(.*) https://$host$request_uri? permanent;  
}

This will automatically listen on port 80 on all network interfaces: you don't need to specify anything else unless you are using other virtual hosts.

The next part of the configuration defines the location of the Plex Media Server. For my setup, it's on the same system as Nginx:

upstream plex {  
 server 127.0.0.1:32400;  
}

Finally, the meat of the configuration sets up the SSL-enabled reverse proxy. This means we can map the SSL port (443) to the outside world via the external firewall, and access the Plex server using an encrypted connection.

server {
    listen 443;

    ssl on;
    ssl_certificate /etc/nginx/cert/server.crt;
    ssl_certificate_key /etc/nginx/cert/server.key;

    ## Settings to use client certificates for authentication
    ssl_client_certificate /etc/nginx/cert/Plex.pem;
    ssl_verify_client on;

    access_log  /var/log/nginx/plex.access.log;
    error_log  /var/log/nginx/plex.error.log;

    location / {
     proxy_pass  http://plex;
     proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
     proxy_redirect off;
     proxy_buffering off;
     proxy_set_header        Host            $host;
     proxy_set_header        X-Real-IP       $remote_addr;
     proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

     ## Required for Websockets
     proxy_http_version 1.1;
     proxy_set_header        Upgrade         $http_upgrade;
     proxy_set_header        Connection      "upgrade";
     proxy_read_timeout      36000s;  ## Timeout after 10 hours
   }
}

This should leave you with a working Plex/Web when you connect to https://plex.example.com/web

Warning! Connecting to the web interface by this method circumvents the Plex login. You need to enable some kind of authentication, otherwise anyone can connect to your server. If you want to use the standard plex login, you'll have to run the gateway on another system than the server itself and turn on authentication for systems on the local network, as it always allows connections from the same system as far as I can tell.

Authentication and Certificates

The SSL configuration requires a server certificate. I'm using a self-signed certificate for this, but you could get a free certificate from StartCom if you want something which won't trigger a browser warning. There are many guides to creating self-signed certificates online.

In the above example, I have enabled SSL Client Certificate authentication. This is using a self-generated certificate authority to sign access keys. There is a guide to generating the necessary files here.

As a more common use case, you could instead enable password authentication. Again, there are many guides to setting up auth_basic for Nginx, so I won't go into details. You just need to replace the ssl_client_certificate and ssl_verify_client options in the configuration above.