Apache mod_proxy: Multiple virtual hosts disable each other

I have an Ubuntu 12.04 server, which had Redmine already installed on a stand-alone apache (everything under /opt/redmine). I wanted to install an instance of Jenkins on the same system, without modifying the existing set-up too much. I want the two services to be accessible under sub.domain.com/redmine and sub.domain.com/jenkins respectively.

I changed Redmines apache to listen on port 8081 instead of 80, installed an additional apache via apt, and set up a virtual host that proxies '/redmine' to localhost:8081/redmine. Thus far everything worked fine. Redmine was accessible as before. However, when I set up Jenkins the same way, with tomcat listening on port 8080, the URL prefix 'jenkins' and a new virtual host, Redmine stops working, i.e. I get a 404. When I remove the Jenkins virtual host, Redmine works again.

Here are the two files under /etc/apache2/sites-available, which I enable/disable via a2ensite/a2dissite.

Redmine:

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName sub.domain.com
    ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPreserveHost off
    ProxyPass /redmine http://localhost:8081/redmine
    ProxyPassReverse /redmine http://localhost:8081/redmine
</VirtualHost>

Jenkins:

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName sub.domain.com
    ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPreserveHost off
    ProxyPass /jenkins http://localhost:8080/jenkins
    ProxyPassReverse /jenkins http://localhost:8080/jenkins
</VirtualHost>

I assume there is an issue with one or both of those files. I copied them from a Jenkins tutorial that assumed only a single virtual host. Wherever I look for mod_proxy solutions for multiple hosts, I find examples which map different ports to different domains, i.e. with different ServerNames. But that is not what I want. Do I have to use the RewriteEngine?


Solution 1:

You need to use a single virtual host to handle both!

Apache matches vhosts based on the HTTP Host header. Since the hostname is the same regardless of whether a client is accessing redmine or jenkins, both must in the same vhost.

What is happening with your current configuration is that Apache is determining which vhost to match as soon as it sees the Host header. Because 'j' comes before 'r' alphabetically, it is giving priority to your jenkins vhost file, even though both match.

You are trying to match based on the request URI, and proxy accordingly.

The <Proxy> directive already has this functionality built in!

You could use something like the following in a single vhost to accomplish your objective:

<VirtualHost *:80>
ServerAdmin [email protected]
ServerName sub.domain.com
ProxyRequests Off

<Proxy http://sub.domain.com/jenkins>

    Order deny,allow
    Allow from all

    ProxyPreserveHost off
    ProxyPass http://localhost:8080/jenkins
    ProxyPassReverse http://localhost:8080/jenkins

</Proxy>
<Proxy http://sub.domain.com/redmine>

    Order deny,allow
    Allow from all

    ProxyPreserveHost off
    ProxyPass http://localhost:8081/redmine
    ProxyPassReverse http://localhost:8081/redmine

</Proxy>

</VirtualHost>