Zimbra with Apache using mod jk - mod proxy - mod proxy ajp
I am no expert at either Linux, Programming or anything whatsoever. I cannot guarantee that this will work for you. If it doesn't please don't blame me. If you think I misunderstood something or I am wrong in some place or even all places, please try to improve on this and be helpful to others. The following has worked for me and, I believe, it should work for you, too. However, no guarantees.
Firstly, thanks to everyone at the Forums for posting about their problems and efforts in trying to run Zimbra with Apache using mod_jk. And thanks to the original Using_Tomcat_with_Apache_(mod_jk) entry (a lot has been borrowed from it). This how-to is a result of their efforts.
What you want to do?
Note: The port could be 8080 or 6080 or any other. This is the port you have used to configure Zimbra's Web UI. Zimbra asked you a question regarding this when you installed it.
How to do that?
There are 2 ways:
- Use Apache's module called "mod_proxy"
- Use Apache's module called "mod_jk"
Which way is better?
Honestly, I don't know which one's better. But, I do know that:
1. If you use "mod_proxy", content from http://your.domain.com:8080/ is proxied to http://your.domain.com/somefolder/. It takes only a few lines and a few seconds to configure this. All you need to edit is one file: httpd.conf . The disbenefit of this method is that, you need to secure your Proxy. Securing Proxy implies that you need to explicitly specify access controls. Only those domains & IP Addresses which have been explicitly allowed by you will be able to access this proxied content. So, what would you do if you were on move or your ISP provides a dynamic IP address? If your ISP gives you a dynamic IP address, Dyndns.org would be one way to go. But, IMHO, that's not a good practice at all. You need to have some other way to do this.
FYI, here is the snippet from my httpd.conf for using "mod_proxy":
<IfModule mod_proxy.c> ProxyRequests On <Proxy *> Order deny,allow Deny from all Allow from 127.0.0.1 Allow from 192.168.0.5 Allow from localhost Allow from your.domain.com # this list goes on and on # OR, you can simply comment out this entire access control block # BUT DON'T EVER DO THAT! # You won't if you have ever heard of Distributed Denial of Service attacks! </Proxy> <Location "/service"> ProxyPass http://192.168.0.5:6080/service ProxyPassReverse http://192.168.0.5:6080/service </Location> <Location "/zimbra"> ProxyPass http://192.168.0.5:6080/zimbra ProxyPassReverse http://192.168.0.5:6080/zimbra </Location> ProxyVia On </IfModule>
2. If you use "mod_jk". It is cool! If it would not be, I would not be writing this.
My setup of Zimbra
- CentOS 4.3
- Zimbra Open Source 4.0.0 RC1 (also, tested this with ZCS 4.0.0 GA, it works and I am using it)
- Pentium 4 2.8 GHz Processor, 1 GB Memory
Pre-requisites, Assumptions, et al.
- I am assuming that you already have a fully functional instance of Zimbra running on your system.
- I had Zimbra running on port 6080. So, I will use 6080 to refer to the port Zimbra runs on.
- I have still not experimented with https, which I will do once I finish writing this How-to and post the results here. But, I am pretty confident that it will work.
Confirmed: This works with SSL, too. For this your authentication type should be https. The following command should do it:
su - zimbra zmtlsctl https
- I am using http authentication
How it works
What does Tomcat or any web server or any server generally do? It binds to some port and waits for requests and when it receives them, it serves them. In this case, too, we are going to do the same. We will bind Tomcat to listen to port 8009 (in addition to other ports for http and https that it will bind to out-of-the-box when Zimbra is installed) and we will ask Apache to send request to this port when it itself receives request for serving Zimbra. So, port 8009 will be their point of communication. The module "mod_jk" allows Apache to communicate via a protocol called "AJP 1.3", which, Tomcat already understands.
Now that both of them know Japanese - (Master mod_jk taught Mr. Apache to speak and understand it) they decide to meet at Miss Tomcat's place!
Here is one representation:
- You want to access Zimbra
- You point your browser to http://your.domain.com/zimbra/
- This request is sent to port 80 on your.server.com
- Apache is listening on port 80 and it tries to serve your request by checking its configuration first
- Its configuration says that the content for http://your.domain.com/zimbra/ is being served by some service on port 8009
- It also says that port 8009 will understand only AJP 1.3 protocol
- Since, Apache has mod_jk.so present in its modules directory it is able to communicate via AJP 1.3
- It sends request to port 8009
- Tomcat is listening on port 8009
- As soon as it receives this request, it fetches the content and serves it on this port 8009
- This content is then taken from there and served to you on port 80, which is where you placed request for it
(I am not repeating what the docs already say somewhere - this is just to make it work)
- Download mod_jk from here
- Uncompress the archive and follow the instructions in the doc directory for installing it.
- Once "mod_jk" is installed, create a file called /etc/httpd/conf/workers.properties and dump in the following text:
# Zimbra worker worker.list=zimbra worker.zimbra.type=ajp13 worker.zimbra.host=localhost worker.zimbra.port=8009 worker.zimbra.lbfactor=1 workers.tomcat_home=/opt/zimbra/tomcat workers.java_home=/opt/zimbra/java
- Create a file called /etc/httpd/conf.d/tomcat.conf and dump in the following text:
# Load mod_jk module # Update this path to match your modules location LoadModule jk_module modules/mod_jk.so # Declare the module for <IfModule directive> (remove this line on Apache 2.x) # AddModule mod_jk.c # Where to find workers.properties # Update this path to match your conf directory location (put workers.properties next to httpd.conf) JkWorkersFile /etc/httpd/conf/workers.properties # Where to put jk logs # Update this path to match your logs directory location (put mod_jk.log next to access_log) JkLogFile /etc/httpd/logs/mod_jk.log # Set the jk log level [debug/error/info] JkLogLevel info # Select the log format JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " # JkOptions indicate to send SSL KEY SIZE, JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories # JkRequestLogFormat set the request format JkRequestLogFormat "%w %V %T" # Send everything for context /examples to worker named zimbra (ajp13) JkMount /zimbra zimbra JkMount /zimbra/ zimbra JkMount /zimbra/* zimbra JkMount /service zimbra JkMount /service/ zimbra JkMount /service/* zimbra JkMount /zimbraAdmin zimbra JkMount /zimbraAdmin/ zimbra JkMount /zimbraAdmin/* zimbra
- Edit /opt/zimbra/tomcat/conf/server.xml and /opt/zimbra/tomcat/conf/server.xml.in and add the following:
<!-- for mod_jk --> <Connector port="8009" acceptCount="1024" enableLookups="false" redirectPort="6443" protocol="AJP/1.3" /> <!-- for mod_jk -->
<Engine name="Catalina" defaultHost="localhost">
Note: The port 6443 mentioned above as redirectPort="6443" is the same that you see in the HTTP section in server.xml file. In my server.xml file it looks like this:
<!-- HTTPBEGIN --> <Connector port="6080" acceptCount="1024" enableLookups="false" redirectPort="6443" maxThreads="100" minSpareThreads="100" maxSpareThreads="100"/> <!-- HTTPEND -->
- Restart Tomcat
tomcat stop tomcat start
- Now, if you try to visit http://your.domain.com/zimbra the Zimbra log-in screen should appear. If it does not appear please re-check everything again. Perhaps, some of the paths I mentioned above are not the same on your system. Please change them accordingly.
- Once the Zimbra log-in screen appears, try to log-in. Most probably you will get some service error. If you can log-in you are done! You need not read ahead. If you can't log-in, please check that in the files /opt/zimbra/apache-tomcat-5.5.15/webapps/service/WEB-INF/web.xml and /opt/zimbra/apache-tomcat-5.5.15/conf/service.web.xml.in you have ports 80 and 443 mentioned in all instances where code such as following appears:
<init-param> <param-name>allowed.ports</param-name> <param-value>80, 443, 6080, 6443, 7070, 7443, 7071</param-value> </init-param>
- Restart Tomcat.
If it won't work ...
What will not work?
Ok, I must admit I entirely forgot to check zimbraAdmin. To make zimbraAdmin available at http://your.domain.com/zimbraAdmin please edit /opt/zimbra/tomcat/webapps/zimbraAdmin/WEB-INF/web.xml, /opt/zimbra/tomcat/conf/zimbraAdmin.web.xml.in, /opt/zimbra/tomcat/webapps/service/WEB-INF/web.xml and /opt/zimbra/tomcat/conf/service.web.xml.in and add port 443 along with 7071 in all instances where 7071 has been solely quoted. E.g. If the block looks like this:
<init-param> <param-name>allowed.ports</param-name> <param-value>7071</param-value> </init-param>
... change it to:
<init-param> <param-name>allowed.ports</param-name> <param-value>443, 7071</param-value> </init-param>
Now you can also access zimbraAdmin at https://your.domain.com/zimbraAdmin
Changes in 4.0.2 GA
You will notice that the path to web.xml.in has changed in 4.0.2 (I never upgraded to 4.0.1 so am not sure whether these changes exist in it). Now there are three files:
/opt/zimbra/apache-tomcat-5.5.15/conf/zimbraAdmin.web.xml.in /opt/zimbra/apache-tomcat-5.5.15/conf/service.web.xml.in /opt/zimbra/apache-tomcat-5.5.15/conf/zimbra.web.xml.in
Please make the changes to these files as per the instructions above.
The only thing that does not work now and is in my attention is the Documents Wiki or Zmwiki. I am working on this currently and will soon report progress.
Ok, regarding the Wiki, I have filed it as a bug here: http://bugzilla.zimbra.com/show_bug.cgi?id=10432
If you are interested in redirecting the wiki to be available on ports 80 or 443, this bug must be resolved - so, please vote for it. Thanks! :-)
(The wiki is available as of now, but the links on the wiki page are all made up of your original port E.g. 8080, So the person who wants to visit those pages, must manually enter the URL in the location bar, excluding the ports.)