Running Jenkins behind Apache

Skip to end of metadata
Go to start of metadata

In situations where you have existing web sites on your server, you may find it useful to run Jenkins (or the servlet container that Jenkins runs in) behind Apache, so that you can bind Jenkins to the part of a bigger website that you may have. This document discusses some of the approaches for doing this.

Make sure that you change the Jenkins httpListenAddress from its default of 0.0.0.0 to 127.0.0.1 or any Apache-level restrictions can be easily bypassed by hitting the Jenkins port directly.

mod_proxy

mod_proxy works by making Apache perform "reverse proxy" — when a request arrives for certain URLs, Apache becomes a proxy and further forward that request to Jenkins, then it forwards the response back to the client.

The following Apache modules must be installed :

a2enmod proxy
a2enmod proxy_http

A typical set up for mod_proxy would look like this:

ProxyPass         /jenkins  http://localhost:8081/jenkins nocanon
ProxyPassReverse  /jenkins  http://localhost:8081/jenkins
ProxyRequests     Off
AllowEncodedSlashes NoDecode

# Local reverse proxy authorization override
# Most unix distribution deny proxy by default (ie /etc/apache2/mods-enabled/proxy.conf in Ubuntu)
<Proxy http://localhost:8081/jenkins*>
  Order deny,allow
  Allow from all
</Proxy>

This assumes that you run Jenkins on port 8081.

