I have a powerful desktop, — and yes, runs Linux. It has a quad-core CPU, and 10GB RAM. My wife only has a small laptop. So, when she needs to do more serious work, like photo processing, she logs in my machine (using her own account) to do it.

And then we have a problem. All our pictures are stored in one shared repository, which is a directory under “/var”. Any file or picture I created in that directory, automatically received the ownership “my_user_id:users”, where “users” is my default group; and the default permission for the files I created are 744, which means my wife can’t modify it without changing the file permission first; and vice versa.

That’s really inconvenient. So I want to find a way, to achieve following goals:

  • Any file / directory we created in our repository, must have group “family”, which is a group I created for just two of us.
  • The files we created in the repository should automatically have default permission 664, so both of us can modify them without having to change the file permission first.
  • I don’t want to change our “umask”, because that will change the default file permission for anywhere, where I just want that for that specific directory.

I though it should be easy, but it turned out not that straightforward. After some research, here is what I did (do all these as root):

  1. chgrp family /var/pictures
  2. chmod 774 /var/pictures # users in other groups can also look into this repository
  3. setfacl -d -m g:family:rw /var/pictures
  4. chmod g+s /var/pictures

If you are interested in the details behind these commands, you can look at this article: Access control lists: Creating an efficient Linux file server with default permissions.

After these changes, we can work smoothly together in the same directory.

I work remotely a lot. So NX client is my best friend. It is fast, even under crappy Internet connection in a coffee shop.

But occasionally I need to input Chinese. I installed SCIM on my home machine, and it works beautifully when I work locally. However, it didn’t work when I use NX client to remote-desktop back to my home machine. After some research, I found I had to put following lines in my .bashrc file to make it work:

export LC_CTYPE="zh_CN"
export XMODIFIERS=@im=SCIM
export GTK_IM_MODULE=scim
export QT_IM_MODULE=scim

After this, everything worked beautifully again.

Ok, it is not done yet. I found another problem today.

Everything worked great in my home network. But today, when I tried to check out code from outside network, I found a problem. I didn’t open port 22 for my home server. Instead, I open a non-stand port on my router and forward traffic on that port to port 22 at my home server. But when I use svn+ssh, it seems there no way to specify port number.

After some research, I found all you need to do is to change the configuration file of the subversion on your local machine (at outside network). Open file “~/.subversion/config”, then go to section “tunnel”, add following line:

ssh_home = $SVN_SSH ssh -p 12345

Port 12345 is the non-standard port opened on my router. Then on my local machine, I use this command to check out code:

svn co svn+svn_home://my.home.domain.com/home/svn/repos/sandbox/trunk sandbox

Problem solved!

Recently I tryied to setup a development server at home. It’s pretty easy to install the subversion server since there are so many great tutorials online. I don’t want to use HTTP protocol to remote access my code repository because I always like svn+ssh better. But I do want a web interface to browse my repositories and compare the difference between reversions. So ViewVC becomes my nature choice. To be more specific, I want to be able to access the source tree from my home network freely; if from outside network, I want some basic security so that my code is not share with the whole world for free.

It’s not that hard either. But I did spend some time to figure out the security stuff. After all, I am not a system engineer. :-) Anyway, after it is done, I restarted the Apache server, and everything worked beautifully.  Actually for me there are only two files you need to modify, one is the /etc/apache2/conf.d/viewvc.conf, the other is the viewvc.conf at ViewVC’s home directory. Here is the Apache configuration file:

ScriptAlias /viewvc /home/svn/viewvc-1.0.6/bin/cgi/viewvc.cgi
ScriptAlias /query /home/svn/viewvc-1.0.6/bin/cgi/query.cgi


AuthUserFile /home/svn/viewvc-1.0.6/viewvc_passwd
AuthName “coffeestone:viewvc”
AuthType Basic
Require valid-user

Order allow,deny
Allow from 127.0.0
Allow from 192.168.2
Satisfy Any


AuthUserFile /home/svn/viewvc-1.0.6/viewvc_passwd
AuthName “coffeestone:viewvc”
AuthType Basic
Require valid-user

Order allow,deny
Allow from 127.0.0
Allow from 192.168.2
Satisfy Any

As you can see, I installed ViewVC at directory “/home/svn/viewvc-1.0.6″, and use command “htpasswd2″ to create a password file “viewvc_passwd” in that directory. Another file changed is viewvc.conf at ViewVC’s home directory. I only post changed variables as following:

