Jump to: navigation, search

Difference between revisions of "Jetty/Howto/Configure mod proxy"

< Jetty‎ | Howto
(New page: {{{Jetty Howto | introduction = (required) == Configuring Apache mod_proxy with Jetty == The Apache web server is frequently used as a server in front of a servlet container.<br /> While ...)
 
(4 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{{Jetty Howto
+
{{Jetty Howto
| introduction = (required)
+
| introduction =
== Configuring Apache mod_proxy with Jetty ==
+
 
 +
{{Jetty TODO}}
  
 
The Apache web server is frequently used as a server in front of a servlet container.<br /> While there are no real technical reasons to front Jetty with apache, sometimes this is needed<br /> for software load balancing, or to fit with a corporate infrastructure, or simply to stick with a known deployment structure.
 
The Apache web server is frequently used as a server in front of a servlet container.<br /> While there are no real technical reasons to front Jetty with apache, sometimes this is needed<br /> for software load balancing, or to fit with a corporate infrastructure, or simply to stick with a known deployment structure.
 +
 +
== Configuring Apache mod_proxy with Jetty ==
  
 
Ways to connect Apache to Jetty include:
 
Ways to connect Apache to Jetty include:
Line 37: Line 40:
 
<source lang="text">  
 
<source lang="text">  
 
  LoadModule proxy_module modules/mod_proxy.so
 
  LoadModule proxy_module modules/mod_proxy.so
</source>
+
</source>  
 +
Apache 2.2 normally bundles mod_proxy, mod_proxy_ajp, and mod_proxy_balancer, so often you do not need to install them separately. If they are bundled separately in your operating system, for example, as RPMs or Debians, be sure to install them.
 +
# Turn off forward proxy.
 
<source lang="text">  
 
<source lang="text">  
 
  ProxyRequests Off
 
  ProxyRequests Off
Line 46: Line 51:
 
  </Proxy>
 
  </Proxy>
 
</source>
 
</source>
# Configure reverse proxy paths with the URL of the Jetty server: <source lang="text">  
+
# Configure reverse proxy paths with the URL of the Jetty server:  
 +
<source lang="text">  
 
  ProxyPass /test http://localhost:8080/test
 
  ProxyPass /test http://localhost:8080/test
 
</source>
 
</source>
# Frequently Apache documentation instructs that you use <tt>ProxyPassReverse</tt> configuration so that Apache can rewrite any URLs in headers. However, if you use the <tt>ProxyPreserveHost</tt> configuration, Jetty can generate the correct URLs, and rewriting is not necessary: <br class="atl-forced-newline" /><source lang="text">  
+
# Frequently Apache documentation instructs that you use <tt>ProxyPassReverse</tt> configuration so that Apache can rewrite any URLs in headers. However, if you use the <tt>ProxyPreserveHost</tt> configuration, Jetty can generate the correct URLs, and rewriting is not necessary:  
 +
<source lang="text">  
 
  ProxyPreserveHost On
 
  ProxyPreserveHost On
</source>Alternatively, since Jetty 6.1.10, instead of preserving the host and to retrieve the client remote address in the webapp (<tt>ServletRequest#getRemoteAddr()</tt>), you can use the [/display/JETTY/Configuring+Connectors#ConfiguringConnectors-forwarded forwarded] property on <tt>AbstractConnector</tt>, which interprets the [http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers mod_proxy_http "x-forwarded-" headers] instead:<source lang="XML">  
+
</source>
 +
 
 +
Alternatively, since Jetty 6.1.10, instead of preserving the host and to retrieve the client remote address in the webapp (<tt>ServletRequest#getRemoteAddr()</tt>), you can use the <tt>forwarded</tt> property on <tt>AbstractConnector</tt>, which interprets the [http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers mod_proxy_http "X-Forwarded-*" headers] instead:
 +
 
 +
<source lang="XML">  
 
  <Configure id="Server" class="org.eclipse.jetty.Server">
 
  <Configure id="Server" class="org.eclipse.jetty.Server">
 
   ...
 
   ...
Line 64: Line 75:
 
   ...
 
   ...
 
  </Configure>
 
  </Configure>
</source>Or, to force the result of <tt>ServletRequest#getServerName()</tt> and <tt>ServletRequest#getServerPort()</tt> (if headers are not available):<source lang="XML">  
+
</source>
 +
 
 +
Or, to force the result of <tt>ServletRequest#getServerName()</tt> and <tt>ServletRequest#getServerPort()</tt> (if headers are not available):
 +
 
 +
<source lang="XML">  
 
  <Configure id="Server" class="org.eclipse.jetty.Server">
 
  <Configure id="Server" class="org.eclipse.jetty.Server">
 
   ...
 
   ...
Line 78: Line 93:
 
   ...
 
   ...
 
  </Configure>
 
  </Configure>
</source><br class="atl-forced-newline" />
+
</source>
# It is also very useful to turn on proxy status monitoring (see management below): <br class="atl-forced-newline" /><source lang="text">
+
 
 +
# It is also very useful to turn on proxy status monitoring (see management below):  
 +
 
 +
<source lang="text">
 
  ProxyStatus On
 
  ProxyStatus On
 
</source>
 
</source>
Line 89: Line 107:
 
<source lang="text">
 
<source lang="text">
  
<nowiki>
 
 
   https                http
 
   https                http
 
  --------->  Apache  -------> Jetty
 
  --------->  Apache  -------> Jetty
Line 109: Line 126:
  
 
</source>
 
</source>
 +
 +
Read this [https://bitbucket.org/Nowaker/jetty-https article] to achieve the same thing without coding.
 +
 +
An even easier way to achieve this with Jetty 9 + Apache 2.2 is this: add
 +
<source lang="text">
 +
    RequestHeader set X-Forwarded-Proto "https" env=HTTPS
 +
</source>
 +
to your Apache configuration (adapted from [http://www.gossamer-threads.com/lists/apache/users/407272 this forum post] and [http://serverfault.com/a/453854/155490 ServerFault.com]).
  
 
If you need access on Jetty to some of the SSL information accessible on Apache, then you need to do some configuration tricks on Apache to insert the SSL info as headers on outgoing requests. Follow the Apache configuration suggestions on this [http://www.zeitoun.net/articles/client-certificate-x509-authentication-behind-reverse-proxy/start tutorial], which shows you how to use <tt>mod_headers</tt> to insert the appropriate request headers. Of course you will also need to code your application to look for the corresponding custom request headers bearing the ssl information.
 
If you need access on Jetty to some of the SSL information accessible on Apache, then you need to do some configuration tricks on Apache to insert the SSL info as headers on outgoing requests. Follow the Apache configuration suggestions on this [http://www.zeitoun.net/articles/client-certificate-x509-authentication-behind-reverse-proxy/start tutorial], which shows you how to use <tt>mod_headers</tt> to insert the appropriate request headers. Of course you will also need to code your application to look for the corresponding custom request headers bearing the ssl information.
Line 116: Line 141:
 
With Apache 2.2 [http://httpd.apache.org/docs/2.2/mod/mod_proxy.html mod_proxy] is able to use the extension [http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html mod_proxy_balancer].
 
With Apache 2.2 [http://httpd.apache.org/docs/2.2/mod/mod_proxy.html mod_proxy] is able to use the extension [http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html mod_proxy_balancer].
  
===Configuration===
+
===Configuring mod_proxy_balancer===
  
 
The configuration of mod_proxy_balancer is similar to pure mod_proxy, except that <tt>balancer://</tt> URLs may be used as a protocol instead of <tt>http://</tt> when specifying destinations (workers) in <tt>ProxyPass</tt> elements. <br class="atl-forced-newline" />
 
The configuration of mod_proxy_balancer is similar to pure mod_proxy, except that <tt>balancer://</tt> URLs may be used as a protocol instead of <tt>http://</tt> when specifying destinations (workers) in <tt>ProxyPass</tt> elements. <br class="atl-forced-newline" />
Line 122: Line 147:
 
<source lang="text">
 
<source lang="text">
  
<nowiki>
 
 
  # map to cluster with session affinity (sticky sessions)
 
  # map to cluster with session affinity (sticky sessions)
 
  ProxyPass /balancer !
 
  ProxyPass /balancer !
Line 131: Line 155:
 
     BalancerMember http://yourjetty2:8080 route=jetty2
 
     BalancerMember http://yourjetty2:8080 route=jetty2
 
  </Proxy>
 
  </Proxy>
 
 
</source>
 
</source>
  
<br class="atl-forced-newline" />'''Proxy balancer://''' - defines the nodes (workers) in the cluster. Each member can be a <tt>http://</tt> or <tt>ajp://</tt> URL or another <tt>balancer://</tt> URL for cascaded load balancing configuration.<br /> If the worker name is not set for the Jetty servers, then session affinity (sticky sessions) will not work. The JSESSIONID cookie must have the format <tt><sessionID>.<worker name></tt>, in which <tt>worker name</tt> has the same value as the <tt>route</tt> specified in the BalancerMember above (in this case "jetty1" and "jetty2"). See [http://www.markround.com/archives/33-Apache-mod_proxy-balancing-with-PHP-sticky-sessions.html this article] for details. The following can be added to the <tt>jetty-web.xml</tt> in the <tt>WEB-INF</tt> directory to set the worker name.
+
''Proxy balancer://'' defines the nodes (workers) in the cluster. Each member can be a <tt>http://</tt> or <tt>ajp://</tt> URL or another <tt>balancer://</tt> URL for cascaded load balancing configuration.
 +
 
 +
If the worker name is not set for the Jetty servers, then session affinity (sticky sessions) does not work. The JSESSIONID cookie must have the format <tt><sessionID>.<worker name></tt>, in which <tt>worker name</tt> has the same value as the <tt>route</tt> specified in the BalancerMember above (in this case "jetty1" and "jetty2"). See [http://www.markround.com/archives/33-Apache-mod_proxy-balancing-with-PHP-sticky-sessions.html this article] for details. You can add the following to the <tt>jetty-web.xml</tt> in the <tt>WEB-INF</tt> directory to set the worker name.
  
 
<source lang="XML">
 
<source lang="XML">
Line 155: Line 180:
 
</source>
 
</source>
  
==Management==
+
==Managing mod_proxy_balancer==
  
Apache provides [http://httpd.apache.org/docs/2.2/mod/mod_status.html mod_status] and [http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html#enable Balancer Manager Support] so that the status of the proxy and balancer can be viewed on a web page. The following configuration enables these UIs at /balancer and /status URLs:
+
Apache provides [http://httpd.apache.org/docs/2.2/mod/mod_status.html mod_status] and [http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html#enable Balancer Manager Support] so that you can view the status of the proxy and balancer on a web page. The following configuration enables these UIs at /balancer and /status URLs:
  
 
<source lang="text">
 
<source lang="text">

Revision as of 10:22, 27 August 2013



Introduction

Warning2.png
Some or all of this content remains to be ported to Jetty 9 Documentation.
If you are interested in migrating this content see our contribution guide or contact us.


The Apache web server is frequently used as a server in front of a servlet container.
While there are no real technical reasons to front Jetty with apache, sometimes this is needed
for software load balancing, or to fit with a corporate infrastructure, or simply to stick with a known deployment structure.

Configuring Apache mod_proxy with Jetty

Ways to connect Apache to Jetty include:

  • Using Apache mod_proxy and an normal Jetty HTTP connector.
  • Using Apache mod_proxy_ajp and the Jetty AJP connector.
  • Using Apache mod_jk and the Jetty AJP connector.

We recommend using the HTTP connectors for the following reasons:

  • Jetty performs significantly better with HTTP.
  • The AJP protocol is poorly documented and has many version irregularities.

If you must use AJP, the mod_proxy_ajp module is better than mod_jk. Previously, the load balancing capabilities of mod_jk meant that you had to use (tolerate) it, but with Apache 2.2, mod_proxy_balancer is available and works over HTTP and AJP connectors.

mod_proxy

A mod_proxy module is available for almost all versions of Apache. However, prior to Apache 2.2, only reverse proxy features were available and mod_proxy_balancer was not available for load balancing.

Documentation for mod_proxy is available for:

Configuring mod_proxy as a Reverse Proxy]

The configuration file layout for Apache varies greatly with version and distribution, but to configure mod_proxy as a reverse proxy, the following is key:

  1. Configure Jetty with a normal HTTP connector, on port 8080 or similar.
  2. Load the proxy module (and any other proxy extension used):
 
 LoadModule proxy_module modules/mod_proxy.so

Apache 2.2 normally bundles mod_proxy, mod_proxy_ajp, and mod_proxy_balancer, so often you do not need to install them separately. If they are bundled separately in your operating system, for example, as RPMs or Debians, be sure to install them.

  1. Turn off forward proxy.
 
 ProxyRequests Off
 
 <Proxy *>
 Order deny,allow
 Allow from all
 </Proxy>
  1. Configure reverse proxy paths with the URL of the Jetty server:
 
 ProxyPass /test http://localhost:8080/test
  1. Frequently Apache documentation instructs that you use ProxyPassReverse configuration so that Apache can rewrite any URLs in headers. However, if you use the ProxyPreserveHost configuration, Jetty can generate the correct URLs, and rewriting is not necessary:
 
 ProxyPreserveHost On

Alternatively, since Jetty 6.1.10, instead of preserving the host and to retrieve the client remote address in the webapp (ServletRequest#getRemoteAddr()), you can use the forwarded property on AbstractConnector, which interprets the mod_proxy_http "X-Forwarded-*" headers instead:

 
 <Configure id="Server" class="org.eclipse.jetty.Server">
   ...
   <Call name="addConnector">
     <Arg>
       <New class="org.eclipse.jetty.nio.SelectChannelConnector">
         <Set name="port">8080</Set>
         <Set name="forwarded">true</Set>
       </New>
     </Arg>
   </Call>
   ...
 </Configure>

Or, to force the result of ServletRequest#getServerName() and ServletRequest#getServerPort() (if headers are not available):

 
 <Configure id="Server" class="org.eclipse.jetty.Server">
   ...
   <Call name="addConnector">
     <Arg>
       <New class="org.eclipse.jetty.nio.SelectChannelConnector">
         <Set name="port">8080</Set>
         <Set name="forwarded">true</Set>
         <Set name="hostHeader">example.com:81</Set>
       </New>
     </Arg>
   </Call>
   ...
 </Configure>
  1. It is also very useful to turn on proxy status monitoring (see management below):
 ProxyStatus On

Proxying SSL on Apache to HTTP on Jetty

The situation here is:

   https                 http
 --------->   Apache   -------> Jetty

If you want to offload the SSL onto Apache, and then use plain http requests to your Jetty backend, you need to configure Jetty to use https:// in all redirected requests.

You can do that by extending the Connector class of your choice, eg the SelectChannelConnector, and implement the customize(EndPoint, Request) method to force the scheme of the Request to be https like so ( don't forget to call super.customize(endpoint,request)! ):

 
 public void customize(org.eclipse.io.EndPoint endpoint, Request request) throws IOException
 {
     request.setScheme("https");
     super.customize(endpoint, request);
 }

Read this article to achieve the same thing without coding.

An even easier way to achieve this with Jetty 9 + Apache 2.2 is this: add

    RequestHeader set X-Forwarded-Proto "https" env=HTTPS

to your Apache configuration (adapted from this forum post and ServerFault.com).

If you need access on Jetty to some of the SSL information accessible on Apache, then you need to do some configuration tricks on Apache to insert the SSL info as headers on outgoing requests. Follow the Apache configuration suggestions on this tutorial, which shows you how to use mod_headers to insert the appropriate request headers. Of course you will also need to code your application to look for the corresponding custom request headers bearing the ssl information.

mod_proxy_balancer

With Apache 2.2 mod_proxy is able to use the extension mod_proxy_balancer.

Configuring mod_proxy_balancer

The configuration of mod_proxy_balancer is similar to pure mod_proxy, except that balancer:// URLs may be used as a protocol instead of http:// when specifying destinations (workers) in ProxyPass elements.

 # map to cluster with session affinity (sticky sessions)
 ProxyPass /balancer !
 ProxyPass / balancer:</nowiki>//my_cluster/ stickysession=jsessionid nofailover=On
 
 <Proxy balancer://my_cluster>
     BalancerMember http://yourjetty1:8080 route=jetty1
     BalancerMember http://yourjetty2:8080 route=jetty2
 </Proxy>

Proxy balancer:// defines the nodes (workers) in the cluster. Each member can be a http:// or ajp:// URL or another balancer:// URL for cascaded load balancing configuration.

If the worker name is not set for the Jetty servers, then session affinity (sticky sessions) does not work. The JSESSIONID cookie must have the format <sessionID>.<worker name>, in which worker name has the same value as the route specified in the BalancerMember above (in this case "jetty1" and "jetty2"). See this article for details. You can add the following to the jetty-web.xml in the WEB-INF directory to set the worker name.

 
 <Configure class="org.eclipse.jetty.webapp.WebAppContext">
   <Get name="sessionHandler">
     <Get name="sessionManager">
       <Call name="setIdManager">
         <Arg>
           <New class="org.eclipse.jetty.server.session.HashSessionIdManager">
             <Set name="WorkerName">jetty1</Set>
           </New>
         </Arg>
       </Call>
     </Get>
   </Get>
 </Configure>

Managing mod_proxy_balancer

Apache provides mod_status and Balancer Manager Support so that you can view the status of the proxy and balancer on a web page. The following configuration enables these UIs at /balancer and /status URLs:

 
 <Location /balancer>
 SetHandler balancer-manager
 
 Order Deny,Allow
 Deny from all
 Allow from all
 </Location>
 
 
 ProxyStatus On
 <Location /status>
 SetHandler server-status
 
 Order Deny,Allow
 Deny from all
 Allow from all
 </Location>

These UIs should be protected from external access.