Configuring Apache HTTP Reverse-Proxy

Exposing OpenKM directly from Tomcat can be risky, if you need the application to be accessed from the Internet (for example https://issues.jboss.org/browse/JBAS-3861). It could be infected by PerlBot. 8080 may be blocked by a firewall, for this reason is a recommendable to expose your OpenKM installation through the standard web port 80. In the following steps we explain how to configure Apache to handle these requests and forward to Tomcat application server using the AJP13 protocol.

From the Apache documentation: The AJP13 protocol is packet-oriented. A binary format was presumably chosen over the more readable plain text for performance reasons. The web server communicates with the servlet container over TCP connections. To cut down on the expensive process of socket creation, the web server will attempt to maintain persistent TCP connections to the servlet container, and to reuse a connection for multiple request/response cycles.

Internal IP vs external IP

Your OpenKM can be accessed from two different zones: Internet and LAN. This means that to access this server you need to use two IPs: external IP (Internet) and internal IP (LAN).

The internal IP address (also known as "local IP address") is the address that is assigned by your local network router that often begins with 192.168.x.x. These IP addresses can only be seen by other computers in your local network (LAN) and not by any computers connected in an external network such the Internet.

To reach the Internet or a computer in another network your computer is often assigned an external IP address, which can then be used to refer to the computer in your local network.

In the above picture, there are three computers in the local network that have each been assigned their own internal IP address by the router. The ISP is connected to the router and gives the router an external IP address that allows it to communicate with the Internet. On the Internet everyone sees your external IP address, but any information coming from the router is "converted" from the external IP address to the internal IP address.

So if you want your OpenKM installation accessible from both LAN and Internet, the trick here is to configure the client computers to resolve your internal IP (192.168.0.50) if they are inside the LAN or the external IP if they are on Internet. To resolve the Internet IP (67.166.214.148) your computer uses the public DNS. So, you need to configure a sort of DNS server inside the LAN or modify every client host file to resolve to the internal IP.

Debian and Ubuntu

The first thing is to install the required Apache software. From Debian / Ubuntu you can install Apache with a single command:

$ sudo apt-get install apache2

Edit the file named /etc/apache2/apache2.conf and configure a ServerName to prevent warnings in the Apache startup process:

$ vim /etc/apache2/apache2.conf

ServerRoot "/etc/apache2"
ServerName "your-domain.com"

Edit apache2.conf is optional.

Enable the proxy module:

$ sudo a2enmod proxy_ajp
$ sudo a2enmod proxy_wstunnel

To get websocket working you also need Tomcat 7.0.61 or later. Note that proxy_wstunnel module requires Apache 2.4.5 or later. Please refer to Apache module documentation.

 Create the configuration file /etc/apache2/sites-available/openkm.conf with this content:  

$ vim /etc/apache2/sites-available/openkm.conf

<VirtualHost *:80>
  ServerName openkm.your-domain.com
  RedirectMatch ^/$ /openkm

# WebSocket support - needs proxy-wstunnel ProxyPass /openkm/frontend/webSocket ws://127.0.0.1:8080/openkm/frontend/webSocket ProxyPassReverse /openkm/frontend/webSocket ws://127.0.0.1:8080/openkm/frontend/webSocket
ProxyPass /openkm ajp://127.0.0.1:8009/openkm keepalive=On ProxyPassReverse /openkm http://openkm.your-domain.com/openkm
ErrorLog /var/log/apache2/openkm-error.log CustomLog /var/log/apache2/openkm-access.log combined </VirtualHost>

Change openkm.your-domain.com with your server IP or your domain value.

The VirtualHost ServerName must be other than ServerName in the main Apache configuration. Enable this site configuration:

$ cd /etc/apache2/sites-available/

$ sudo a2ensite openkm.conf

You have to enable explicitly the proxy access editing the Apache configuration file /etc/apache2/mods-available/proxy.conf:

$ vim /etc/apache2/mods-available/proxy.conf

<IfModule mod_proxy.c>
  #turning ProxyRequests on and allowing proxying from all may allow
  #spammers to use your proxy to send email.
 
  ProxyRequests Off
 
  <Proxy *>
    AddDefaultCharset off
    Order deny,allow
    Allow from all
    Deny from all
    #Allow from .example.com
  </Proxy>
 
  # Enable/disable the handling of HTTP/1.1 "Via:" headers.
  # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
  # Set to one of: Off | On | Full | Block
 
  ProxyVia On
</IfModule>

For security reasons, might you be interested in removing default apache configuration:

$ a2dissite 000-default.conf

Check the configuration

Restart Apache:

$ sudo /etc/init.d/apache2 restart

Check the access your OpenKM installation from http://openkm.your-domain.com/.  

Another advantage of using Apache is that you can log OpenKM access and generate web statistics.

To check the configuration files can execute the command:

/usr/sbin/apache2 -t

Red Hat and CentOS

Use the yum application manager to install Apache:

$ sudo yum install httpd

Enable it at boot:

$ sudo chkconfig httpd --level 2345 on

Now create the file /etc/httpd/conf.d/openkm.conf with this content:

$ vim /etc/httpd/conf.d/openkm.conf

<VirtualHost *:80>
  ServerName openkm.your-domain.com
  RedirectMatch ^/$ /openkm

# WebSocket support
ProxyPass /openkm/frontend/webSocket ws://127.0.0.1:8080/openkm/frontend/webSocket
ProxyPassReverse /openkm/frontend/webSocket ws://127.0.0.1:8080/openkm/frontend/webSocket

ProxyPass /openkm ajp://127.0.0.1:8009/openkm keepalive=On
ProxyPassReverse /openkm http://openkm.your-domain.com/openkm
ErrorLog /var/log/httpd/openkm-error.log CustomLog /var/log/httpd/openkm-access.log combined </VirtualHost>

Change openkm.your-domain.com with your server IP or your domain value.

Check the configuration

Restart Apache:

$ sudo /etc/init.d/httpd restart

If this command fails, try with:

$ sudo systemctl restart httpd

Check the access your OpenKM installation from http://openkm.your-domain.com/.  

Another advantage of using Apache is that you can log OpenKM access and generate web statistics.

Error Permission denied: proxy: AJP: attempt to connect

If  in the log appears an error like Permission denied: proxy: AJP: attempt to connect to solve executing the next command:

$ /usr/sbin/setsebool httpd_can_network_connect 1

If it works then set the configuration permanent to persist across reboots:

$ /usr/sbin/setsebool -P httpd_can_network_connect 1

Windows

The Apache web server is already included in "extras" folder.

Edit the C:\tomcat\extras\Apache\conf\httpd.conf configuration file and uncomment the VirtualHost section at bottom. Modify the ServerName to match your server name or IP:

<VirtualHost *:80>
ServerName 192.168.10.230

ProxyPass /openkm ajp://localhost:8009/openkm
ProxyPassReverse /openkm http://192.168.10.230/openkm

ErrorLog logs/openkm-error.log
CustomLog logs/openkm-access.log combined
</VirtualHost>

Change 192.168.10.230 with your server ip or your domain value.

Register Apache service

C:\> cd tomcat/extras/Apache/bin

C:\> httpd.exe -k install

Apache SSL configuration

Set openSSL configuration location:

C:\> set OPENSSL_CONF=C:\tomcat\extras\Apache\conf\openssl.cnf

Execute this command to generate the self-certificate:

C:\> cd c:/tomcat/extras/Apache/bin
C:\> openssl.exe req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ..\conf\server.key -out ..\conf\server.crt

This is a sample output:

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:Alicante
Locality Name (eg, city) []:Alicante
Organization Name (eg, company) [Internet Widgits Pty Ltd]:OpenKM
Organizational Unit Name (eg, section) []:IT Manager
Common Name (e.g. server FQDN or YOUR name) []:192.168.10.230
Email Address []:noreply@openkm.com

Change 192.168.10.230 with your server ip or your domain value.

Un comment this configuration section:

# Secure (SSL/TLS) connections
Include conf/extra/httpd-ssl.conf

Change default server name in conf/extras/httpd-ssl.conf to match your domain or IP:

# General setup for the virtual host
DocumentRoot "${SRVROOT}/htdocs"
ServerName 192.168.10.230:443
ServerAdmin admin@example.com
ErrorLog "${SRVROOT}/logs/error.log"
TransferLog "${SRVROOT}/logs/access.log"

Troubleshooting

If you see an error message like:

Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration

You need to enable this Apache module:  

$ sudo a2enmod rewrite
$ sudo a2enmod proxy_http
$ sudo a2enmod headers

If you see errors like these:

[proxy_ajp:error] [pid 27579:tid 140057021224704] (70007)The timeout specified has expired: AH01030: ajp_ilink_receive() can't receive header
[proxy_ajp:error] [pid 27579:tid 140057021224704] [client xxx.xxx.xxx.xxx:60526] AH00992: ajp_read_header: ajp_ilink_receive failed      
[proxy_ajp:error] [pid 27579:tid 140057021224704] (70007)The timeout specified has expired: [client xxx.xxx.xxx.xxx:60526] AH00878: read response failed from 127.0.0.1:8009 (127.0.0.1)

Is possible that Tomcat is not accepting AJP connections. Please, uncomment these lines at $TOMCAT_HOME/conf/server.xml

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector protocol="AJP/1.3"
           address="127.0.0.1"
           port="8009"
           redirectPort="8443"
           secretRequired="false" />

The secretRequired parameter is importar, and if it's not present you need to add.

More info at Apache Tomcat 8 Configuration Reference.

Additional information