svn_roots = coffeestone : /home/svn/repos/
default_root = coffeestone
root_as_url_component = 0
use_rcsparse = 0
use_enscript = 1
enscript_path = /usr/bin/

Well, it is that simple. Now I can enjoy my home development server!

My company doesn’t have VPN setup. To be able to work from home, usually I have to setup a reversed ssh tunnel from office to my home server (my home router forwards port 12345 to my home server port 22) by running this command from my office machine:

ssh -R 10000:localhost:22 my.homeserver.com -p 12345

In this way, when I get to home, I can connect to my office by command:

ssh -p 10000 localhost

But the ssh session sometimes got timed-out and then I couldn’t connect back. It happened several time and I eventually got annoyed. To keep my connection always alive, I created a file ~/.ssh/config:

Host *
Protocol 2
TCPKeepAlive yes
ServerAliveInterval 60

This helped a lot. But later, my company had some network issues and sometimes the network was down for hours. This broke my tunnel again. So I went even further and tried to find a solution to always keep my tunnel up — as soon as the network is available. Finally I found a program called “autossh“, which solved my problem perfectly.

First I made ssh passwordless from my office machine to my home server:

On my office machine, run following commands:

ssh-keygen -t dsa
scp ~/.ssh/id_dsa.pub my.homeserver.com:/tmp -p 12345

Then login my home server, run these commands:

cat ~/id_dsa.pub >> ~/.ssh/authorized_keys

After this, I tried to login my home server from office again, and yes! it didn’t ask me password anymore. Finally I installed autossh with apt-get, and changed my reverse tunnel command to:

autossh -M 29001 -f -N -R 10000:localhost:22 www.coffeestone.com -p 12345

You can find more information about autossh at this page: http://gentoo-wiki.com/HOWTO_autossh.

After re-setup the reverse tunnel with command autossh, I intentionally killed the ssh session from my home server; on my office machine side, the process autossh detected it and immediately restarted a new ssh session to my home server.

Now I have a perfect unbreakable ssh tunnel!

A few weeks ago we noticed that one of our applications had wrong timestamps in the log files by late for an hour.

At first I thought the timezone setting in the OS could be wrong but our ops people confirmed it is actually correct. Then I thought the JVM settings on that server must have something wrong. But I compared the JVM directories on the problematic server to a good server, they are exactly the same. This puzzles me. Then I wrote a simple Java app to print out all system properties and found that on the “bad” server, the default timezone is “GMT-08:00″ instead of “US/Pacific”.

After searching online, it turned out this is actually a bug in Java.

In short, in some cases JVM can get a wrong timezone from the machine, even if all the settings are right. What happened is when JVM starts, it looks for a matched file in directory /usr/share/zoneinfo/ to “/etc/localtime”. If it finds one, it uses the path to that file as the default timezone. The problem is, on different machine, JVM can traverse the directory in a different way; and even worse, for one “localtime” file, there can be multiple matches in the zoneinfo directory. For example, for our /etc/localtime, I found following matches:

/usr/share/zoneinfo/US/Pacific
/usr/share/zoneinfo/SystemV/PST8PDT
/usr/share/zoneinfo/America/Los_Angeles
/usr/share/zoneinfo/posix/US/Pacific
/usr/share/zoneinfo/posix/SystemV/PST8PDT
/usr/share/zoneinfo/posix/America/Los_Angeles

If we are lucky the “US/Pacific” happens to be the first match, we are in good shape; if the file “posix/SystemV/PST8PDT” matches first, Java will find it a invalid timezone. And the JVM stops looking further once the first match is found. So in this case it will use a default timezone, which is something like “GMT”, which of course doesn’t have day light saving adjustment. That’s why the timestamp was offset by one hour.

If you want to know more about this bug, check out following links:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6456628
https://bugs.launchpad.net/debian/+source/sun-java5/+bug/49068

The problem is complex, but the solution is simple: just specify a system property when you start your Java app:

-Duser.timezone=US/Pacific

Because JVM always tries to use that system property before it goes down to its default system value search. I added this property to the wrapper.conf file, restarted the application and everything is fine now. Maybe you should do the same thing just in case one day in a new server, a JVM goes through the directory in a slightly different way …

More than a year ago, when I chose OpenSuse as my desktop OS, clearly I made a wrong decision — I mean, OpenSuse is very good, but I shouldn’t have chosen the x86_64 version. There are just too many compatibility issues.

