HTTPS Wildcard Subdomain: DNS + Apache + Tomcat Config

I recently had to configure HTTPS on a wildcard subdomain with Apache HTTP server as reverse proxy to a Tomcat backend. I had few more requirements:

  1. Redirect all http traffic to https and preserve the subdomain (hostname). For instance:
    • http://sub1.example.com/ -> redirect to -> https://sub1.example.com/
    • http://sub2.example.com/ -> redirect to -> https://sub2.example.com/
    • etc.
  2. I want to have a PHP wiki on the subdirectory /wiki and I want to send the rest of the traffic to Tomcat.
  3. Tomcat needs to know the subdomain (hostname) and will serve content accordingly.
  4. I don’t know the subdomains in advance because they are chosen by users, just like *.wordpress.com

Few parts were not trivial, so I will share my setup.

DNS Wildcard Subdomain Configuration

DNS is probably the easiest part. Nowadays, most domain registrar offer good DNS support for free with your domain. If that is not the case of your registrar, you may want to consider namecheap. Their DNS also support wildcard entries. Otherwise, you can use the popular Bind DNS server. Here is how to configure a wildcard entry in BIND. Change 55.55.55.55 with your IP address.

Apache Wildcard Subdomain Configuration

This was trickier. The Apache HTTP server configuration has 2 main parts.

1. HTTP (port 80): We use mod_rewrite to redirect all traffic for *.example.com to https (port 443) and we preserve the hostname with the %{HTTP_HOST} variable.

2. HTTPS (port 443): Except for the PHP subdirectory (/wiki), we reverse proxy all traffic to Tomcat, which listen on port 9090 of localhost.

Tomcat Wildcard Subdomain Configuration

Below you’ll find the configuration of Tomcat (in server.xml), which is quite standard. Actually, we do not need to define any “wildcard“, we just define a defaultHost in the Engine element. Then we deploy a ROOT.war in the webapps directory (/opt/example.com/tomcat7/webapps) to serve all content at the root context path.

How does Tomcat Know the Subdomain?

With this configuration, all content will be sent to Tomcat with “localhost” as the hostname. Fortunately, the Apache reverse proxy will send extra request headers to Tomcat, namely:

X-Forwarded-For: The IP address of the client.

X-Forwarded-Host: The original host requested by the client in the Host HTTP request header.

X-Forwarded-Server: The hostname of the proxy server.

So in Tomcat (or any other servlet container), just use the Java code below to get the value of that header “X-Forwarded-Host” and you’ll know the subdomain.

 

Alternatively, you may also use the ProxyPreserveHost On directive in Apache configuration and you should be able to get the hostname (subdomain) normally in Tomcat. NOTE: I haven’t tested that setup.

Bonus: Wildcard SSL Certificate

Of course you’ll need a wildcard SSL certificate. Those are usually very expensive, but Namecheap resells Comodo wildcard certificate at very good price. No, I do not have any interest in namecheap, they just happen to be very good at what they do :)