Introduction
In some cases, you may want to provide Abiquo access to different departments or organisations with different DNS subdomain name and a customised Abiquo UI theme per each subdomain. There are several ways to achieve this setup depending on the needs and resources available but this document covers a simple path with minimal resources required.
Sample Configuration
Scenario
We are going to describe this setup assuming the scenario described below. Note that you will need to adjust the rest of the commands in this document to suit your environment (mostly host names and IPs).
Machine | Host name | IP Address |
---|---|---|
Abiquo Monolithic & Apache2 SSL front-end | api.example.com | 192.168.1.100 |
Datacenter2 Remote Services | dc2rs.example.com | 192.168.1.150 |
Setup disclaimer
- Users must reach api.example.com, theme1.example.com and theme2.example.com. (DNS names must be resolvable)
- Abiquo API and RS must reach each other by all its DNS names
Once environment has been described, we are going into changes needed to achieve Abiquo UI theming per subdomain.
Abiquo UI configuration
In order to provide different themes per subdomain we need to do some changes in the default UI folder structure, by default looks like:
# tree /var/www/html/ui/ . ??? config ? ??? client-config.json ... ??? theme ? ??? abicloudDefault ...
We need to create a configuration file and theme folder per each subdomain. In the sample scenario the structure will look like:
# tree /var/www/html/ui/ . ??? config ? ??? theme1.json ? ??? theme2.json ... ??? theme1 ? ??? abicloudDefault ??? theme2 ? ??? abicloudDefault ...
You can have different property configuration in each config json file, but most important is that config.endpoint property points to its related API subdomain URL:
# grep endpoint /var/www/html/ui/config/* /var/www/html/ui/config/theme1.json: "config.endpoint": "https://theme1.example.com/api", /var/www/html/ui/config/theme2.json: "config.endpoint": "https://theme2.example.com/api",
Now, place you customised themes in the Abiquo UI root folder with a suitable name and ensure that the structure looks like how has been described before.
Apache SSL front-end
Apache will provide the SSL layer to Abiquo components and serve the Abiquo UI. We need to tell Apache to work with NameVirtualHost directive as we want to serve different content depending in the accessed hostname.
Ensure that NameVirtualHost directive is enabled for both HTTP and HTTPS protocols:
# grep "NameVirtualHost" /etc/httpd/conf/httpd.conf NameVirtualHost *:80 NameVirtualHost *:443
We need a VirtualHost configuration file per each subdomain plus a VirtualHost configuration file for API and Appliance Managers:
# tree /etc/httpd/conf.d/ . ??? conf.d ? ??? api.conf ? ??? theme1.conf ? ??? theme2.conf
First of all, let's have a look to api.conf. This VirtualHost configuration file will group SSL access for all Abiquo Appliance Manager webapps and API endpoint: (api.conf)
<VirtualHost *:80> RewriteEngine On RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301] </VirtualHost> <VirtualHost *:443> ServerName api.example.com RewriteEngine On ProxyRequests Off ProxyPreserveHost On # Avoid CORS when uploading a template from different domains <IfModule mod_headers.c> SetEnvIfNoCase Origin "https?://(api\.example\.com|theme1\.example\.com|theme2\.example\.com|dc2rs\.example\.com)(:\d+)?$" AccessControlAllowOrigin=$0 Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> # Subdomain1 download RewriteRule RewriteCond %{HTTP_REFERER} ^https://theme1\.example\.com/ui/ [NC] RewriteCond %{REQUEST_URI} ^/(.*)/files/.*$ [NC] RewriteRule /(.*)/files/(.*) https://theme1.example.com/$1/files/$2 [R,L] # Subdomain2 download RewriteRule RewriteCond %{HTTP_REFERER} ^https://theme2\.example\.com/ui/ [NC] RewriteCond %{REQUEST_URI} ^/(.*)/files/.*$ [NC] RewriteRule /(.*)/files/(.*) https://theme2.example.com/$1/files/$2 [R,L] <Location /api> ProxyPass ajp://localhost:8010/api retry=0 ProxyPassReverse ajp://localhost:8010/api </Location> # All Abiquo Appliance Managers managed in each datacenter # Datacenter1 Appliance Manager <Location /am> ProxyPass ajp://192.168.1.100:8010/am retry=0 timeout=1800 ProxyPassReverse ajp://192.168.1.100:8010/am </Location> # Datacenter2 Appliance Manager <Location /am-barcelona> ProxyPass ajp://192.168.1.150:8010/am retry=0 keepalive=On timeout=1800 ProxyPassReverse ajp://192.168.1.150:8010/am </Location> SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW SSLCertificateFile /etc/httpd/ssl/example.com.pem SSLCertificateKeyFile /etc/httpd/ssl/example.com.key CustomLog /var/log/httpd/api-access.log combined ErrorLog /var/log/httpd/api-error.log </VirtualHost>
There are few things we need highlight about the api.conf:
<IfModule mod_headers.c> ... </IfModule> section: This section is intended to deal with CORS browser protection when different subdomains interacts together for the Template upload functionality. As you can see, if new Datacenters or subdomains are added to the environment, this section will require to be modified to allow those new subdomains.
Subdomain X download RewriteRule section: This section is intended to deal with CORS browser protection when different subdomains interacts together for the Template download functionality. As you can see, if new subdomains are added to the environment, you will need to create correspondent RewriteCond and RewriteRule to allow the download.
Datacenter X Appliance Manager section: This section is intended to provide the SSL layer to the Appliance Manager webapp on all Datacenters. If Abiquo UI is running SSL, the Appliance Manager endpoint should be accessed also through SSL to avoid browser's Mixed-Content protection. Because of this, is a good practise to proxy all Appliance Manager request through Apache2 front-end which will provide the SSL layer. As you can see, if new Datacenters are added to the environment, you will need to create the correspondent Location section for the new Datacenter Appliance Manager.
There are other sections and parameters such as the certificate configuration, apache log files and ProxyPass extra options such retry, keepalive and timeout that can be modified depending in your environment. Refer to Apache website documentation to further information.
Now, we should create a VirtualHost configuration file per each subdomain. All files will look almost the same:
theme1.conf
<VirtualHost *:80> RewriteEngine On RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301] </VirtualHost> <VirtualHost *:443> ServerName theme1.example.com RewriteEngine On ProxyRequests Off ProxyPreserveHost On <Directory "/var/www/html/ui"> Options MultiViews AllowOverride None Order allow,deny Allow from all </Directory> RewriteRule ^/$ /ui/ [R] # Theme and config AliasMatch AliasMatch ^/ui/theme/(.*)$ /var/www/html/ui/theme1/$1 AliasMatch ^/ui/config/client-config.json /var/www/html/ui/config/theme1.json <Location /api> ProxyPass ajp://192.168.1.100:8010/api retry=0 ProxyPassReverse ajp://192.168.1.100:8010/api </Location> <Location /m> ProxyPass ajp://192.168.1.100:8010/m retry=0 ProxyPassReverse ajp://192.168.1.100:8010/m </Location> <Location /am> ProxyPass ajp://192.168.1.100:8010/am retry=0 timeout=1800 ProxyPassReverse ajp://192.168.1.100:8010/am </Location> <Location /am-barcelona> ProxyPass ajp://192.168.1.150:8010/am retry=0 keepalive=On timeout=1800 ProxyPassReverse ajp://192.168.1.150:8010/am </Location> <Location /legal> ProxyPass ajp://192.168.1.100:8010/legal retry=0 ProxyPassReverse ajp://192.168.1.100:8010/legal </Location> SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW SSLCertificateFile /etc/httpd/ssl/example.com.pem SSLCertificateKeyFile /etc/httpd/ssl/example.com.key CustomLog /var/log/httpd/theme1-access.log combined ErrorLog /var/log/httpd/theme1-error.log </VirtualHost>
theme2.conf
<VirtualHost *:80> RewriteEngine On RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301] </VirtualHost> <VirtualHost *:443> ServerName theme2.example.com RewriteEngine On ProxyRequests Off ProxyPreserveHost On <Directory "/var/www/html/ui"> Options MultiViews AllowOverride None Order allow,deny Allow from all </Directory> RewriteRule ^/$ /ui/ [R] # Theme and config AliasMatch AliasMatch ^/ui/theme/(.*)$ /var/www/html/ui/theme2/$1 AliasMatch ^/ui/config/client-config.json /var/www/html/ui/config/theme2.json <Location /api> ProxyPass ajp://192.168.1.100:8010/api retry=0 ProxyPassReverse ajp://192.168.1.100:8010/api </Location> <Location /m> ProxyPass ajp://192.168.1.100:8010/m retry=0 ProxyPassReverse ajp://192.168.1.100:8010/m </Location> <Location /am> ProxyPass ajp://192.168.1.100:8010/am retry=0 timeout=1800 ProxyPassReverse ajp://192.168.1.100:8010/am </Location> <Location /am-barcelona> ProxyPass ajp://192.168.1.150:8010/am retry=0 keepalive=On timeout=1800 ProxyPassReverse ajp://192.168.1.150:8010/am </Location> <Location /legal> ProxyPass ajp://192.168.1.100:8010/legal retry=0 ProxyPassReverse ajp://192.168.1.100:8010/legal </Location> SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW SSLCertificateFile /etc/httpd/ssl/example.com.pem SSLCertificateKeyFile /etc/httpd/ssl/example.com.key CustomLog /var/log/httpd/theme2-access.log combined ErrorLog /var/log/httpd/theme2-error.log </VirtualHost>
The only differences are the ServerName directive and the AliasMatch rules required to apply the desired theme per subdomain:
theme1.example.com
ServerName theme1.example.com AliasMatch ^/ui/theme/(.*)$ /var/www/html/ui/theme1/$1 AliasMatch ^/ui/config/client-config.json /var/www/html/ui/config/theme1.json
theme2.example.com
ServerName theme2.example.com AliasMatch ^/ui/theme/(.*)$ /var/www/html/ui/theme2/$1 AliasMatch ^/ui/config/client-config.json /var/www/html/ui/config/theme2.json
Abiquo.properties configuration
You only need to ensure that abiquo.server.api.location property points to the common API URL:
# grep api.location /opt/abiquo/config/abiquo.properties abiquo.server.api.location = https://api.example.com/api
Add certificates to Tomcat trust store
In the sample setup we used a wildcard certificate which allows us to use same certificate file for all VirtualHost configuration files. However, if you are using different certificates per each DNS name, you will need to specify correspondent certificate, key an CA files in the Apache VirtualHost configuration files.
We will need to add correspondent certificates and CA to all Abiquo Tomcat trust store files. You must follow next steps:
- Find and backup original cacerts file
- Download certificates
- Add certificates and CA to Tomcat trust store (cacerts file)
- Restart abiquo-tomcat service
In the sample environment we've performed the following steps to both Abiquo Monolithic server and Datacenter 2 Abiquo Remotes Services node:
#1# find / -iname cacerts #2# cp /usr/java/jdk1.7.0_21/jre/lib/security/cacerts /root/cacerts.201410011200 #3# echo -n | openssl s_client -connect api.example.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > example.com.cert #4# keytool -import -file example.com.cert -alias example.com -keystore /usr/java/jdk1.7.0_21/jre/lib/security/cacerts #5# service abiquo-tomcat restart
If you are not using a wildcard SSL certificate, repeat steps #3# and #4# per each DNS name involved in the environment. (In the sample scenario: theme1.example.com, theme2.example.com, api.example.com and dc2rs.example.com)
Having done the steps indicated above, you can now access https://theme1.example.com and https://theme2.example.com having different themes.