Anyway, I don’t want to reinstally my OS yet, so I have to deal with it. Here is how I installed the 32-bit Skype on my 64bit OS:
# 1. download the static version of Linux Skype
wget http://www.skype.com/go/getskype-linux-static
# The file I got is skype_static-1.4.0.118.tar.bz2
#
# 2. untar it to my "apps" directory, where I usually keep all my customized applications
tar xjvf skype_static-1.4.0.118.tar.bz2 -C ~/apps/
#
# 3. get 32-bit libsigc-2.0.so.0
cd /tmp
wget ftp://fr.rpmfind.net/linux/fedora/extras/4/i386/libsigc++20-2.0.17-1.i386.rpm
rpm2cpio libsigc++20-2.0.17-1.i386.rpm | cpio -idv
cp /tmp/usr/lib/libsigc-2.0.so.0.0.0 ~/apps/skype_static-1.4.0.118/libsigc-2.0.so.0
#
# 4. create a script to start skype in /usr/bin
sudo vi /usr/bin/skype
#
# following is the script for /usr/bin/skype
#
#!/bin/bash
#
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
cd ~/skype_static-1.4.0.118/ && ./skype &
#
# 5. make sure the new skype script is executalbe
sudo chmod 755 /usr/bin/skype

Now Skype can be started by typing in “skype” in any terminal window.

Early last month, when I was wandering in a Fry’s store, I found a returned Netgear EVA8000 digital media center. I have always been looking for a good multimedia hub for my living room, but had never found a satisfying one. The feature set of EVA8000 looked pretty good to me, and I remembered some good reviews from Maximum PC, Amazon and Cnet. So I decided to give it a try.

My requirements for a media center actually are not that complex, :-)

  1. It must be able to play regular DVDs — how can you call it a media center if there is no DVD-playing feature!? But I want more than just simply playing DVDs. Since I still have some VCD movies, of course I expect it to play them as well.
  2. It has to play other video formats from hard drives, such as Divx, AVI, MPEG4, QuickTime, … You name it, I want them all! Playing ripped DVD ISO files is a must, too. In this way, I can manage all my DVD collections from the media center without changing disks.
  3. It should be a good manager for my music collections. When I say good, I mean something like iTunes, and even more formats — OGG, WAV, …
  4. I have thousands of digital pictures on my desktop in my home office room. Even though I love to show them to my friends, I don’t want to show my messy office, :-) . So, the media center has to connect to my home network and present my digital photos on my LCD TV — trust me, pictures look so much better on a bigger screen, even a mediocre one looks great!
  5. I have a 7.1 speaker system with a receiver and I definitely don’t want to compromise my acoustic experience. The media center needs to drive them all.
  6. Remote control is a must — using a keyboard or mouse just doesn’t feel like in a living room.

Some other features are good to have, but I don’t have to have them now:

  1. TV recording. I know this is one of the most-wanted features for a media center, but fortunately it is not a big deal to me. I am not a big TV fan (as you can imagine, I spend most of my time on Internet instead of TV), so I think I can live without it.
  2. Blu-ray DVD and HD-DVD play back. As any new technology, currently these players are ridiculously expensive, just like a $20 DVD drive at seven or eight years ago. I always think it makes more sense to upgrade later when they are more affordable.
  3. YouTube and other online videos! Well, I know these low-resolution videos won’t look very good on a HD LCD TV, but sometimes it’s fun to watch them together with friends. Not mention that the Internet does have some high-def video contents such as movie trailers.

As you can see, the feature list for my media center is not too long, isn’t it? ;-)

Knowing what I am looking for, you will understand why I was interested in the EVA8000. It is such a slim box, looks like a regular router. According to the manual, it has very strong network capabilities. Even though it doesn’t have a DVD drive and can’t play DVD discs directly, I think I can compromise if it can do other things really well.

eva8000

The installation process of EVA8000 was fairly easy. It took me a little bit time to understand its menu system, but once figured out, everything is straightforward. But for a non-technical person, it may not be that simple. After setting up the network and my network storage places (I shared my photos and videos to my local home network from my office PC as Samba mounts — yes, my office PC runs on Linux!) , the EVA8000 started scan my media files. This is a painfully looooooooooooooooooong process. I meant it! It took literally more than half hour to go through my 9000 pictures and some video files! The manual said it was building a database for my media collections, but later I found its so-called database is just a plain text file with all my media files listed! I just couldn’t understand why it spent that much time on scanning, even with a wired network connection.