For this set up to work, the context path of Jenkins must be the same between your Apache and Jenkins (that is, you can't run Jenkins on http://localhost:8081/ci and have it exposed at http://localhost:80/jenkins).
Set the context path in Windows by modifying the jenkins.xml configuration file and adding --prefix=/jenkins (or similar) to the <arguments> entry.
Set the context path  when using the Ubuntu package by adding --prefix=/jenkins to JENKINS_ARGS in /etc/default/jenkins ( or in /etc/sysconfig/jenkins for RHEL/CentOS package)

The ProxyRequests Off prevents Apache from functioning as a forward proxy server (except for ProxyPass), it is advised to include it unless the server should function as a proxy.

Both the nocanon option to ProxyPass, and AllowEncodedSlashes NoDecode, are required for certain Jenkins features to work.
If you are running Apache on a Security-Enhanced Linux (SE-Linux) machine it is essential to make SE-Linux do the right thing by issuing as root
setsebool -P httpd_can_network_connect true

If this is not issued Apache will not be allowed to forward proxy requests to Jenkins and only an error message will be displayed.

Because Jenkins already compress its output, you can not use the normal proxy-html filter to modify urls:
SetOutputFilter proxy-html

Instead you can use the following:

SetOutputFilter INFLATE;proxy-html;DEFLATE
ProxyHTMLURLMap http://your_server:8080/jenkins /jenkins

http://wiki.uniformserver.com/index.php/Reverse_Proxy_Server_2:_mod_proxy_html_2
But since Jenkins seems to be well behaved it's even better to just not use SetOutputFilter and ProxyHTMLURLMap.

If there are problems with Jenkins sometimes servicing random garbage pages, then the following may help:
SetEnv proxy-nokeepalive 1
Some plug-ins determine URLs from client requests from Host header, so if you experience some problems with wrong URLs, you can try to switch on ProxyPreserveHost directive, which is switched off by default:
ProxyPreserveHost On

mod_proxy with HTTPS

If you'd like to run Jenkins with reverse proxy in HTTPS, one user reported that HTTPS needs to be terminated at Jenkins, not at the front-end Apache. See this e-mail thread for more discussion.

Alternatively, you can add an additional ProxyPassReverse directive to redirect non-SSL URLs generated by Jenkins to the SSL side. Assuming that your webserver is your.host.com, placing the following within the SSL virtual host definition will do the trick:

ProxyRequests     Off
ProxyPreserveHost On

<Proxy http://localhost:8081/jenkins*>
  Order deny,allow
  Allow from all
</Proxy>

ProxyPass         /jenkins  http://localhost:8081/jenkins
ProxyPassReverse  /jenkins  http://localhost:8081/jenkins
ProxyPassReverse  /jenkins  http://your.host.com/jenkins

Yet another option is to rewrite the Location headers that contain non-ssl URL's generated by Jenkins. If you want to access Jenkins from https://www.example.com/jenkins, placing the following within the SSL virtual host definition also works:

ProxyRequests     Off
ProxyPreserveHost On
ProxyPass /jenkins/ http://localhost:8081/jenkins/
<Location /jenkins/>
  ProxyPassReverse /
  Order deny,allow
  Allow from all
</Location>
Header edit Location ^http://www.example.com/jenkins/ https://www.example.com/jenkins/

mod_ajp/mod_proxy_ajp

More info welcome. Probably we should move the contents from here

I wanted to have Jenkins running in a different workspace than my normal Tomcat server, but both available via the Apache web server. So, first up, modify Jenkins to use a different web and ajp port than Tomcat:

HTTP_PORT=9080
AJP_PORT=9009
...
nohup java -jar "$WAR" --httpPort=$HTTP_PORT --ajp13Port=$AJP_PORT --prefix=/jenkins >> "$LOG" 2>&1 &

Then setup Apache so that it knows that the prefix /jenkins is being served by AJP in the httpd.conf file:

LoadModule jk_module          libexec/httpd/mod_jk.so

AddModule     mod_jk.c

#== AJP hooks ==
JkWorkersFile /etc/httpd/workers.properties
JkLogFile     /private/var/log/httpd/mod_jk.log
JkLogLevel    info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions     +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat     "%w %V %T"
# Here are 3 sample applications - 2 that are being served by Tomcat, and Jenkins
JkMount  /friki/* worker1
JkMount  /pebble/* worker1
JkMount  /jenkins/* worker2

Then finally the workers.conf file specified above, that just tells AJP which port to use for which web application:

# Define 2 real workers using ajp13
worker.list=worker1,worker2
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
# Set properties for worker2 (ajp13)
worker.worker2.type=ajp13
worker.worker2.host=localhost
worker.worker2.port=9009
worker.worker2.lbfactor=50
worker.worker2.cachesize=10
worker.worker2.cache_timeout=600
worker.worker2.socket_keepalive=1
worker.worker2.recycle_timeout=300

mod_rewrite

Some people attempted to use mod_rewrite to do this, but this will never work if you do not add a ProxyPassReverse.
See the thread if you'd like to know why.

The following Apache modules must be installed :

a2enmod rewrite
a2enmod proxy
a2enmod proxy_http

A typical set up for mod_rewrite would look like this:

# Use last flag because no more rewrite can be applied after proxy pass
RewriteRule       ^/jenkins(.*)$  http://localhost:8081/jenkins$1 [P,L]
ProxyPassReverse  /jenkins        http://localhost:8081/jenkins
ProxyRequests     Off

# Local reverse proxy authorization override
# Most unix distribution deny proxy by default (ie /etc/apache2/mods-enabled/proxy.conf in Ubuntu)
<Proxy http://localhost:8081/jenkins*>
  Order deny,allow
  Allow from all
</Proxy>

This assumes that you run Jenkins on port 8081. For this set up to work, the context path of Jenkins must be the same between your Apache and Jenkins (that is, you can't run Jenkins on http://localhost:8081/ci and have it exposed at http://localhost:80/jenkins)

The ProxyRequests Off prevents Apache from functioning as a forward proxy server (except for ProxyPass), it is advised to include it unless the server should function as a proxy.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Feb 15, 2011

    Ismael Angelo Jr. Casimpan says:

    May I know if anyone has succesfully deplyed jenkins using an apache worker mpm ...

    May I know if anyone has succesfully deplyed jenkins using an apache worker mpm as compared to the default pre-fork?

    Thanks in advance,

    Ismael

  2. Aug 24, 2011

    Granville Raper says:

    For those that want to have the Jenkins app as a root app but don't want it in t...

    For those that want to have the Jenkins app as a root app but don't want it in the root folder, you can use a virtual host in Tomcat to do that so that you're using a single instance of Tomcat instead of multiple instances

    In the server.xml file for Tomcat, nest a new Host element inside of the Engine element.  You can place it before or after the default Host element.  Inside the new host create a new Context element and an Alias element. If Jenkins.war is in the webaps folder and it's been deployed so that you have webapps/jenkins with all the goodies inside then the following will work.

    <Engine ...>
    ...
    <Host name="jenkins" appBase="webapps">
    	<Context path="" docBase="jenkins" />
    	<Alias>jenkins.example.com</Alias>
    </Host>
    
    ...
    </Engine>
    

    You can now add jenkins.example.com to your DNS and hit that hostname with whatever port the connector is setup on.  I used a DNS trick of putting "127.0.0.1 jenkins" in my hosts file so that the server would be able to respond to http://jenkins:8080/ which allowed me to test it.  The Alias element will also work, but I would recommend setting that up with a real dns server.  The <Host name=""> could also be "jenkins.example.com" and you could do without the Alias if you prefer.

    Once I had that working, I was able to setup Apache like stated above with the ProxyPass and ProxyPassReverse statements being changed to ProxyPass / http://jenkins:8080/.  Notice that I'm using the same port as localhost for Tomcat default, not a new one.  if you wanted a new port, you can obviously get that setup as well.

  3. Jun 22, 2012

    Jaime Gago says:

    For those out there trying to set the context path on RHEL/CentOS/SL 6 with a cl...

    For those out there trying to set the context path on RHEL/CentOS/SL 6 with a classic install with yum from official repository, you will find the JENKINS_ARGS flag in /etc/sysconfig/jenkins.

  4. Aug 29, 2012

    Jesse Bowes says:

    When I follow the mod_proxy instructions, it works but 'Â' characters are t...

    When I follow the mod_proxy instructions, it works but 'Â' characters are thrown in before almost every link on the page.  

  5. Sep 28, 2012

    Emil Petkov says:

    Hello, I followed the instructions and the reverse proxy with Apache in front o...

    Hello,

    I followed the instructions and the reverse proxy with Apache in front of Jenkins does not work. I have set up an Apache virtualhost config that proxies to Jenkins:

    # Apache virtualhost

    <VirtualHost *:8084>
            ServerAdmin emil@my_email.com
            ProxyRequests     Off
            ProxyPass         /jenkins  http://localhost:8084/jenkins
            ProxyPassReverse  /jenkins  http://localhost:8084/jenkins
            <Proxy http://localhost:8084/jenkins*>
              Order allow,deny
              Allow from all
             </Proxy>
            ProxyPreserveHost on
    </VirtualHost>

    The virtualhost is activated, no errors.

    You can see my changes to /etc/default/jenkins here:

    ...

    HTTP_PORT=8084

    PREFIX=/jenkins

    ...

    JENKINS_ARGS="--httpListenAddress=127.0.0.1 --webroot=/var/cache/jenkins/war --prefix=$PREFIX --httpPort=$HTTP_PORT --ajp13Port=$AJP_PORT"

    I am tailing the apache logs and jenkins, but when I try to access http://10.100.25.14:8084/jenkins, I get nothing, no page. When I start Jenkins without --httpListenAddress=127.0.0.1, I open http://10.100.25.14:8084/jenkins successfully, but this is directly accessing Jenkins, does not pass through Apache.

    Any ideas what might be the problem in my reverse proxy config? It is pretty standard.

    Thanks,

    Emil

  6. Apr 15

    John Heller says:

    RHEL/CentoOS 6 uses Apache 2.2.15 and the NoDecode option for AllowEncodedS...

    RHEL/CentoOS 6 uses Apache 2.2.15 and the NoDecode option for AllowEncodedSlashes only became available in 2.2.18. Can you recommend settings suitable for RHEL/CentOS.