Skip to content

Configuring Apache HTTPS Reverse-Proxy

Exposing OpenKM directly from Tomcat can be dangerous if you need the application to be accessed from the Internet (for example https://issues.jboss.org/browse/JBAS-3861). As a result you can be infected by PerlBot. Also port 8080 may be blocked by a firewall. For these reasons, it is a good practice 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 them to the 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.

Your OpenKM can be accessed from two different zones: Internet and LAN. This means that to access this server you need to use two IP addresses: 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 and 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 computer connected in an external network such as 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 to be 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 the Internet. To resolve the Internet IP (67.166.214.148) your computer uses the public DNS. So, you need to configure a local DNS server inside the LAN or modify every client’s hosts file to resolve to the internal IP.

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

Terminal window
$ 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:

Terminal window
$ vim /etc/apache2/apache2.conf
ServerRoot "/etc/apache2"
ServerName "your-domain.com"

Enable the proxy module:

Terminal window
$ sudo a2enmod proxy_ajp
$ sudo a2enmod proxy_wstunnel

Create the Certificates

Terminal window
$ sudo mkdir /etc/apache2/ssl
$ sudo /usr/sbin/make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/ssl/apache.pem
$ sudo a2enmod ssl

Ensure port 443 is listed in /etc/apache2/ports.conf:

Terminal window
$ cat /etc/apache2/ports.conf | grep Listen

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

Terminal window
$ vim /etc/apache2/sites-available/openkm.conf
<VirtualHost *:443>
ServerName openkm.your-domain.com
RedirectMatch ^/$ /openkm
# WebSocket support - needs proxy-wstunnel
ProxyPass /openkm/webSocket wss://127.0.0.1:8080/openkm/webSocket
ProxyPassReverse /openkm/webSocket wss://127.0.0.1:8080/openkm/webSocket
ProxyPass /openkm ajp://127.0.0.1:8009/openkm
ProxyPassReverse /openkm https://openkm.your-domain.com/openkm
ErrorLog /var/log/apache2/openkm.your-domain.com-error.log
CustomLog /var/log/apache2/openkm.your-domain.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.pem
</VirtualHost>

The VirtualHost ServerName must be different from the ServerName in the main Apache configuration. Enable this site configuration:

Terminal window
$ cd /etc/apache2/sites-available/
$ sudo a2ensite openkm.conf

Edit the configuration file /etc/apache2/sites-available/openkm.conf and add this content

Terminal window
$ vim /etc/apache2/sites-available/openkm.conf
<VirtualHost *:80>
ServerName openkm.your-domain.com
Redirect permanent / https://openkm.your-domain.com/
</VirtualHost>

Restart Apache:

Terminal window
$ sudo /etc/init.d/apache2 restart

Check access to your OpenKM installation at https://openkm.your-domain.com/.

Let’s Encrypt is a free certificate authority that provides X.509 certificates for Transport Layer Security (TLS) encryption at no charge. To be able to request and install the certificates you need the certbot utility. If you are using Apache, you also need the certbot-apache package:

Terminal window
$ apt install certbot certbot-apache

Once installed, execute the utility with these parameters:

Terminal window
$ certbot --domain <your-domain-name> --email <your-sysadmin-email> --agree-tos --redirect --apache

This certificate will be valid for 90 days, so you need to renew it before it expires. It’s a good practice to create a cron task to update it automatically:

Terminal window
@monthly /usr/bin/certbot renew

Also keep in mind that both ports 80 and 443 should be accessible from the Internet to validate the domain and generate the certificate.

Use the yum application manager to install Apache:

Terminal window
$ sudo yum install httpd

Enable it at boot:

Terminal window
$ sudo chkconfig httpd --level 2345 on

Create the Certificate

Terminal window
$ sudo yum install mod_ssl openssl crypto-utils

Generate private keys (for more information, visit Apache HTTP Secure Server Configuration).

Terminal window
$ genkey your-domain.com

During the process, two files will be generated at:

ReplaceSSLCertificateFile /etc/pki/tls/certs/your-domain.com.cert
SSLCertificateKeyFile /etc/pki/tls/private/your-domain.com.key

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

Terminal window
$ vim /etc/httpd/conf.d/openkm.conf
<VirtualHost *:443>
ServerName openkm.your-domain.com
ProxyPass / ajp://localhost:8009/openkm/
ProxyPassReverse / http://your-domain.com/openkm/
ErrorLog /var/log/your-domain.com-error.log
CustomLog /var/log/your-domain.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/your-domain.com.cert
SSLCertificateKeyFile /etc/pki/tls/private/your-domain.com.key
</VirtualHost>

Finally, you must modify SSLCertificateFile and SSLCertificateKeyFile values in the file /etc/httpd/conf.d/ssl.conf:

Terminal window
$ vim /etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/pki/tls/certs/your-domain.com.cert
SSLCertificateKeyFile /etc/pki/tls/private/your-domain.com.key

Restart Apache:

Terminal window
$ sudo /etc/init.d/httpd restart

Check access to your OpenKM installation at https://openkm.your-domain.com/.

Error Permission denied: proxy: AJP: attempt to connect

Section titled “Error Permission denied: proxy: AJP: attempt to connect”

If the log shows an error like Permission denied: proxy: AJP: attempt to connect, solve it by executing the following command:

Terminal window
$ /usr/sbin/setsebool httpd_can_network_connect 1

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

Terminal window
$ /usr/sbin/setsebool -P httpd_can_network_connect 1

If you see an error like:

You need to enable these Apache modules:

Terminal window
$ sudo a2enmod rewrite
$ sudo a2enmod proxy_http
$ sudo a2enmod headers

If you see errors like these:

Terminal window
[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)

It is possible that Tomcat is not accepting AJP connections. Please uncomment these lines in $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 important, and if it’s not present you need to add it.

More info at Apache Tomcat 8 Configuration Reference.