Anyway, once the scan was finished, it was ready to do some interesting things. First I tried to play a DVD ISO file stored on my remote PC. Surprisingly, it did a very good job! The streaming was very smooth, not jumpy at all! But soon I found the audio was only in two channel audio, and I am sure this ISO is encoded in 5.1. A little bit disappointing. Then I tried to browse my pictures from this box, which turned out to be a terrible experience. It is extremely slow. Browsing in sequence is barely acceptable, while random slideshow is totally unusable! I don’t fully understand why DVD playback is good but picture browsing is so slow. One reason I can think of is DVD playback may have a dedicated hardware decoder, but browsing pictures has to use its CPU, which is seriously underpowered.

However, I have to say, this product is actually a pretty good one. It has a lot of potential and is going to the right direction. It has powerful network functionality, with HDMI output, slim and good-looking. If it could come with a DVD drive, and the whole playback experience could be smoother, I might have just settled with it. But now, I knew I have to give it up. Because my goal is — yes — a PERFECT media center!

After returning the item back to Fry’s, I went through my feature list again. I realized that most of the features are actually PC functionalities and what I am looking for is indeed a Home Theater PC! This idea made me excited because I love building PC. Now I have another excuse! :-) But since it will be a PC, I have to add another must-have feature to the list: the softwares must be FREE — aka NO Microsoft Windows! I knew this would make the whole process harder, but, well, who cares! We are geeks, aren’t we?

That’s how I started building my perfect HTPC!

Last week I upgraded my blog from wordpress 2.1 to 2.2. Because the new version of wordpress uses UTF8 charset, while the older version uses Latin1, all the Chinese characters turns to question marks. I use this script to fix it:
#!/bin/bash
tables=`mysql -u WORDPRESS_DATABASE_USER_NAME -pPassword WORDPRESS_DATABASE_NAME \
-e "show tables" | grep wp_`
for table in $tables;
do
echo "processing table $table ..."
mysqldump -u WORDPRESS_DATABASE_USER_NAME -pPassword WORDPRESS_DATABASE_NAME --opt \
--default-character-set=latin1 --skip-set-charset $table > $table.conv.sql
sed -e 's/latin1/utf8/g' -i $table.conv.sql
mysql -u WORDPRESS_DATABASE_USER_NAME -pPassword --default-character-set=utf8 \
WORDPRESS_DATABASE_NAME < $table.conv.sql
done

After running this script, make sure the wp-config.php file under the wordpress root directory has following lines:
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Recently I registered two domains: my personal domain www.coffeestone.com, — mostly for my blog, wiki, and maybe other personal usage, and … www.myseconddomain.com for our community forum. I plan to use Wordpress for my blog, JSPWiki for my wiki, and JForum for my second domain. JSPWiki and Jforum will be running in Tomcat, and both domains will be in the same Linux server. A router with my static IP sits between my server and Internet, which is also a firewall and forwards incoming traffic on port 80 to my Linux server. So here are my goals:

  1. Use one Apache to serve both domains;
  2. Run two Java applications separately, with a script that can easily shutdown / start each of them independently;
  3. Use Apache to redirect traffic to each Tomcat instance based on the requested domain name.

My server is running on OpenSUSE 10.1, with Apache 2.2.0 and Tomcat 5.5.20.

1. Software installation

First, I have to install some software / modules.

  1. Apache
    By default, Apache is already installed in OpenSUSE. If it has not been installed, go to YaST / Software / Software Management, search for Apache2 and install it.
  2. Apache modules
    I also need some Apache modules:
    a) apache2-mod_php5: this module is necessary for PHP support
    b) mod_jk-ap20: this is the module that connects Apache and Tomcat together
    c) php5-mysql and php5-mysqli: these modules provide mysql support for PHP5Following modules are good to have for performance and stability reasons: apache2-worker, apache2-prefork. All these modules can be easily installed from YaST.
  3. Load Apache modules
    All Apache modules can be loaded from YaST. Go to YaST / System / ‘/etc/sysconfig’ Editor, and then navigate to the directory Network / WWW / Apache2 / APACHE_MODULES, add ” jk” at the end of the setting — this will add the module mod_jk-ap20 to Apache; also make sure “php5″ is there if you also need PHP support. Then click “Finish”.
  4. Tomcat
    Tomcat is a Java application, I prefer to install it manually instead of from YaST. I’ll cover that later.

