Running Jenkins behind an Apache reverse proxy
The Apache HTTP Server Project (referred to as Apache) was first released to the public in April 1995. Apache represents a cornerstone of the Internet and is highly acclaimed. Since its initial release, Apache has become one of the most widely adopted web server platforms around the world. Apache thrives to this day, and has a vast array of modules that extend its functionality.
Running Jenkins on a nonstandard web port is a limitation that you may wish to address. It requires users to specify the port as part of the URL, which can become a hassle to manage. To address this concern, it's useful to run Jenkins behind an Apache proxy. Apache provides an extensive set of features that can benefit Jenkins users. Some benefits of this solution include:
- Running Jenkins on port 80 (privileged port workaround)
- Adding SSL support for your Jenkins instance
- Running Jenkins from a different context, either
/Jenkins
or/ci
- Running Jenkins side by side with other web apps, http://jenkins.foo.com
On Linux and Unix hosts, all TCP and UDP ports lower than 1024 are considered privileged. A privileged port is one where the services exposed are running under a privileged user account (typically, root). Running Jenkins as root is considered dangerous and is, therefore, not recommended. The prescribed user account under which the Jenkins service executes is jenkins.
The privileged port restriction can create a bit of a problem for Jenkins administrators. We may want Jenkins to be accessible on standard web port 80, but still want to run it under the Jenkins user account. By running Jenkins behind Apache, we can address this issue while still adhering to best practices.
One possible solution is to run Jenkins behind Apache and use mod_proxy
to internally redirect traffic. This solution will allow us to get Jenkins to respond to requests on a privileged port without executing it as the root user, or changing its port configuration.
Apache's mod_proxy
operates by forwarding incoming TCP/UDP port 80 requests to Jenkins on port 8080. Any responses from Jenkins are forwarded back to port 80. This creates a seamless experience for web users, while allowing Jenkins to remain on its original port.
To configure Jenkins to use Apache's mod_proxy
module, we will need a basic installation of the Apache web server (http://www.apache.org). If Apache is not already installed on your system, you can use the standard package manager for your Linux or Unix distribution to install it. Here are some example terminal commands to install Apache on Linux:
- Debian/Ubuntu
$> sudo apt-get update $> sudo apt-get install apache2
Installs Apache2 in ->
/etc/apache2
- CentOS/Fedora
$> sudo yum install httpd
Installs Apache2 in ->
/etc/httpd
Once Apache is installed on the host, we will need to ensure that mod_proxy
is installed and loaded also.
On RHEL-/CentOS-based systems, mod_proxy
is typically installed at the same time as Apache. For Debian-based systems, you may need to install the Apache mod_proxy
module specifically. You can look at your Apache modules
folder on your system to see whether the mod_proxy.so
and mod_proxy_http.so
files are present.
To ensure mod_proxy is operating properly we need to ensure that Apache loads the mod_proxy.so
and mod_proxy_http.so
modules when Apache initializes. Apache's configuration file is usually httpd.conf
or apache2.conf
, depending on your system. Let's open up the Apache configuration file in an editor (vi, nano, and so on) and ensure that we have the proper LoadModule
directives.
Next we will want to direct Apache to load our mod_proxy
modules. The proper Apache configuration lines are provided below.
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
Tip
If the preceding lines do not exist (or are commented out) in your Apache configuration file, you will need to add them or uncomment them.
Once the LoadModule
changes to the Apache configuration file have been completed, we will need to configure the port 80 VirtualHost
XML block and create a reverse proxy. An example of an Apache virtual host entry for a Jenkins instance and proxy running on port 80
is provided below.
<VirtualHost *:80> ServerAdmin webmaster@localhost ProxyRequests Off ProxyPreserveHost On AllowEncodedSlashes On <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass / http://localhost:8080/ nocanon ProxyPassReverse / http://localhost:8080/</VirtualHost>
Now that the virtual host configuration entries have been added, save the configuration file to disk and restart Apache. Depending on the distribution, the commands necessary to restart Apache may vary slightly. Examples for CentOS and Debian are provided here:
- CentOS:
$> sudo service httpd restart
- Debian/Ubuntu:
$> sudo service apache2 restart
Note
If this is a root level (
/
) proxy pass, make sure you have a tailing slash in yourProxyPass
andProxyPassReverse
directives.
For the Jenkins UI and the Apache reverse proxy to properly integrate, the context paths of Jenkins and the Apache subdirectory must match. For example, if the Jenkins system is configured to utilize a context path of http://localhost:8080/jenkins
, the proxy pass context defined in the Apache configuration file must also reflect the /Jenkins
suffix.
To set the context path for Jenkins, add the --prefix=
entry to the JENKINS_ARGS=
property. An example of this configuration entry is provided below.
--prefix=/Jenkins --prefix=/somecontextpathhere
The JENKINS_ARGS
configuration line is located inside the Jenkins startup bash/dash script. This file is typically found in one of the following locations on the filesystem that houses Jenkins (depending on your Linux distribution):
/etc/default/Jenkins
/etc/sysconfig/Jenkins (line 151)
Once everything has been configured, restart the Apache one more time as well as the Jenkins service to finalize the implementation of the reverse proxy solution. To verify everything is functioning properly navigate from a web browser to your Jenkins URL on port 80 and verify that the Jenkins UI behaves as expected.