Apache HTTP server (SSL) + Tomcat 6.x on Ubuntu and CentOS


The Environment

From time to time I need to do some Apache httpd + Tomcat installations on Linux servers and usually they come in different flavors. While you’re still experimenting it’s a good idea to use a pre-installed Linux on a virtual machine. I’m using the free VMware player to run virtual appliances, a list of which can be found on VMware page. Personally I like the clean Linux installations without any extras, this way you can install anything you need and create multiple virtual machines of the same Linux flavor with different purposes if you need to. My preferred versions are the Debian based Ubuntu 9.04 server and the CentOS which is a community-supported OS based on Red Hat Enterprise Linux. Sometimes you get a pre-installed server for development and you’re not sure what kind of Linux flavor is on it. Usually a simple uname -a helps, but sometimes it spits out something vague like

Linux someserver 2.6.16.27-0.9-smp #1 SMP Tue Feb 13 09:35:18 UTC 2007 i686 i686 i386 GNU/Linux

This doesn’t really tell you a whole lot about the distribution. What I found is that in these cases you can issue a command

$ cat /etc/*-release

and you’ll get your answer in the form similar to

LSB_VERSION="core-2.0-noarch:core-3.0-noarch:core-2.0-ia32:core-3.0-ia32"
SUSE Linux Enterprise Server 10 (i586)
VERSION = 10

This is just an example of a server response. The following setup instructions are targeted towards the Ubuntu and CentOS servers.

Installing Apache HTTP Server

When installing the precompiled version of Apache httpd on Ubuntu there are a few versions to choose from:

Each version has been given a different set of parameters when compiling and produced quite different versions of the server. Which one to use is a completely different topic and in the end you might decide that it’s better to compile it yourself for the production. Being on the safe side we’ll choose the one that is not so speedy, but is considered to be more stable.

# apt-get install apache2-mpm-prefork

If you’re using the CentOS there is no such choice of the Apache HTTP server, at least I’m not aware of it. All you need to do to install it is issue

# yum groupinstall 'Web Server'

After sucessful installation take a look at the configuration directory structure on the Ubuntu server.

$ tree /etc/apache2/
.
|-- apache2.conf
|-- conf.d
|   |-- charset
|   `-- security
|-- envvars
|-- httpd.conf
|-- mods-available
|   |-- actions.load
...
|   `-- vhost_alias.load
|-- mods-enabled
|   |-- alias.load -> ../mods-available/alias.load
...
|   `-- status.load -> ../mods-available/status.load
|-- ports.conf
|-- sites-available
|   |-- default
|   `-- default-ssl
|-- sites-enabled
    |-- 000-default -> ../sites-available/default
    `-- 001-default-ssl -> ../sites-available/default-ssl

This looks quite different compared to the Apache directory structure on CentOS. First of all the directory is not named apache2 like on Ubuntu.

$ tree /etc/httpd
.
|-- conf
|   |-- httpd.conf
|   `-- magic
|-- conf.d
|   |-- README
|   |-- manual.conf
|   |-- perl.conf
|   |-- php.conf
|   |-- proxy_ajp.conf
|   |-- python.conf
|   |-- squid.conf
|   |-- ssl.conf
|   |-- webalizer.conf
|   `-- welcome.conf
|-- logs -> ../../var/log/httpd
|-- modules -> ../../usr/lib/httpd/modules
`-- run -> ../../var/run

You can start/stop Apache with the init scripts /etc/init.d/apache2 and /etc/init.d/httpd respectively for the Ubuntu and the CentOS. Take note that on Ubuntu httpd.conf is not the main configuration file for Apache server, it’s the /etc/apache2/apache2.conf.

Configuring SSL

Loading Apache modules in Ubuntu is easy, you just create a link in mods-enabled directory to a configuration snippet of the required module in the mods-available directory. In our case we need the ssl module.

# ln -s /etc/apache2/mods-available/ssl.load /etc/apache2/mods-enabled/
# ln -s /etc/apache2/mods-available/ssl.conf /etc/apache2/mods-enabled/

This will load the ssl module and provide some default parameters for the module, but we also need another link to a so-called default ssl site which is yet another configuration snippet file.

# ln -s /etc/apache2/sites-available/default-ssl /etc/apache2/sites-enabled/001-default-ssl

Remember to restart Apache after such changes to configuration like module loading. If you’re satisfied with the defaults then you’re done, the server should be accessible via https protocol. It so happens that with CentOS the setup is even easier because SSL is preconfigured and setup for you right out of the box, so you don’t need to do any additional configuration.

Though this setup will work fine you may wish to generate a new certificate for the server anyway. One of the reasons that come to mind is the Common Name value in the certificate which should be the same as the hostname you’re using to access the server. Since this is a development server we’ll generate a self-signed certificate which means that the browser will not fully trust our server by default, but personally I don’t consider this a big problem for development because one can just choose to trust the generated certificate inside the browser. To generate our certificate simply use the following command

# openssl req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes \
-keyout server.pem -out server.crt -subj'/O=Company/OU=Department/CN=vap.lan'

This outputs the new private key as server.pem and the certificate as server.crt in the current directory. With these options the certificate will be valid for 365 days, you can change this value if you need to. Also remember to replace the vap.lan part of the command with the hostname of your server. Where you actually place the generated files is really up to you, but I prefer to keep them close to Apache’s configuration like /etc/apache2/ssl. In CentOS after installing Apache you’ll find automatically generated certificate (localhost.crt) and private key (localhost.key) files placed in /etc/pki/tls/certs/ and /etc/pki/tls/private/ respectively. In Ubuntu the certificate resides in /etc/ssl/certs/, the private key in /etc/ssl/private/ and are named ssl-cert-snakeoil.pem and ssl-cert-snakeoil.key.

Now that you’re equiped with the knowledge of the location of these files you may choose to change this or leave it as it is. Two Apache directives are used for this purpose SSLCertificateFile and SSLCertificateKeyFile. In Ubuntu these directives can be found in the default-ssl site configuration mentioned earlier and in CentOS look for them in /etc/httpd/conf.d/ssl.conf file.

Another thing to mention when configuring SSL remember to check the directives SSLProtocol and SSLCipherSuite. They define what protocols are allowed for the secure socket layer and the set of ciphers that can be used. There are usually a few of them defined since these are negotiable between the server and the browser when establishing connection. It’s actually possible to configure the HTTPS connection so that no encryption would be used when sending the data, so make sure you set these setting to something reasonable. I generally use the following.

SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

This uses only the newer protocols and doesn’t allow the cipher suite which would send the data as plain text. When selecting the cipher suite also remember that the more secure suite you choose to use, the more expensive becomes the operation of establishing a connection, this applies for both sides.

Tomcat via AJP Proxy

First we’ll install Java. In Ubuntu this is done by issuing

# apt-get install sun-java6-jdk

as for the CentOS simply use this

# yum install java

When the install is done grab the Tomcat 6.x Core binary and extract it to a directory of your liking like /home/joe/tomcat6. Even though you can install Tomcat6 using apt-get on Ubuntu I still prefer downloading a copy from the Tomcat website (sometimes one needs to have more than one version of Tomcat). Starting Tomcat is really simple just execute the bin/startup.sh file in the directory where you chose to extract it. Next we’ll load a couple of modules for Apache so that it knows how to forward the requests to Tomcat. In Ubuntu again this is done using the links

# ln -s /etc/apache2/mods-available/proxy.load /etc/apache2/mods-enabled/
# ln -s /etc/apache2/mods-available/proxy.conf /etc/apache2/mods-enabled/
# ln -s /etc/apache2/mods-available/proxy_ajp.load /etc/apache2/mods-enabled/

and in CentOS we don’t need to change anything as the module is already loaded for us in _/etc/httpd/conf.d/proxyajp.conf file. What we’ll need to do is add a line to this file and in Ubuntu’s case the /etc/apache2/mods-enabled/proxy.conf file

ProxyPass / ajp://localhost:8009/

This will tell Apache to forward all requests that come to the sever’s root or any subdirectory to Tomcat which is listening for them on the default port 8009. The communication between Apache server and Tomcat is done via AJP protocol and that why we need to explicitly specify this, because it’s also possible to use http, ftp and other protocols to proxy the requests to other back end servers. I you need to change the Tomcat’s AJP port for some reason open the tomcat/conf/server.xml file and edit the connector line where it says something like

<Connector port="8009" protocol="AJP/1.3" ...>

I always try to keep it short, but this was the bare minimum that I thought was necessary to write about the topic. I’ll probably continue on the Apache configuration topic in the next post as there are still some things that are left unsaid when configuring a server with an Apache front-end and Tomcat back-end. If you have something to say about my way of doing things or have a question don’t hesitate to ask.