It is possible with Apache to host multiple websites with a single static IP address. However, you can only have one SSL certificate per static IP. This post describes setting up Apache with multiple secure virtual hosts and a single self-signed wildcard certificate. To learn about creating the certificate, check out Creating Self-Signed Certs on Apache 2.2.
Here’s a table of our example hosts:
| Domain | Force SSL? | Trusted? | Valid Domain? |
|---|---|---|---|
| www.site-a.com | No | No | Yes |
| secure.site-a.com | Yes | No | Yes |
| test.site-a.com | No | No | Yes |
| www.site-b.com | No | No | No |
| secure.site-b.com | Yes | No | No |
In order for the certificate to be trusted, you need to obtain the certificate from a trusted certificate authority. Since we are using self-signed certificates, they are not trusted and we will see some warning messages. The data will still be encrypted.
For this to work, we are going to use name-based virtual hosts.
The name and location of Apache’s configuration files vary based on which platform you use. This post assumes Ubuntu in which case the configuration files in the /etc/apache2 directory.
For starters, we need to tell Apache which ports to listen on by editing the file /etc/apache2/ports.conf.
Listen 80
<IfModule mod_ssl.c>
Listen 443
</IfModule>
Next we need to add our virtual hosts. They are kept in the /etc/apache2/sites-available directory. For organization purposes, separate your sites into separate config files, then run a2ensite for each site to generate a symbolic link in the /etc/apache2/sites-enabled directory.
Here is the configuration for the sites:
NameVirtualHost 192.168.1.200:80 NameVirtualHost 192.168.1.200:443 # http://site-a.com # https://site-a.com -- Throws warning because cert is for *.site-a.com... see bottom # http://www.site-a.com # https://www.site-a.com <VirtualHost 192.168.1.200:80 192.168.1.200:443> ServerName site-a.com ServerAlias www.site-a.com DocumentRoot /path/to/www.site-a # Note: SSL settings only need to be defined once! SSLEngine On SSLCertificateFile /path/to/thecert.crt SSLCertificateKeyFile /path/to/thecert.key </VirtualHost> # Not SSL, redirect to https://secure.site-a.com <VirtualHost 192.168.1.200:80> ServerName secure.site-a.com Redirect / https://secure.site-a.com/ </VirtualHost> # https://secure.site-a.com <VirtualHost 192.168.1.200:443> ServerName secure.site-a.com DocumentRoot /path/to/secure.site-a </VirtualHost> # http://test.site-a.com # https://test.site-a.com <VirtualHost 192.168.1.200:80 192.168.1.200:443> ServerName test.site-a.com DocumentRoot /path/to/test.site-a </VirtualHost> # http://www.site-b.com # https://www.site-b.com -- Throws warning because cert is for *.site-a.com <VirtualHost 192.168.1.200:80 192.168.1.200:443> ServerName www.site-b.com DocumentRoot /path/to/secure.site-b </VirtualHost> # Not SSL, redirect to https://secure.site-b.com <VirtualHost *:80> ServerName secure.site-b.com Redirect / https://secure.site-b.com/ </VirtualHost> # https://secure.site-b.com -- Throws warning because cert is for *.site-a.com <VirtualHost 192.168.1.200:443> ServerName secure.site-b.com DocumentRoot /path/to/secure.site-b </VirtualHost>
Despite having a wildcard certificate for *.site-a.com, you will get an invalid domain message when you don’t supply the subdomain (i.e. http://site-a.com). The only way I know of to solve this is with 2 static IPs and 2 certs where one cert is for site-a.com and the other is for *.site-a.com.
I’m using 192.168.1.200 for the server’s IP address behind the firewall. You could try using * instead of 192.168.1.200 in the <VirtualHost> blocks, but I haven’t tested this. Leave a comment if you happen to test this.
Assuming the stars have aligned, you should have several secured virtual hosts!
