Using virtual hosts

You can use virtual hosts if you want isolation between applications and the endpoints that serve them.

Open Liberty Documentation for using virtual hosts in version 21.0.0.10 and later is available on the Open Liberty website.

A single application server is often responding to requests from multiple different host and port configurations. This occurs for a combination of reasons, such as it is running on a machine with multiple network interfaces with different names or it is routed to from an http server, proxy, or load balancer. In these cases, you might want to control which application can be contacted from a specific host. Virtual hosts provide this capability. It matches the requested host name and port number (as determined from the HTTP Host header) against the configured list of host aliases.

In WebSphere® Application Server Liberty, the default configuration is sufficient. The default virtual host (default_host) matches requests from any incoming host and port combination, and forwards them on to the default application container.

The following list illustrates the key configuration elements when you are configuring virtual hosts.
  • The virtualHost configuration element ID value.
  • The hostAlias subelement configuration.
  • The allowFromEndpoint subelement configuration (if used).
  • The virtual host configuration in the ibm-web-bnd.xml or ibm-web-bnd.xmi file of the WAR.
  • The host attribute value of the httpEndpoint.
  • The ID attribute value of the httpEndpoint.

Isolating two applications from each other

The following example illustrates one of the more common usages of virtual hosting to give an understanding of some of the configuration that is required. This example shows how to configure two applications that run on differing ports. Further in this example illustrates that one application is only available on the localhost interface.
<httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="9080" />
<httpEndpoint id="alternateEndpoint" host="*" httpPort="9081" />

<virtualHost id="application-1">
    <hostAlias>your_host_name:9080</hostAlias>
</virtualHost>

<virtualHost id="application-2">
    <hostAlias>localhost:9081</hostAlias>
</virtualHost>

<enterpriseApplication location="myApp.ear" name="App1"/>
<webApplication location="myApp2.war" name="App2" />

The defaultHttpEndpoint exposes all interfaces on port 9080, and the alternateEndpoint exposes all interfaces on port 9081.

If App1 has a WAR file with an ibm-web-bnd.xml file that specifies <virtual-host name="application-1"/>, then this application can be accessed only at your_host_name:9080/app1_context_root.

If App2 (which is a WAR) has an ibm-web-bnd.xml file that specifies <virtual-host name="application-2"/>, then this application can be accessed only at localhost:9081/app2_context_root.

If a third application was deployed which specified no specific virtual host, in this configuration, that application would be accessible only if it were a proxied request that contained HOST header that specifies a different port. For example, if the request was made to a proxy on port 80, that port is not listed in any of the hostAlias specifications, and so the request would be routed to the default_host virtual host.

Isolating applications based on the requested host or port

The default virtual host in Liberty is also used for JMX communications. If you wanted to isolate JMX communications from application traffic, you would need to complete the following steps.
  1. Decide on your virtual host name, and update your application to reference the new (non-default) host. Add a virtual-host element to the ibm-web-bnd.xml or ibm-web-bnd.xmi file of the WAR.
    <?xml version="1.0" encoding="UTF-8"?>
    <web-bnd
        xmlns="http://websphere.ibm.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://websphere.ibm.com/xmk/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd"
        version="1.0" />
    
        <virtual-host name="proxiedRequests" />
    
    </web-bnd>
  2. Add a virtualHost element to your server.xml file. The name must match what is specified in the application, and must define hostAliases that are routed to the new virtual host.
    Note: The host name and the port that is being matched is the one that is originally requested by the user, which might or might not match the host and port that Liberty is using. The following example illustrates a virtual host element added to your server.xml file.
    <virtualHost id="proxiedRequests">
        <hostAlias>external.host.name:80</hostAlias>
        <hostAlias>external.host.name:443</hostAlias>
    </virtualHost>

    If requests are coming from a proxy, this configuration alone routes any request that is made to the proxy's host and port to the "proxiedRequests" virtual host.

Restricting access based on originating endpoint

If you want to restrict access to the default/system applications that are using the defaultHttpEndpoint, there are more steps to take.
  1. Define another httpEndpoint. The following example illustrates another httpEndpoint.
    <httpEndpoint id="localHostOnly" host="localhost" httpPort="9081" httpsPort="9444"/>

    This http endpoint specifies that host="localhost," meaning that ports 9081 and 9444 are exposed only on the localhost interface.

  2. Update virtualHost definitions to specify the allowFromEndpointRef attribute. When this attribute is specified, a virtualHost accepts requests only from the specified endpoint. For example:
    <virtualHost id="default_host" allowFromEndpointRef="localHostOnly">
        <hostAlias>*:9081</hostAlias>
        <hostAlias>*:9444</hostAlias>
    </virtualHost>
    
    </virtualHost id="proxiedRequests">
        <hostAlias>*:9080</hostAlias>
        <hostAlias>*:9443</hostAlias>
        <hostAlias>external.host.name:80</hostAlias>
        <hostAlias>external.host.name:443</hostAlias>
    </virtualHost>
    With this configuration:
    • The default_host virtual host now accepts requests that are directed only at localhost:9081 and localhost:9444 that also originate from the localHostOnly endpoint. Any other request to ports 9081 and 9444 are refused. For example, a request from the defaultHttpEndpoint with Host headers that reference localhost:9081 is refused.
    • The proxiedRequests virtual host now accepts any request that is issued to port 9080, or 9443 (which are the default ports that are used by the defaultHttpEndpoint), in addition to those that have a Host header that references the external host name from the proxy and port 80 or 443.