Jump to content

Apache Proxy Frontend for Emby


riothamus

Recommended Posts

riothamus

I have had a few people ask me to explain how I set up my Apache server to forward to my Emby server.  Here is a breakdown of how mine is set up should anyone else wish to try this.  This is just my way of doing this (yeah, I know, Nginx exists but I have always been an Apache user).

Note that I use RPM based distributions, and my frontend Apache server is running on Fedora Server Edition (so that I can have the http/2 goodness).  My instructions will emphasize this type of Linux distribution, so you will need to read up on how your particular flavor of Linux handles Apache installations.

First off, here is an overview of my network.  Everyone's network is different, but this is what I have set up:

edge firewall -> wireless ap/firewall -> apache server -> media server (where the media files are actually stored)

On my firewalls, I only have ports 80 and 443 tcp opened up, and they forward to my Apache server.  No other ports are exposed to the Internet.

My Emby server is not configured with SSL.  All SSL is terminated at my Apache server.  This way, I can use one SSL certificate to encrypt any web services that I run on my network, without trying to get a certificate for each individual server installation.  Anything that comes in on port 80 automatically gets forced over to port 443 (this is done by my Apache server itself).  I am also using HTTP/2 which has helped with the various web services that my Apache frontend is exposing to the web.  Also, all of my internal servers are running host-based firewalls.  There is nothing wrong with security in depth here, and I have personally not heard a valid reason to not run a host-based firewall for your networking services.

I use https://letsencrypt.org/ for my SSL certificate.  It's free, and their tools are awesome.  If you use their services, please donate to them as they are providing a valuable service to practically every community.

I also have my own domain name set up and registered, with a dynamic IP from my ISP.  There are a plethora of services that will let you register your dynamic IP for a domain name, so search around for the one that suits you best.  Personally, I am using Google Domains for mine.  My firewall assists in keeping my latest IP registered for my domain.  This is extremely handy for mobile devices and family members who wish to use my Emby server remotely.

Here are the general steps I would recommend to someone setting this up for themselves:

  • Use an edge firewall.  The extra protection is worth it.
  • Use your edge firewall to keep track of your public IP, and use whatever agent that your dynamic DNS provider provides to keep your latest IP registered for your domain.  I do not recommend doing this from your Apache server, as your Apache server should be further into your network and protected by your other firewall(s).
  • Set up an SSL certificate for your domain.  Again, LetsEncrypt is pretty awesome.
  • Install Apache on a server that can handle a fair amount of network traffic.  If you are using LetsEncrypt, set up the agent to keep up with your SSL certificate on this server.   
dnf groupinstall "Web Server"
dnf install mod_http2
  • Configure your Apache server.  On a Fedora, CentOS, RHEL system create a file called /etc/httpd/conf.d/00_yourdomain.conf  (the two zeroes are there to make sure that your domain file is loaded first).  Here are snippets of my configuration (cleaned up a bit for, you know, security):
<VirtualHost *:80>
	Protocols h2c http/1.1
	# Send everything over to https instead, best practice over mod_rewrite
	ServerName example.com
	Redirect / https://example.com/
</VirtualHost>
   
<VirtualHost _default_:443>
        # Enable http/2
        Protocols h2 http/1.1
 
        <IfModule http2_module>
          LogLevel http2:info
        </IfModule>

        SSLEngine on
        SSLProtocol all -SSLv2 -SSLv3
        SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DH-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
        SSLHonorCipherOrder On
        SSLCompression off
        Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"
        Header always set X-Frame-Options SAMEORIGIN
        Header always set X-Content-Type-Options nosniff

        SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
        SSLCertificateChainFile /etc/letsencrypt/live/example.com/fullchain.pem

        <Files ~ "\.(cgi|shtml|phtml|php3?)$">
           SSLOptions +StdEnvVars
        </Files>
        <Directory "/var/www/cgi-bin">
           SSLOptions +StdEnvVars
        </Directory>

        BrowserMatch "MSIE [2-5]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0

        ServerName example.com
        ServerAlias example.com
        ErrorLog logs/example-error_log
	  
        RewriteEngine on
        RewriteRule ^/emby(.*)    http://127.0.0.1:8096/emby$1 [proxy]
        RewriteRule ^/emby http://127.0.0.1:8096 [proxy]
        RewriteRule ^/embywebsocket(.*)    http://127.0.0.1:8096/embywebsocket$1 [proxy]
        RewriteRule ^/embywebsocket http://127.0.0.1:8096 [proxy]
        <location /emby>
           ProxyPass  http://127.0.0.1:8096/
           ProxyPassReverse  http://127.0.0.1:8096/
        </location>
        <location /embywebsocket>
           ProxyPass  http://127.0.0.1:8096/
           ProxyPassReverse  http://127.0.0.1:8096/
        </location>
</VirtualHost>

