Introduction
About four years ago I wrote a series of posts covering installing Jenkins on Ubuntu 12.04 with Tomcat 6 and using Jenkins for PHP Continuous Integration. A lot of the tools for PHP CI where provided via pear, but things have changed since then. For starters, phpUnit as of version 4.0 was no longer provided by the channel pear.phpunit.de and should be installed by other means.
So in this new set of posts I plan to cover the following:
- Installing the needed prerequisites
- Globally installing Composer
- Installing the PHP CI tools with Composer
- Installing Tomcat 8.x
- Installing Tomcat APR
- Installing TCNative
- Installing Jenkins
- Configuring Apache to act as a SSL handler and proxy for Tomcat 8
- TLSv1.2 and appropriate ciphers
- HSTS (HTTP Strict Transport Security)
- Port 80 redirect with 301 response code to 443
- OCSP Stapling
- Proxy Setup in Apache
Installing the Needed Prerequisites
In this section we are going to install several packages via apt-get, from Oracle-Java-8 to PHP 7.1
Installing Oracle Java 8
- Add the Oracle Java PPA to apt-get
add-apt-repository ppa:webupd8team/java
- Update apt-get and install Oracle Java 8
apt-get update; sudo apt install oracle-java8-installer
- Agree to the license agreement.
- Edit /etc/environment
vim /etc/environment
- add the following line
JAVA_HOME="/usr/lib/jvm/java-8-oracle"
- Save the file and relaunch the terminal to use the updated environment
Installing PHP 7.1
- Add the PPA for PHP 7.1
add-apt-repository ppa:ondrej/php
- Update with “apt-get update”
- Install the many PHP 7.1 libraries via apt-get
- php7.1
- php7.1-cli
- php7.1-common
- php7.1-curl
- php7.1-dev
- php7.1-fpm
- php7.1-iconv
- php7.1-intl
- php7.1-json
- php7.1-ldap
- php7.1-mbstring
- php7.1-mcrypt
- php7.1-mysql
- php7.1-opcache
- php7.1-pdo
- php7.1-pgsql
- php7.1-xdebug
- php7.1-xsl
- php7.1-xml
- php-pear
apt-get install php7.1 php7.1-cli php7.1-common php7.1-curl php7.1-dev php7.1-fpm php7.1-iconv php7.1-intl php7.1-json php7.1-ldap php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-opcache php7.1-pdo php7.1-pgsql php7.1-xdebug php7.1-xsl php7.1-xml php-pear
Install Subversion 1.9
- Add the WanDisco Repository
sh -c 'echo "deb http://opensource.wandisco.com/ubuntu `lsb_release -cs` svn19" >> /etc/apt/sources.list.d/subversion19.list' wget -q http://opensource.wandisco.com/wandisco-debian.gpg -O- | sudo apt-key add - apt-get update
- Install subversion 1.9
apt-get install subversion
Install Other Needed Libraries
There are a few more needed packages/libraries we need to install before we can move on
apt-get install graphviz python-software-properties build-essential git ant libxml2-utils libcrypt-openssl-dsa-perl mavenlibapache2-mod-proxy-html
libxml2-dev
Globally Installing Composer
Since PHPUnit is now no longer on pear.phpunit.de, the new method of installing these tools uses Composer. Which after a little setup, isn’t all the bad to use.
Setting up Composer globally is pretty easy with just a few commands
- Download composer
curl -sS https://getcomposer.org/installer | php
- Move composer.phar into place
mv composer.phar /usr/local/bin/composer
- Make sure composer is executable
chmod +x /usr/local/bin/composer
Installing the PHP CI Tools With Composer
For this section, we will create a centrally accessible location for our PHP CI tools to reside and then use a simple composer.json file for the installation. I could go with several composer commands instead, but this is far easier.
- Create a central location for the tools to be installed to
mkdir -p /opt/composer/vendor
- Create the composer.json file
{ "config": { "vendor-dir": "/opt/composer/vendor" }, "require-dev": { "phpunit/phpunit": "^6.0", "doctrine/annotations": "^1.3" }, "require": { "phpunit/dbunit": "^3.0", "symfony/console": "2.8.9", "phing/phing": "^2.16", "sebastian/phpcpd": "2.0.4", "phploc/phploc": "^3.0", "phpmd/phpmd": "^2.6", "squizlabs/php_codesniffer": "^2.8", "phpdocumentor/reflection-docblock": "~2.0", "symfony/config": "~2.8", "symfony/filesystem": "~2.8", "symfony/finder": "~2.8", "phpdocumentor/phpdocumentor": "2.9" } }
Alternatively, you can download the file here
- Install the libraries/bundles (In the directory that you made composer.json or where ever you places it).
composer install
- Add the following to the PATH variable line in /etc/environment to update the path for all of the users
:/opt/composer/vendor/bin/
- Close and re-open your terminal to have the new environment take effect
Installing Tomcat 8.x
This part will be pretty easy to do as I’m going to use the apt-get version and not the source version. Apache will be handling our front end SSL and other things, so we just need Tomcat to serve the application.
- Install tomcat8
apt-get install tomcat8
For the next two sections, if you do not want to do an install from source for APR or TC-Native, you can just install the libraries from apt-get, if you are happy with the versions in the repository for your ubuntu version.
apt-get install libapr1 libtcnative-1
Installing Tomcat APR
- Download the APR source from the Apache Portable Runtime Project
wget http://mirrors.advancedhosters.com/apache/apr/apr-1.5.2.tar.gz
- Move the and extract the tar file to /opt
mv apr-1.5.2.tar.gz /opt cd /opt tar xvf apr-1.5.2.tar.gz
- Change to the directory and run the following
cd apr-1.5.2 ./configure make make install
Installing TC Native
- Download the source from Apache’s Site or use wget to download it.
wget http://mirrors.ocf.berkeley.edu/apache/tomcat/tomcat-connectors/native/1.2.12/source/tomcat-native-1.2.12-src.tar.gz
- Extract the tar file and move into the new directories native directory
tar xvf tomcat-native-1.2.12-src.tar.gz cd tomcat-native-1.2.12/native
- Configure TC-Native
./configure --with-apr=/usr/local/apr/bin/apr-1-config --with-java-home=/usr/lib/jvm/java-8-oracle --with-ssl=yes --prefix=/usr/share/tomcat8
- Make and install
make make install
- Create or edit setenv.sh
Under /usr/share/tomcat8/bin there should be a file called setenv.sh, if there is not, created it with your favorite editor and set its contents to the followingLD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CATALINA_HOME/lib export LD_LIBRARY_PATH
- Restart Tomcat 8 and check or watch with “tail -f”, /var/log/tomcat/catalina.out for the line where APR and TC Native is loaded, to make sure all went as expected.
- Open a browser and navigate to http://<your ip or server here>:8080 to see if tomcat is up and running
- Edit /etc/tomcat/server.xml with your favorite editor and uncomment the apr line in the file, while setting it’s ssl attribute to false so it looks like
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" />
- Change the connector for port 8080 to look like the following:
note: remove the address= part if you want to test the page without apache first as it restricts access to only that address.<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" URIEncoding="UTF-8" server="Apache" maxThreads="150" address="127.0.0.1"/>
- Save server.xml and restart tomcat
Installing Jenkins
The installation of Jenkins is pretty easy and doesn’t have a lot of configuration
- Make the home directory for jenkins in /opt/jenkins
mkdir /opt/jenkins
- Add the following home directory environment variable definition to tomcat8 in /etc/init.d/tomcat8
#JENKINS HOME JENKINS_HOME=/opt/jenkins export JENKINS_HOME
- Download the version Jenkins you want (I’m using the LTS version) from the Jenkins-CI site or download it with wget, like so:
wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war
- Make jenkins.war the root site of tomcat8 (you don’t have to do this, you could just copy it over to webapps, but you will need to append /jenkins to the proxy configuration when you get there)
mv jenkins.war /var/lib/tomcat8/webapps/ROOT.war
- Restart Jenkins
service tomcat8 restart
Configuring Apache to Act as an SSL Handler and Proxy for Tomcat 8
Since Apache is already installed by installing PHP 7.1, we can move straight on to the configuration and enabling the needed mods.
First, we are going to enable the needed mods: headers, proxy, proxy_connect, proxy_html, proxy_http, rewrite, and ssl.
- enable needed mods
a2enmod headers a2enmod rewrite a2enmod ssl a2enmod proxy a2enmod proxy_http a2enmod proxy_html
- Restart Apache to enable the modsservice apache2 restart
TLSv1.2 and appropriate ciphers
For this particular install we are going to use TLS 1.2 only and a handful of high security ciphers. For your users to use your site, they will need to be running the following clients or higher:
- Android 5.0
- Chrome 30
- Edge
- Firefox 27
- IE 11 on Windows 7
- Java 8
- Opera 17
- Safari 9
The first thing you will need to be able to perform the steps in this section, is to have an SSL cert, either self signed or not. Once you have that and have placed it (I tend to prefer to put them under /etc/ssl/private), you will need to tell Apache where it is. After which , we can set what ciphers are allowed and what versions of SSL will be accepted.
- Edit /etc/apache2/sites-available/default-ssl.conf
- Add the following lines
SSLEngine on SSLCertificateChainFile /etc/ssl/private/<your chain cert>.crt SSLCertificateFile /etc/ssl/private/<your cert>.crt SSLCertificateKeyFile /etc/ssl/private/<your cert key>.key SSLProtocol -all +TLSv1.2 SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
- Save and then restart apache2
If these ciphers are too restrictive for your, please check the following resources for some more cipher and TLS options.
Mozilla- Server Side TLS
OWASP – Securing Tomcat (Although this is for Tomcat, the translation to Apache is pretty easy)
HSTS (HTTP Strict Transport Security)
By enabling HSTS, your browser is instructed to always use HTTPS when communicating with your site, and it is quiet easy to turn on.
- Add the following line to your ssl vhost definition for apache, /etc/apache2/sites-available/default-ssl.conf
Header always set Strict-Transport-Security "max-age=86300; includeSubdomains;"
In the above line max-age should be around a week or less than a day
Port 80 Redirect with 301 Response Code to 443
Now that we have HSTS setup and SSL, we should default our site to use SSL. To do so, we will edit the default VHost for port 80 to redirect to the same URL, but with https and a response of 301.
- Edit /etc/apache2/sites-available/000-default.conf and make it look like the following
<VirtualHost *:80> ServerAdmin webmaster@localhost ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{SERVER_NAME}$1 [R=301,L] </IfModule> </VirtualHost>
OCSP Stapling
OCSP Stapling delivers certificate revocation information during the TLS handshake and can improve performance of TLS when using HTTPS. To use this, we simply need to enable it and specify a cache location.
- Specify a cache location by adding the following line to the top of your default-ssl.conf vhost
SSLStaplingCache shmcb:/tmp/stapling_cache(128000)
- Add the following line somewhere in the <VirtualHost _default_:443> block of the same file
SSLUseStapling on
- Restart Apache2
service apache2 restart
- Check of your cert is using OCSP as you expect
openssl.exe s_client -connect [yoursite.com]:443 -status
You should see a line in the OCSP Response Data section like “OCSP Response Status: successful (0x0)“
Proxy Setup in Apache
Having Apache act as an SSL handler for Tomcat is not too hard to setup and allows us to use the SSL Ciphers we want to use, without having to deal the capabilities of the Java version we have installed.
To set this up we need to add the following lines to our default-ssl.conf in the VirtualHost definition block.
ProxyRequests Off ProxyPreserveHost On AllowEncodedSlashes NoDecode <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass / http://localhost:8080/ nocanon ProxyPassReverse / http://localhost:8080/ ProxyPassReverse / http://your_server_url.com/ # lets jenkins know SSL is being handled elsewhere RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443"