Apache is the most widely used web server. If you are already using it, you can set up Apache httpd as a proxy for your Play application, instead of exposing it to the Internet directly.
This recipe shows you how to configure SSL and non-SSL Play applications together with the Apache httpd. This chapter features a couple of recipes on how to use a web server as a proxy for Play. In any configuration example one assumption is made: You want to use SSL, but you do not want to use the built-in SSL support of the Play framework, because you are using a proxy in front of your Play application. The forwarding from the external SSL port is done to the internal Play application. However, the internal application does not use SSL. This prevents doing encryption twice or redirecting SSL directly to the Play application. However, you still have to make sure the Play application handles the request as if it came via HTTPS.
The source code of the example application is available at examples/chapter7/ssl/example-app
as well as for examples/chapter7/ssl/example-app-2
for the second application instance, which is needed for clustering. The configuration files for the web server are put at examples/chapter7/apache
.
You should have an Apache 2 web server up and running. Furthermore, you should have the following modules enabled: mod_ssl
, mod_headers
, mod_proxy
, mod_proxy_http
, mod_proxy_balancer
. The last one is only needed in case you want to do load balancing. When using a Debian derived distribution like Ubuntu, you can use the a2enmod
command, for example a2enmod ssl
to enable the SSL module.
The only thing you need to change on your Play application.conf
, is the configuration about proxies, which redirect to Play. The IP referenced here is the one from the host Apache runs on:
XForwardedSupport=192.168.0.1
This is a simple Apache configuration for redirecting from external port 80 to internal IP and port 9000 of your Play application.
Be aware that the configuration snippets are highly specific and might not work with your Apache configuration. If you have a web server with several virtual domains you have to specify a name in the <VirtualHost>
directive. The snippets here have been tried without any other virtual hosts running on the apache instance. Please refer to the Apache documentation when having a more complex setup.
<VirtualHost *:80> ProxyPreserveHost on ProxyPass / http://192.168.0.2:9000/ ProxyPassReverse / http://192.168.0.2:9000/ </VirtualHost>
Now a configuration for redirecting an external SSL connection to internal HTTP, but still making sure it is handled as SSL by the Play application:
<VirtualHost *:443> SSLEngine on SSLCertificateFile /etc/ssl/host.crt SSLCertificateKeyFile /etc/ssl/host.key ProxyPreserveHost on ProxyPass / http://192.168.0.2:9000/ ProxyPassReverse / http://192.168.0.2:9000/ RequestHeader set "X-Forwarded-SSL" "on" RequestHeader set "X-Forwarded-Proto" "https" </VirtualHost>
The main difference here is the enabling of SSL and adding a special header, which will tell Play to mark this request as secure.
The next possible step is to cluster your application by running it on several nodes:
<Proxy balancer://playcluster> BalancerMember http://192.168.0.2:9000 BalancerMember http://192.168.0.3:9000 </Proxy> <VirtualHost *:80> ProxyPreserveHost on ProxyPass / balancer://playcluster/ ProxyPassReverse / balancer://playcluster/ </VirtualHost>
The Play configuration itself is merely a security feature. The support for proxy forwarding should be done explicitly. Instead of a single IP address you can also supply a comma separated list of IP addresses.
Depending on your setup, for example either by using localhost or only IP addresses, you also might have to use the ProxyPassReverseCookieDomain
to make sure session cookies are set and handled correctly. Furthermore, it is not the best idea to use a wild card virtual host definition, but rather use name or IP-based virtual hosts. This has just been done out of convenience in this case. Also you should make sure to really use the RequestHeader
instead of the Header
directive to add the needed headers, as this directive ensures the headers are set before the request is forwarded to Play.
If you are seeking an answer about why the SSL code works and is then set up correctly, the answer is simple. This is a framework convention. You can read about it directly in the source at play.mvc.Http.Request.parseXForwarded()
.
Regarding load balancing, you need to replace the real hostname in the proxy-specific directive with the balancer configuration. As the Play framework has been designed as a real share nothing system, there is no need to add complex configurations like sticky session IDs, where load balancing is done by keeping the session ID of a node mapped to the application server instance, which always means to keep state on the redirect host. The configuration for SSL has to be done accordingly.
Also be aware that the trailing slash in the ProxyPass
and ProxyPassReverse
directives is absolutely essential, regardless of whether you are doing balanced or single forwarding, because you have to match to a URL in this case.
As Apache is widely used, there is not much point in showing off other features that aren't needed. However, you can even do transparent upgrades of your applications with zero downtime!
As this feature of upgrading your application without any downtime is already written in the documentation, it does not make any sense to talk about it in this book, so just check out http://www.playframework.org/documentation/1.1.1/production#Apacheasafrontproxytoallowtransparentupgradeofyourapplication.
3.15.186.79