Skip to main content
Advertisement

mod_jk Configuration — From Installation to JkMount

mod_jk was the standard method for legacy Apache+Tomcat integration. It is no longer recommended for new projects, but understanding its configuration is necessary for maintaining existing systems.


Installing mod_jk

Ubuntu/Debian

# Install via APT (simplest method)
sudo apt install libapache2-mod-jk

# Verify installation
apache2ctl -M | grep jk
# jk_module (shared)

CentOS/RHEL

# Requires EPEL repository
sudo dnf install epel-release
sudo dnf install mod_jk

# Module file location
ls /etc/httpd/modules/mod_jk.so

Compile from Source (Latest Version)

# Dependencies
sudo apt install -y build-essential apache2-dev

# Download source
cd /tmp
wget https://dlcdn.apache.org/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.49-src.tar.gz
tar -xzf tomcat-connectors-1.2.49-src.tar.gz
cd tomcat-connectors-1.2.49-src/native

# Compile
./configure --with-apxs=/usr/bin/apxs
make
sudo make install

# Verify
ls /usr/lib/apache2/modules/mod_jk.so

workers.properties Configuration

workers.properties is the core configuration file for mod_jk, where Tomcat instances (workers) are defined.

# /etc/apache2/workers.properties

# === Single Tomcat Worker ===
worker.list=worker1

# Worker type: ajp13 (AJP/1.3)
worker.worker1.type=ajp13
worker.worker1.host=127.0.0.1
worker.worker1.port=8009

# Connection settings
worker.worker1.connection_pool_size=10 # Connection pool size
worker.worker1.connection_pool_timeout=600 # Idle connection timeout (seconds)
worker.worker1.socket_timeout=300 # Socket timeout (seconds)
worker.worker1.socket_keepalive=true # TCP keepalive

# Retry settings
worker.worker1.retries=2
worker.worker1.recovery_options=7 # Auto-recover on errors

Load Balancing Worker Configuration

# /etc/apache2/workers.properties

# Individual Tomcat instances
worker.list=lb_worker,tomcat1,tomcat2

worker.tomcat1.type=ajp13
worker.tomcat1.host=127.0.0.1
worker.tomcat1.port=8009
worker.tomcat1.lbfactor=1 # Weight (higher = more requests)

worker.tomcat2.type=ajp13
worker.tomcat2.host=192.168.1.11
worker.tomcat2.port=8009
worker.tomcat2.lbfactor=1

# Load balancer worker
worker.lb_worker.type=lb
worker.lb_worker.balance_workers=tomcat1,tomcat2
worker.lb_worker.method=R # R=Round Robin, T=Traffic, B=Busyness
worker.lb_worker.sticky_session=true # Enable sticky sessions
worker.lb_worker.sticky_session_force=false # Fail over to another node on failure

Apache Configuration — Loading mod_jk and JkMount

# /etc/apache2/conf-available/mod-jk.conf

# Load module
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so

# Path to workers.properties
JkWorkersFile /etc/apache2/workers.properties

# Log settings
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel warn # info, warn, error
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# Request/response log (for debugging, disable in production)
JkRequestLogFormat "%w %V %T"
# Enable configuration
sudo a2enconf mod-jk
sudo systemctl reload apache2

Using JkMount in VirtualHost

# /etc/apache2/sites-available/myapp.conf

<VirtualHost *:80>
ServerName example.com

# Forward all requests to worker1
JkMount /* worker1

# Static files served by Apache (JkUnMount)
JkUnMount /static/* worker1
JkUnMount /images/* worker1
JkUnMount /css/* worker1
JkUnMount /js/* worker1

# Static file directory
Alias /static /var/www/myapp/static
<Directory "/var/www/myapp/static">
Options -Indexes
Require all granted
</Directory>

# Access log
CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
</VirtualHost>

Sticky Session Configuration

In a clustered environment, ensures the same client always routes to the same Tomcat instance.

Tomcat server.xml Configuration

<!-- Set unique jvmRoute for each Tomcat instance -->
<!-- Tomcat 1: server.xml -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

<!-- Tomcat 2: server.xml -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">

workers.properties Sticky Sessions

worker.lb_worker.sticky_session=true

# JSESSIONID example: abc123.tomcat1 (the .tomcat1 suffix is the routing key)
# worker.worker1.route=tomcat1 (explicit routing key)
worker.tomcat1.route=tomcat1
worker.tomcat2.route=tomcat2

mod_jk Status Page

The mod_jk status page lets you monitor worker status and load balancing statistics in real time.

<VirtualHost *:80>
ServerName admin.example.com

# mod_jk status page
<Location /jkstatus>
JkMount jkstatus
Require ip 127.0.0.1 192.168.1.0/24
</Location>
</VirtualHost>

Add the status worker to workers.properties:

worker.list=worker1,jkstatus

worker.jkstatus.type=status
worker.jkstatus.read_only=true # Read-only (for security)
# Access status page (internal network only)
curl http://localhost/jkstatus/

Migrating from mod_jk to mod_proxy_http

Step-by-step guide for transitioning from legacy mod_jk to mod_proxy_http.

Step 1: Verify Tomcat HTTP Connector

<!-- server.xml — Confirm HTTP connector is present -->
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
connectionTimeout="20000"/>

Step 2: Update Apache Configuration

# Old mod_jk approach (remove)
# JkMount /* worker1

# New mod_proxy_http approach
<VirtualHost *:80>
ServerName example.com

ProxyRequests Off
ProxyPreserveHost On

# Exclude static files
ProxyPass /static !
ProxyPass /images !

# Forward dynamic requests
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

Step 3: Disable AJP Connector (Security)

<!-- server.xml — Comment out AJP connector -->
<!--
<Connector protocol="AJP/1.3"
address="127.0.0.1"
port="8009"
redirectPort="8443"/>
-->

Troubleshooting

# Check mod_jk log
tail -f /var/log/apache2/mod_jk.log

# Common errors
# [warn] ajp_get_reply::jk_ajp_common.c: Timeout waiting for a reply

# Check worker status via CLI
# curl -s "http://localhost/jkstatus/?cmd=show&w=worker1"

# Check AJP port
ss -tlnp | grep 8009

# Temporarily increase log level for debugging
# JkLogLevel debug (change in httpd.conf then reload)

Summary

ItemLocationContent
Module loadhttpd.confLoadModule jk_module ...
Worker definitionworkers.propertiesajp13 type, host, port
URL mappingVirtualHostJkMount /* worker1
Static exclusionVirtualHostJkUnMount /static/* worker1
Sticky sessionsworkers.properties + server.xmljvmRoute + sticky_session=true
MigrationMigrate to mod_proxy_http
Advertisement