setup tomcat6 (with native library) with apache2 integration
In this post, I'll setup a apache2 with php5 and tomcat6 integrated with apache2.
Since Tomcat 5, you don't need a front http server anymore, but since I want to have php5 and tomcat6 on port 80, I need the tomcat6-apache2 integration with modjk
since a lot of operation need the root privilege, switch to root :
sudo -s
Apache2 & PHP5 installation
The following command install php5, php5 command line interface (CLI to use php as shell script) and some common php extension.
aptitude install php5 php5-cli apache2 php5-xmlrpc php5-mysql php5-gd php5-imagick php-pear php5-mcrypt
a2enmod headers #Activation of Mod headers
a2enmod deflate #Activation of Mod deflate
Setup the timezone :
vi /etc/php5/apache2/php.ini
[Date]
; Defines the default timezone used by the date functions
date.timezone = Europe/Paris
Java installation
aptitude install sun-java6-jdk
vi /etc/profile
Append the following line :
export JAVA_HOME=/usr/lib/jvm/java-6-sun
reload your .profile :
(command to type is "dot space dot profile")
. .profile
check :
echo $JAVA_HOME
/usr/lib/jvm/java-6-sun
root@rdp:/home/special/tomcat# java -version
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02, mixed mode)
Tomcat6 installation
In this installation, I install the tomcat binaries in /usr/local and separate the CATALINA_HOME and the CATALINA_BASE
CATALINA_HOME is in /usr/local/tomcat (the engine)
CATALINA_BASE is in /home/special/tomcat (the configuration files to configure tomcat for your app)
Like this I can have several CATALINA_BASE (with differnent tomcat config) with one HOME (which is a link to the last current version, upgrading to the next version will mean change a link, switch back to the previous version : change the link to its original point).
mkdir ~/download
cd ~/download
wget http://apache.cict.fr/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip
unzip apache-tomcat-6.0.20.zip
mv apache-tomcat-6.0.20 /usr/local/
ln -s /usr/local/apache-tomcat-6.0.20 /usr/local/tomcat
chmod 755 /usr/local/tomcat/bin/*.sh
mkdir /home/special/tomcat
cp -r /usr/local/tomcat/* /home/special/tomcat
cd /home/special/tomcat
rm -r bin/ lib/ LICENSE NOTICE RELEASE-NOTES RUNNING.txt webapps/*
Disable the SSL Engine
as I won't use it :
switch the value from 'on' to 'off' on this line :
<listener classname="org.apache.catalina.core.AprLifecycleListener" sslengine="off"/>
Edit tomcat init script
with this script you'll be able to start/stop/restart tomcat with the service command.
It's in this script I'll specify where the CATALINA_HOME and CATALINA_BASE are.
If you want another instance of tomcat with another CATALINA_BASE location, write a second script with a different CATALINA_BASE.
In this script I set the jvm in server mode "-server" and specify some memory settings.
vi /etc/init.d/tomcat
# Tomcat auto-start
#
# description: Auto-starts tomcat
# processname: tomcat
# pidfile: /var/run/tomcat.pid
JAVA_HOME=/usr/lib/jvm/java-6-sun; export JAVA_HOME
JAVA_OPTS="-server -Xms100m -Xmx512m"; export JAVA_OPTS
CATALINA_HOME=/usr/local/tomcat; export CATALINA_HOME
CATALINA_BASE=/home/special/tomcat; export CATALINA_BASE
case $1 in
start)
sh $CATALINA_HOME/bin/startup.sh
;;
stop)
sh $CATALINA_HOME/bin/shutdown.sh
;;
restart)
sh $CATALINA_HOME/bin/shutdown.sh
sh $CATALINA_HOME/bin/startup.sh
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
chmod 755 /etc/init.d/tomcat
#auto start & stop with the machine :
ln -s /etc/init.d/tomcat /etc/rc1.d/K99tomcat
ln -s /etc/init.d/tomcat /etc/rc2.d/S99tomcat
MOD_JK installation
MOD_JK is here to link apache2 and tomcat.
aptitude install libapache2-mod-jk
Edit the jk.conf file, which is here to setup general config option of mod_jk
vi /etc/apache2/mods-available/jk.conf
JkWorkersFile /etc/apache2/workers.properties
JkLogFile "|/usr/bin/rotatelogs /var/log/apache2/mod_jk.log 86400"
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkRequestLogFormat "%w %V %T"
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
Activation of modjk :
cd /etc/apache2/mods-enabled
sudo ln -s ../mods-available/jk.conf
In workers.properties we specify the links between apache2 and J2EE servers (tomcat/jetty etc..)
You can have multiple J2EE servers declared in this file.
here I setup one J2EE server which is on the same server (yes, the tomcat could have been on another server)
vi /etc/apache2/workers.properties
worker.list=tomcat6
worker.tomcat6.type=ajp13
worker.tomcat6.host=localhost
worker.tomcat6.port=8009
Apache2 virtualhost configuration
Here we add a virtualhost for the tomcat application.
Based on the servername sent by the browser, apache will select the virtualhost to send the http request.
(At the end of this post I'll explain how to use this)
let's say the application is named "crf-rdp"
mkdir -p /home/special/tomcat/www/crf-rdpAdd a virtual host:
vi /etc/apache2/sites-available/crf-rdp
<VirtualHost *>
ServerAdmin webmaster@localhost
DocumentRoot /home/special/tomcat/www/crf-rdp
ServerName crf-rdp.server.com
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /home/special/tomcat/www/crf-rdp>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ErrorLog "|/usr/local/apache/bin/rotatelogs /var/log/apache2/error_crf-rdp.log 86400"
CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/apache2/access_crf-rdp.log 86400" combined
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
ServerSignature On
RewriteEngine on
RewriteLog /var/log/apache2/mod_rewrite_crf-rdp.log
RewriteLogLevel 1
RewriteCond %{REQUEST_URI} !^/crf-rdp
RewriteRule ^(.*) /crf-rdp$1 [PT,L]
JkMount /crf-rdp/* tomcat6
</VirtualHost>
With the rewrite rule and the JkMount all http request sent to crf-rdp.domain.com will be forwarded to the tomcat webapp.
Set the new virtual host as available :
ln -s /etc/apache2/sites-available/crf-rdp 001-crf-rdp
Installation of Apache Tomcat Native Library
This "library allows optimal performance in production environment".
Note : libapr1 is installed with apache2
aptitude install make gcc gcc-4.2 gcc-4.2-locales gcc-4.2-multilib libapr1-dev
cd /usr/local/apache-tomcat-6.0.20/bin/
tar zxf tomcat-native.tar.gz
cd /usr/local/apache-tomcat-6.0.20/bin/tomcat-native-1.1.16-src/jni/native
export JAVA_HOME=/usr/lib/jvm/java-6-sun
./configure --with-apr=/usr/bin/apr-config; make; make install
cd /usr/lib
ln -s /usr/local/apr/lib/libtcnative-1.so.0.1.16 libtcnative-1.so
when your tomcat will start, you can check the catalina.out log file and this the following :
thomas@home:/home/special/tomcat/logs$ cat catalina.out
Oct 18, 2008 9:13:02 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.16.
Oct 18, 2008 9:13:02 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
Oct 18, 2008 9:13:02 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
INFO: Failed to initialize the SSLEngine.
Oct 18, 2008 9:13:02 PM org.apache.coyote.http11.Http11AprProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Oct 18, 2008 9:13:02 PM org.apache.coyote.ajp.AjpAprProtocol init
INFO: Initializing Coyote AJP/1.3 on ajp-8009
Oct 18, 2008 9:13:02 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 708 ms
Oct 18, 2008 9:13:02 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Oct 18, 2008 9:13:02 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.18
Oct 18, 2008 9:13:02 PM org.apache.coyote.http11.Http11AprProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Oct 18, 2008 9:13:02 PM org.apache.coyote.ajp.AjpAprProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Oct 18, 2008 9:13:02 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 109 ms
Now you should have a working installation with tomcat6 linked with apache2.
You start/stop/restart tomcat with
service tomcat start
service tomcat stop
service tomcat restart
Now here is some useful tips you may find valuable :
Define a dataSource in tomcat
It's useful and more secure to define a dataSource (database connection) inside the J2EE server instead of inside the application itself.
Because developpers should know production credentials and with credentials inside your application properties files, it goes into your cvs/svn/bazaar/git source control.
While if it's a dataSource that you use as a JDNI ressource, the person who operate tomcat (the server admin) is the only one knows the dataSource credentials.
You first need to get the jdbc driver of the datasource.
The example is here for mysql (but works too with other db servers)
cd ~/download
wget http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.7.tar.gz/from/http://mir2.ovh.net/ftp.mysql.com/
tar zxf mysql-connector-java-5.1.7.tar.gz
cp mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar /usr/local/tomcat/lib/
cd /home/special/tomcat/conf
mkdir -p Catalina/localhost
Example for the CRF-RDP application :
(where crf-rdp is the context-path of the webapp, see first chapter here http://tomcat.apache.org/tomcat-6.0-doc/config/context.html)
vi /home/special/tomcat/conf/Catalina/localhost/crf-rdp.xml
<Context path="crf-rdp" docBase="/home/special/tomcat/crf/crf-rdp.war" debug="0">
<Resource name="jdbc/crfirpDS" auth="Container" type="javax.sql.DataSource"
username="crfirpUser"
password="***********"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/crfirpDb?autoReconnect=true&useUnicode=true&characterEncoding=UTF8"
validationQuery="Select 1"
/>
</Context>
here we setup a datasource named "crfrdpDS" for the webapplication "crf-rdp" which has its war file here "/home/special/tomcat/crf/crf-rdp.war".
It connects to the localhost mysql database, with 'crfrdpUser' database user, on crfrdpDb database schema.
In the application, the datasource should be named 'java:comp/env/jdbc/crfrdpDS' (without quote) (and not 'jdbc/crfrdpDS' as you may think it would be... to easy ;))
Notice : about the password, don't use < or & since it's XML special characters (it should be encoded)
A virtualhost for phpMyAdmin
PhpMyAdmin is a great tool to operate your mysql databases (even more usefull than mysql-query-browser in many situation).
But your database is your most precious thing...
So expose a phpMyAdmin over internet is not the best thing to do.
But you can still enjoy phpMyAdmin in a secure way :
Create a virtualhost for phpMyAdmin that accept http connection only for localhost client,
and then connect to your server using ssh with a tunnel so that Apache see localhost connection.
mkdir /home/special/phpMyAdmin
cd /home/special/phpMyAdmin
wget http://freefr.dl.sourceforge.net/sourceforge/phpmyadmin/phpMyAdmin-3.1.5-all-languages.tar.bz2
tar jxf phpMyAdmin-3.1.5-all-languages.tar.bz2
mv phpMyAdmin-3.1.5-all-languages/* .
rm -r phpMyAdmin-3.1.5-all-languages phpMyAdmin-3.1.5-all-languages.tar.bz2
vi /etc/apache2/sites-available/phpmyadmin
<VirtualHost 127.0.0.1:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/phpmyadmin
ServerName localhost
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/phpmyadmin/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
ErrorLog /var/log/apache2/phpmyadmin/error.log
CustomLog /var/log/apache2/phpmyadmin/access.log combined
ServerSignature On
</VirtualHost>
cd /etc/apache2/sites-enabled
ln -s ../sites-available/phpmyadmin 001-phpmyadmin
mkdir /var/log/apache2/phpmyadmin
service apache2 restart
Now, connect to your server using this command :
sudo ssh -lthomas -L 81:localhost:80 my.server.com
(you can do the same with putty SSH->Tunnel)
and type in your browser :
http://localhost:81
you should see phpMyAdmin.
Virtualhost and DNS trick
Sometime you need to access you website by its full domain name while the domain is not yet setup or the website is not open yet (you're still developping it...).
So, you either access to your site with it's IP or maybe mainserverDNSName.com/~username
or if you block the access you may have set up your virtualhost like the phpMyAdmin one with <virtualhost 127.0.0.1:80/> and ServerName localhost
To access you website as if it were already with its production url (which is www.mydomain.com) do this :
Edit on your client machine the etc/hosts file :
[c:\windows\system32\drivers]/etc/hosts file, add
127.0.0.1 www.mydomain.com
#blank line
(replace 127.0.0.1 with the server ip if you were accessing your server by its IP)
open an ssh connection with a tunnel
sudo ssh -lthomas -L 80:localhost:80 serverIp
(or do the same with putty in windows)
type in your browser
http://www.mydomain.com
What happen :
Your local client machine will resolve http://www.mydomain.com as localhost because of your /etc/hosts file.
The http connection will go through your ssh tunnel and hit your web server as a local(from the server point of view) connection with a servername in the http request "www.mydomain.com" so that Apache will select the right virtualhost.
(It might not be that clear... I'll maybe update this part with some more detailed explanation).
Comments
Just wanted to thank you for posting this guide.
Regards,