So what this does for me is let Apache handle all incoming port 80 requests, and turns them into encrypted traffic.  All connections to and from the server (that can support it) are encapsulated in HTTP/2 packets.  All of my SSL encrypted web traffic is handled by one certificate, so I can have multiple URL paths served by the same domain name, with only the https port used, and it just plain looks cleaner.  For example, you can have:

   https://example.com/emby
   https://example.com/nextcloud
   https://example.com/hello_kitty_island_adventure
   
Or whatever suits your needs.  My Emby server doesn't have to worry about any proxy configurations or SSL, as Apache takes care of all of that.  My example is using the localhost IP address to direct all incoming and outgoing Emby requests, but if you are using a separate host that runs Emby, just make sure to use the IP of that system instaed and that you have port 8096 open and available.

I hope that others may find this helpful.

Edited by riothamus
  • Like 1
Link to comment
Share on other sites

Jägs

Thanks!  Picking this up from our git conversation, so others can benefit.

 

Unfortunately, I'm still having issues, and it's likely operator error, so please bear with me.  Just for the sake of clarity, I'm running Ubuntu 18.04 with Apache and Emby, as well as Subsonic for my audio.

 

I've been able to get the reverse proxy to work with Subsonic, no problem, and here's my subsonic.conf file from sites-enabled:

 ProxyPass        /music http://127.0.1.1:8080/music
 ProxyPassReverse /music http://127.0.1.1:8080/music
 
 <Location /music>
    Order allow,deny
    Allow from all
    #SSLCipherSuite HIGH:MEDIUM
    #SSLRequireSSL
    #AuthName "BorkaBorkaBork"
    #AuthType Basic
    #AuthUserFile /etc/httpd/conf.d/htpasswd
    #Require valid-user
 </Location>

On the Emby side--again, it runs on the same server as both Subsonic and Apache--I removed my LE PFX file from the Advanced --> Hosting page in Emby and set it back to have the secure connection disabled.  I then created emby.conf in sites-available, with the following from your example above:

RewriteEngine on
RewriteRule ^/emby(.*)    http://127.0.0.1:8096/emby$1 [proxy]
RewriteRule ^/emby http://127.0.0.1:8096 [proxy]
RewriteRule ^/embywebsocket(.*)    http://127.0.0.1:8096/embywebsocket$1 [proxy]
RewriteRule ^/embywebsocket http://127.0.0.1:8096 [proxy]
<location /emby>
ProxyPass  http://127.0.0.1:8096/
ProxyPassReverse  http://127.0.0.1:8096/
</location>
<location /embywebsocket>
ProxyPass  http://127.0.0.1:8096/
ProxyPassReverse  http://127.0.0.1:8096/
</location>

I created a softlink for emby.conf to sites-enabled, restarted Emby and Apache, and gave it a try.  Here's what's happening:

Now, on Subsonic, I had to make sure it's path was <web>/music.  Is there a setting I'm missing on Emby to do the same?

Edited by Jägs
Link to comment
Share on other sites

riothamus

Which version of Apache are you using? 

 

Also, could you add the following 2 directives to your emby.conf file:

ErrorLog logs/example-error_log
LogFormat "%t \"%r\" %>s" common
CustomLog logs/emby-access_log common

Then restart your Apache server.  Try again, and tail your logs to see what's happening in real-time.  I don't believe that your setup is actually passing traffic back to Emby.

Link to comment
Share on other sites

Jägs

Thanks for your help! Here’s the version of Apache I’m running:

 

Apache/2.4.29 (Ubuntu)

 

Note: short of enabling the proxy modules, I’m running the stock install from the Ubuntu package.

 

I added the following to my emby.conf file and restarted Apache:

 

ErrorLog ${APACHE_LOG_DIR}/emby-error_log

LogFormat "%t \"%r\" %>s" common

CustomLog ${APACHE_LOG_DIR}/emby-access_log common

 

I then tried to access both https://example.com/emby and https://example.com/embywebsocket, both of which returned 404 errors at the path /web/index.html. Unfortunately, nothing showed up in the logs:

 

::::::::::::::

emby-access_log

::::::::::::::

::::::::::::::

emby-error_log

::::::::::::::

[Mon Aug 06 22:01:50.738268 2018] [mpm_event:notice] [pid 29278:tid 139863243697088] AH00489: Apache/2.4.29 (Ubuntu) OpenSSL/1.1.0g configured -- resuming normal operations

[Mon Aug 06 22:01:50.738446 2018] [core:notice] [pid 29278:tid 139863243697088] AH00094: Command line: '/usr/sbin/apache2'

 

I also did not see anything relevant in error.log, but similar entries to this was in access.log:

 

access.log:xxx.xxx.xxx.xxx - - [06/Aug/2018:22:02:38 -0500] "GET /web/index.html HTTP/1.1" 404 532 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"

 

Any idea what’s going on?

Link to comment
Share on other sites

riothamus

