Confluence itself does not support multiple domains out of the box, however this is desired for certain Scroll Viewport use cases. 

If your Confluence installation sits behind a reverse proxy and you want to run a viewport on a domain that is different from the Confluence base URL, you may have to make some changes to your networking setup to ensure that everything works correctly.

Common effects of an incomplete configuration are:

  • Viewports with a custom domain name are not reachable
  • Confluence rejecting certain requests whose server name does not match the name of the host. 
    • For example: POST requests to /rest/webResources/1.0/resources that fail with a status code of 403

Required Configuration Changes

There are several ways to configure Confluence / Tomcat and a reverse proxy to support multiple domains in Scroll Viewport, each with certain drawbacks and benefits.

If you just want to configure one additional domain, choose approach 1. If you need many additional domains, choose approach 2.

Approach 1: Additional Tomcat Connector

For this approach we'll configure a separate Tomcat listener for the additional domain.

multiple-connectors

Properties of this approach:

(plus) Simple to set up

(plus) Compatible with Confluence setup checks

(minus) Requires additional memory for the threads serving requests for the new connector (1MB per thread configured in maxThreads attribute)

(minus) Configuration overhead when many additional domains are required

Tomcat Configuration

In server.xml find the enabled connector. It should look like this:

Original server.xml

<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
           maxThreads="48" minSpareThreads="10"
           enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           scheme="https" proxyName="wiki.example.com" proxyPort="443"/>
CODE

Now copy it and adapt the port and proxyName attributes:

Modified server.xml

<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
           maxThreads="48" minSpareThreads="10"
           enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           scheme="https" proxyName="wiki.example.com" proxyPort="443"/>

<Connector port="8095" connectionTimeout="20000" redirectPort="8443"
           maxThreads="48" minSpareThreads="10"
           enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           scheme="https" proxyName="docs.example.com" proxyPort="443"/>
CODE

Set the attributes as follows:

  • port needs to be set to an unused port. Please note that synchrony be default runs on port 8091.
  • proxyName should contain the additional domain name.
  • proxyPort should be the same for both connectors unless the reverse proxy uses different ports for the virtual hosts.

(info) Changes to server.xml require you to restart Confluence to have any effect.

Reverse Proxy Configuration

You need to create a separate virtual host in your reverse proxy configuration. Here's the NGINX example from Atlassian's docs:

server {
    listen 443;
    server_name wiki.example.com;
    location /confluence {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_pass http://localhost:8090/confluence;
    }
}
CODE

Now copy this server block and adapt the server_name and proxy_pass directives, so they match the additional domain and the respective connector port:

server {
    listen 443 ssl;
    server_name wiki.example.com;
	...
    location /confluence {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_pass http://localhost:8090/confluence;
    }
}


server {
    listen 443 ssl;
    server_name docs.example.com;
	...
    location /confluence {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_pass http://localhost:8095/confluence;
    }
}
CODE

(info) Don't forget to restart the reverse proxy.

Approach 2: Shared Tomcat Connector for multiple Domains

For this approach we'll configure a single Tomcat connector so it supports multiple domains.

The actual domain used by requests will be extracted from a HTTP header which needs to be set by the reverse proxy.

generic-connector

Properties of this approach:

(plus) Does not require additional memory for multiple tomcat connectors

(plus) No Confluence configuration updates and restart required when adding further domains later on

(minus) Not compatible with Confluence setup checks. Confluence system administrators will get warnings from Confluence. Disable the "Confluence Base Url Plugin" to suppress.

(minus) More complicated to set up initially

(minus) Atlassian support might not be aware of this setup

Tomcat Configuration

In server.xml find the enabled connector. It should look like this:

Original Connector

<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
           maxThreads="48" minSpareThreads="10"
           enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
           protocol="org.apache.coyote.http11.Http11NioProtocol"
           scheme="https" proxyName="wiki.example.com" proxyPort="443"/>
CODE

Now remove the attributes related to the proxy: schemeport and proxyName.

Modified Connector

<Connector port="8090" connectionTimeout="20000" redirectPort="8443"
           maxThreads="48" minSpareThreads="10"
           enableLookups="false" acceptCount="10" debug="0" URIEncoding="UTF-8"
           protocol="org.apache.coyote.http11.Http11NioProtocol"/>
CODE

Next find the Context element in server.xml (the path attribute might be different, depending on your setup):

Original Context

<Context path="" docBase="../confluence" debug="0" reloadable="false" useHttpOnly="true">
    <!-- Logging configuration for Confluence is specified in confluence/WEB-INF/classes/log4j.properties -->
    <Manager pathname=""/>
    <Valve className="org.apache.catalina.valves.StuckThreadDetectionValve" threshold="60"/>
</Context>
CODE

Finally add another Valve element as follows. This valve will extract the original request's domain name and provide it to the connector.

Modified Context

<Context path="" docBase="../confluence" debug="0" reloadable="false" useHttpOnly="true">
    <!-- Logging configuration for Confluence is specified in confluence/WEB-INF/classes/log4j.properties -->
    <Manager pathname=""/>
    <Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="x-forwarded-for" protocolHeader="x-forwarded-proto" />
    <Valve className="org.apache.catalina.valves.StuckThreadDetectionValve" threshold="60"/>
</Context>
CODE

(info) Changes to server.xml require you to restart Confluence to have any effect.

Reverse Proxy Configuration

The RemoteIpValve requires several additional HTTP headers to retrieve the original request data from.

Here's the NGINX example from Atlassian's docs:

server {
    listen 443 ssl;
    server_name wiki.example.com;
    location /confluence {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        
        proxy_pass http://localhost:8090/confluence;
    }
}
CODE

Now add headers as follows:

Nginx vhost definition

server {
    listen 443 ssl;
    server_name wiki.example.com;    
    ...
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Ssl $https;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;

        proxy_pass http://localhost:8090;
    }
}
TEXT

Repeat such a server block for each domain you require.

(info) Don't forget to restart the reverse proxy.