2. Configure Virtual Hosts in Apache

Because I want to serve more than one domains from my server with one IP address, I have to use name based virtual host. To learn how virtual host works in Apache, check http://httpd.apache.org/docs/2.0/vhosts/ for more detail. I tried to do the virtual host configuration in YaST / Network Services / HTTP Server, but that didn’t give me all the controls. So I did it by adding / changing configuration files. In OpenSUSE 10.1, all Apache related configuration files are in directory /etc/apache2.

  1. Add a NameVirtualHost
    Open /etc/apache2/listen.conf, add a line:
    NameVirtualHost 192.168.2.2:80This tells Apache that the IP 192.168.2.2 (my server’s local network IP) will serve the name based virtual hosts. If your server connects to Internet directly (no router in between), you may want to change the IP address to your static IP. In my case, all incoming traffic has to go through my router first, and then forwarded to my local server with IP address 192.168.2.2, so I only need to specify my local IP address here.
  2. Add virtual host files
    In OpenSUSE 10.1, all virtual host configuration files should go to /etc/apache2/vhosts.d. Every file in this directory ending with .conf is automatically included in the Apache. To make the configuration even easier, OpenSUSE already includes two template files in that directory: vhost-ssl.template is for a virtual host with SSL, vhost.template is for a virtual host without SSL. Since my site will not have SSL, I used the latter one as my template.
    cp vhost-template coffeestone.confThen I changed the file coffeestone.conf to:<virtualhost>
    ServerAdmin webadmin@coffeestone.com
    ServerName coffeestone.com
    ServerAlias www.coffeestone.com
    DocumentRoot /srv/www/vhosts/coffeestone.com
    .....
    </virtualhost>
    You should change the value of DocumentRoot and other domain related directives. To do that, you can simply do a search for “dummy-host” in the conf file and replace them with the correct values. Following the same procedure, I created another conf file for my second domain: myseconddomain.conf.
  3. Change host file
    Because my local IP 192.168.2.2 is a NameVirtualHost, I have to make my domains to be resolved as 192.168.2.2 locally. Open file /etc/hosts and add following line:192.168.2.2 www.coffeestone.com www.myseconddomain.comAgain, if your server has the static IP already, you don’t have to do this.
  4. Create doc root and restart Apache
    mkdir /srv/www/vhosts/coffeestone.com
    echo "coffeestone" &gt; /srv/www/vhosts/coffeestone.com/index.htm
    mkdir /srv/www/vhosts/myseconddomain.com
    echo "myseconddomain" &gt; /srv/www/vhosts/myseconddomain.com/index.htm
    rcapache2 restart
    Then I type in www.coffeestone.com and www.myseconddomain.com in my browser and check if both of the index pages show up correcty. Another way to test if the virtual host configuration works is to use command “httpd2 -S”. You should get something like:
    VirtualHost configuration:
    192.168.2.2:80 is a NameVirtualHost
    default server coffeestone.com (/etc/apache2/vhosts.d/coffeestone.conf:15)
    port 80 namevhost coffeestone.com (/etc/apache2/vhosts.d/coffeestone.conf:15)
    port 80 namevhost myseconddomain.com (/etc/apache2/vhosts.d/myseconddomain.conf:1)
    As you can see, my domain coffeestone.com is the default server because its conf file (coffeestone.conf) is alphabeticly before the second domain’s conf file (myseconddomain.conf). If I want to make my second domain the default server, I can just rename its conf file to _myseconddomain.conf.

3. Install Wordpress

This part is the easiest part in the whole process. Download the tgz file from http://www.wordpress.org, and then extract the content to /srv/www/vhosts/coffeestone.com, which is my document root for the website. I want the URL for my blogs started with “http://www.coffeestone.com/blog”, so I change the directory for Wordpress to “blog” under directory “coffeestone.com”. Now the directory structure looks like:

/srv/www/vhosts/
     +-- coffeestone.com
                     +-- blog

Then I follow the “Famous 5-Minute Install” instruction to configure the Wordpress. After that, I go to www.coffeestone.com/blog and my blog is there!

4. Run two Tomcat instances in one server