From the looks of it, nothing is hitting your Emby instance (as indicated by the empty logs for Emby's httpd configuration). 

 

I haven't used Apache on a Debian based distro before.  I'll set up a VM and try it out to see if I can help track down what's happening here.

Link to comment
Share on other sites

Jägs

Here's my other Apache conf files, if it helps:

 

000-default.conf

<VirtualHost *:80>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@[member="Localhost"]
	DocumentRoot /media/docs/www

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf
RewriteEngine on
RewriteCond %{SERVER_NAME} =home.example.com [OR]
RewriteCond %{SERVER_NAME} =example.duckdns.org
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

000-default-le-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
	# The ServerName directive sets the request scheme, hostname and port that
	# the server uses to identify itself. This is used when creating
	# redirection URLs. In the context of virtual hosts, the ServerName
	# specifies what hostname must appear in the request's Host: header to
	# match this virtual host. For the default virtual host (this file) this
	# value is not decisive as it is used as a last resort host regardless.
	# However, you must set it for any further virtual host explicitly.
	#ServerName www.example.com

	ServerAdmin webmaster@[member="Localhost"]
	DocumentRoot /media/docs/www

	# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
	# error, crit, alert, emerg.
	# It is also possible to configure the loglevel for particular
	# modules, e.g.
	#LogLevel info ssl:warn

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	# For most configuration files from conf-available/, which are
	# enabled or disabled at a global level, it is possible to
	# include a line for only one particular virtual host. For example the
	# following line enables the CGI configuration for this host only
	# after it has been globally disabled with "a2disconf".
	#Include conf-available/serve-cgi-bin.conf


ServerName home.example.com
Include /etc/letsencrypt/options-ssl-apache.conf
ServerAlias example.duckdns.org
SSLCertificateFile /etc/letsencrypt/live/home.example.com/fullchain.pem
</VirtualHost>
</IfModule>
Link to comment
Share on other sites

riothamus

Got an Ubuntu 18.04 vm setup.  I'll play with it some to see if I can replicate your issue.

 

Just to be sure, do you have mod_rewrite enabled?

a2enmod rewrite
Link to comment
Share on other sites

riothamus

Ok, I was able to reproduce a similar-ish issue on Apache with Ubuntu.

 

So, make sure that you have the proxy_http module loaded:

sudo a2enmod proxy_http

Then, change your proxy location to this:

<location /emby>
   ProxyPass  http://127.0.0.1:8096/emby
   ProxyPassReverse  http://127.0.0.1:8096/emby
</location>
<location /embywebsocket>
   ProxyPass  http://127.0.0.1:8096/embywebsocket
   ProxyPassReverse  http://127.0.0.1:8096/embywebsocket
</location>

Check your configuration files:

apache2ctl -t

Then restart Apache:

sudo systemctl restart apache2.service

Then try to load the page (use a private browsing window first for testing).

 

Also, for what it's worth, I named the Emby configuration file for Apache as 001-emby.conf in the sites-available folder, and enabled it via Apache's tool:

sudo a2ensite 001-emby
# If you follow this route, you'll need to restart Apache again
sudo systemctl restart apache.service

I kept it simple and avoided SSL on the test VM, as it looked as if your original issue was that the proxy was not properly receiving your request for Emby to begin with.

 

If you are still having issues, I would recommend that you open a separate terminal and tail your logs to see what is happening in real-time while you test your site:

sudo tail -f /var/log/apache2/access.log

I imagine you know how to troubleshoot a server, just including the play-by-play for those who may be new to this, and for future reference.

 

Edited by riothamus
  • Like 1
Link to comment
Share on other sites

Jägs

I did have both modules enabled, but the tweak to the proxy locations in the conf file did the trick.

 

Thanks so much for taking the time to help me, here!  I really appreciate it!

 

And in case anyone needs it, here's my working emby.conf:

ErrorLog ${APACHE_LOG_DIR}/emby-error_log
LogFormat "%t \"%r\" %>s" common
CustomLog ${APACHE_LOG_DIR}/emby-access_log common

RewriteEngine on
RewriteRule ^/emby(.*)    http://127.0.0.1:8096/emby$1 [proxy]
RewriteRule ^/emby http://127.0.0.1:8096 [proxy]
RewriteRule ^/embywebsocket(.*)    http://127.0.0.1:8096/embywebsocket$1 [proxy]
RewriteRule ^/embywebsocket http://127.0.0.1:8096 [proxy]

<location /emby>
ProxyPass  http://127.0.0.1:8096/emby
ProxyPassReverse  http://127.0.0.1:8096/emby
</location>

<location /embywebsocket>
ProxyPass  http://127.0.0.1:8096/embywebsocket
ProxyPassReverse  http://127.0.0.1:8096/embywebsocket
</location>
Edited by Jägs
Link to comment
Share on other sites

Jägs

One other question:  what's the purpose of the embywebsocket location?  Do clients use this for some specific purpose?

Edited by Jägs
Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...