Now it’s time to install the two Java web applications in Tomcat. To do this, you must understand two important concepts in Tomcat: CATALINA_HOME and CATALINA_BASE. Basically, CATALINA_HOME is the directory where your Tomcat is installed; CATALINA_BASE is where your web application is installed. This means in your server, usually there is only one CATALINA_HOME (because only one copy of Tomcat binary is necessary), but there can be multiple CATALINA_BASE (because you may install several web applications). CATALINA_BASE usually contains following subdirectories:

  • conf - Server configuration files (including server.xml)
  • logs - Log and output files
  • shared - For classes and resources that must be shared across all web applications
  • webapps - Automatically loaded web applications
  • work - Temporary working directories for web applications
  • temp - Directory used by the JVM for temporary files (java.io.tmpdir)

CATALINA_HOME contains directory “bin” and “common”. If you want to know more about these settings, look at file $CATALINA_HOME/RUNNING.txt.

  1. Install TomcatAfter download the Tomcat binary, just untar it to the directory where you want to install it. I like to put it under /opt.
    cd /opt
    tar -zxvf /tmp/apache-tomcat-5.5.20.tar.gz .
    Now I have a directory /opt/apache-tomcat-5.5.20.
  2. Create a soft link to the Tomcat directoryIn the same directory,
    ls -s apache-tomcat-5.5.20 tomcatIn this way, I can always keep my CATALINA_HOME as /opt/tomcat. In the future if I want to upgrade Tomcat, I just need to update my sym link to point to the new directory.
  3. Create directories for all Tomcat instances.
    I am going to keep all my tomcat instances in /opt/tomcat_instances:
    mkdir /opt/tomcat_instances
    mkdir /opt/tomcat_instances/jspwiki
    mkdir /opt/tomcat_instances/myseconddomain
    In my case, the CATALINA_BASE for my JSPWiki will be /opt/tomcat_instances/jspwiki, the CATALINA_BASE for my second domain will be /opt/tomcat_instances/myseconddomain.
  4. Create CATALINA_BASE directory structure for each Tomcat instance
    Copy following directories from /opt/tomcat to /opt/tomcat_instances/jspwiki and /opt/tomcat_instances/myseconddomain:
    cp -pr /opt/tomcat/conf /opt/tomcat_instances/jspwiki
    cp -pr /opt/tomcat/logs /opt/tomcat_instances/jspwiki
    cp -pr /opt/tomcat/shared /opt/tomcat_instances/jspwiki
    cp -pr /opt/tomcat/webapps /opt/tomcat_instances/jspwiki
    cp -pr /opt/tomcat/temp /opt/tomcat_instances/jspwiki
    Do the same thing for the second domain. The option -p will keep the original permissions, option -r will copy all files recursively. After the directory structure is created, those directories in original directory /opt/tomcat can be removed. If you do a ls on /opt/tomcat, it gonna look like:
    drwxr-xr-x 3 root root 4096 2007-01-28 23:00 bin
    drwxr-xr-x 6 root root 4096 2006-04-14 14:09 common
    -rw-r--r-- 1 root root 11558 2006-04-14 14:09 LICENSE
    -rw-r--r-- 1 root root 704 2006-04-14 14:09 NOTICE
    -rw-r--r-- 1 root root 6384 2006-04-14 14:09 RELEASE-NOTES
    -rw-r--r-- 1 root root 7146 2006-04-14 14:09 RUNNING.txt
    drwxr-xr-x 5 root root 4096 2006-04-14 14:09 server
  5. Copy war files to CATALINA_BASE
    cp /tmp/JSPWiki.war /opt/tomcat_instances/jspwiki/webapps
    cp /tmp/myseconddomain.war /opt/tomcat_instances/myseconddomain/webapps
  6. Configure every Tomcat instance
    Now I need to configure these two web applications to run on different ports to accept web requests and start / stop command. The configuration file I need to work on is server.xml in directory $CATALINA_BASE/conf. For the web application JSPWiki, I leave every setting as default; for the second domain, I need to change following settings:
    a) Change the shutdown port from 8005 to 8105 — this is the port where Tomcat listens to the shutdown command:
    &lt;Server port="8105" shutdown="SHUTDOWN"&gt;
    b) Change the Coyote connector port from 8080 to 8180 — this is the port where you can connect to Tomcat directly:
    &lt;Connector port="8180" maxHttpHeaderSize="8192"
    maxThreads="150" minSpareThreads="25" .../&gt;
    You can also comment out this tag completely if you don’t want the Tomcat instance to accept any request other than forwarded by Apache. Usually doing this is useful and more secure if your web server is exposed to the internet directly. In my case, I have a router / firewall to connect to Internet and I do like to connect to my Tomcat instances directly from my internal network at port 8080 / 8180, so I kept this section.c) Change the AJP connector port from 8009 to 8109 — this is the port where Tomcat accepts the web requests from Apache:
    &lt;Connector port="8109" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" /&gt;
  7. Create a script to control Tomcat instances.This script is mostly from this article: http://edwardaux.wordpress.com/2006/09/20/3/. I just add one more argument to make it more flexible. Download the attached script (tomcat.sh) to /usr/local/bin and make sure it is executable. To run it, just type in:
    tomcat.sh {start|stop} {instance_name}The instance name is the name of the directory in /opt/tomcat_instances. For example, I can type in
    tomcat.sh start jspwikito start my web application JSPWiki.
  8. Configure Java web applicationsAfter starting both Java web applications, I went to http://192.168.2.2:8080 to configure my JSPWiki and http://192.168.2.2:8180 to configure the Java web application for my second domain.

5. Make Apache and Tomcat work together

Finally we come to the last step.

  1. Add configuration for mod_jk
    This is the configuration file that defines the behavior of mod_jk. Under directory /etc/apache2/conf.d, create a file “jk.conf”:
    &lt;IfModule mod_jk.c&gt;
    JkWorkersFile "/etc/apache2/workers.properties"
    JkLogFile "/var/log/apache2/mod_jk.log"
    JkLogLevel info
    JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
    JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
    JkRequestLogFormat "%w %V %T"
    &lt;/IfModule&gt;
    This configuration file tells Apache that the worker thread of mod_jk is defined in file /etc/apache2/workers.properties, the log goes to /var/log/apache2/mod_jk.log; it also defines the format of the log file.
  2. Add configuration file for mod_jk workers
    Create a file /etc/apache2/workers.properties:
    ps=/
    worker.list=wiki, myseconddomain
    worker.wiki.port=8009
    worker.wiki.host=localhost
    worker.wiki.type=ajp13
    worker.wiki.lbfactor=1
    worker.myseconddomain.port=8109
    worker.myseconddomain.host=localhost
    worker.myseconddomain.type=ajp13
    worker.myseconddomain.lbfactor=1
    In this configuration file, “ps” is the file system separator of my OS — if you are on Windows, it should be “\”; lbfactor is for load
    balancing — since I don’t need that, I just keep it 1; the port is the AJP connector port we defined in previous section (4.6.c) .
  3. Change the virtual host file to forward traffice properly
    Open file /etc/apache2/vhost.d/coffeestone.conf, add following line: JkMount /wiki/* wiki
    JkMount /wiki wiki
    This tells Apache that any requested URL to my domain www.coffeestone.com, if it is started with “/wiki”, it will be handled by mod_jk worker “wiki”, which is defined in our workers.properties to forward to localhost 8009, where my JSPWiki is running. Similarly, open
    file /etc/apache2/vhost.d/myseconddomain.conf, add following line:
    JkMount /* myseconddomain
    JkMount / myseconddomain
    This tells Apache that all incoming traffic to my domain www.myseconddomain.com will be handled by mod_jk worker “myseconddomain”, which is defined in the workers.properties to forward to localhost 8109, where my second Java web application is running.

Finally I finished everything. I restarted the Apache and Tomcat:

tomcat.sh stop jspwiki
tomcat.sh stop myseconddomain
tomcat.sh start jspwiki
tomcat.sh start myseconddomain
rcapache2 restart
And then, I got my Wordpress blog running on http://www.coffeestone.com/blog, my wiki running on http://www.coffeestone.com/wiki, all together with my second domain nicely in one server!

6. References

  1. http://tomcat.apache.org/tomcat-5.5-doc/RUNNING.txt
  2. http://tomcat.apache.org/tomcat-3.3-doc/Tomcat-Workers-HowTo.html
  3. http://httpd.apache.org/docs/2.0/vhosts/
  4. /usr/share/doc/packages/apache2/README.QUICKSTART
  5. http://www.linuxjournal.com/article/8561
  6. http://edwardaux.wordpress.com/2006/09/20/3/
  7. http://raibledesigns.com/page/rd?entry=setting_up_cvs_appfuse_jspwiki