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!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Reddit

13 Comments »

  1. The “export” command was truncated in the post above. Should have been:
      export SAN=’DNS:[base-domain-name]‘
    Eg,
      export SAN=’DNS:site-a.com’

    Comment by Warwick — November 5, 2008 @ 12:38 am

  2. If you want browsers to be happy with the certificate when hitting the base domain (site-a.com), you might want to look at signing the certificate with a subjectAlternativeName set to the base domain as well.

    My openssl.conf has “subjectAltName=${ENV::SAN}” in the [ usr_crt ] section, and I set the environment variable (eg “export SAN=’DNS:‘”) before running the openssl commands to create the certificate.

    Comment by Warwick — November 5, 2008 @ 12:36 am

  3. I ran into a similar problem just the other day with redirects. Your config looks good. The problem was browser cache. I had to empty my cache and restart my browser and then the redirects worked.

    Comment by Chris Barber — February 27, 2009 @ 7:30 pm

  4. I configured my sites-enabled conf like yours, direkt SSL is working fine, but if I go to http://www.domain.com or xyz.domain.com I see a bad request (400) and a redirect to https://domain.com regardless what subdomain I used. (so the redirect is not working and http://www.domain.com didn’t work too) only the direkt SSL will work like https://test.domain.com the wildcard certificate works well with the direkt SSL connection, so it have to be the config :hmm: I’m not sure if the fcgi config have to be on every VirtualHost

    1 NameVirtualHost 84.200.208.192:80
    2 NameVirtualHost 84.200.208.192:443
    3
    4
    5 ServerName suretodie.de
    6 ServerAlias http://www.suretodie.de
    7 ServerAdmin admin@suretodie.de
    8 DocumentRoot /var/www/web1/web/
    9
    10
    11 SuexecUserGroup web1 web1
    12 PHP_Fix_Pathinfo_Enable 1
    13
    14 Options +ExecCGI
    15 AllowOverride All
    16 AddHandler fcgid-script .php
    17 FCGIWrapper /var/www/php-fcgi-scripts/web1/php-fcgi-starter .php
    18 Order allow,deny
    19 Allow from all
    20
    21

    22
    23 # ErrorLog /var/log/apache2/error.log
    24 # CustomLog /var/log/apache2/access.log combined
    25 ServerSignature Off
    26
    27 SSLEngine On
    28 SSLCertificateFile /etc/apache2/ssl/suretodie.crt
    29 SSLCertificateKeyFile /etc/apache2/ssl/suretodie.key
    30
    31

    32
    33 #Redirects
    34 # Not SSL, redirect to https://qmail.suretodie.de
    35
    36 ServerName qmail.suretodie.de
    37 Redirect / https://qmail.suretodie.de/
    38

    39
    40
    41 ServerName webmail.suretodie.de
    42 Redirect / https://webmail.suretodie.de/
    43

    44
    45
    46
    47 ServerName qmail.suretodie.de
    48 ServerAdmin admin@suretodie.de
    49 DocumentRoot /var/www/web1/qmailad/
    50
    51
    52 SuexecUserGroup web1 web1
    53 PHP_Fix_Pathinfo_Enable 1
    54
    55 Options +ExecCGI
    56 AllowOverride All
    57 AddHandler fcgid-script .php
    58 FCGIWrapper /var/www/php-fcgi-scripts/web1/php-fcgi-starter .php
    59 Order allow,deny
    60 Allow from all
    61
    62

    63
    64 # ErrorLog /var/log/apache2/error.log
    65 # CustomLog /var/log/apache2/access.log combined
    66 ServerSignature Off
    67

    68
    69
    70 ServerName webmail.suretodie.de
    71 ServerAdmin admin@suretodie.de
    72 DocumentRoot /var/www/web1/webmail/
    73
    74
    75 SuexecUserGroup web1 web1
    76 PHP_Fix_Pathinfo_Enable 1
    77
    78 Options +ExecCGI
    79 AllowOverride All
    80 AddHandler fcgid-script .php
    81 FCGIWrapper /var/www/php-fcgi-scripts/web1/php-fcgi-starter .php
    82 Order allow,deny
    83 Allow from all
    84
    85

    86
    87 # ErrorLog /var/log/apache2/error.log
    88 # CustomLog /var/log/apache2/access.log combined
    89 ServerSignature Off
    90

    Comment by hackbard — February 27, 2009 @ 5:00 pm

  5. sry for that copy crap, here is a better pastebin
    http://pastebin.com/m5a3d5201
    you can delete my other post

    “I configured my sites-enabled conf like yours, direkt SSL is working fine, but if I go to http://www.domain.com or xyz.domain.com I see a bad request (400) and a redirect to https://domain.com regardless what subdomain I used. (so the redirect is not working and http://www.domain.com didn’t work too) only the direkt SSL will work like https://test.domain.com the wildcard certificate works well with the direkt SSL connection, so it have to be the config :hmm: I’m not sure if the fcgi config have to be on every VirtualHost”

    greets hackbard

    Comment by hackbard — February 27, 2009 @ 5:12 pm

  6. Hi Chris!

    I checked it with deleted cache in IE and Firefox, the same as before. With the IE nothing is shown, no error, no redirect, no index :hmm:
    In firefox the same as belwo shows up.

    I don’t get whats wrong :hmm:

    my second domain shows the same error in FF, “go to https://suretodie.de

    :hmm:²

    Comment by hackbard — March 2, 2009 @ 10:13 am

  7. I think I’ve got it. I splittet up the first vhost entry like this:
    http://pastebin.com/m3eceb493
    After that the bad Requests gone away and the little Indian Apache works.
    Thx for your help and config.

    Greetz hackbard

    Comment by hackbard — March 5, 2009 @ 9:35 am

  8. Hmm, well, that was easy. Good thinking!

    Comment by Chris Barber — March 5, 2009 @ 4:52 pm

  9. [...] Here is a good tutorial show you about Virtual Hosts and Wildcard SSL Certificates with Apache 2.2: 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. [...]

    Pingback by Virtual Hosts and Wildcard SSL Certificates with Apache 2.2 | TurboLinux Blog — August 4, 2011 @ 7:36 am

  10. [...] http://www.cb1inc.com/2008/09/11/vir…ith-apache-2.2 [...]

    Pingback by Multiple subdomains (virtual hosts) using a wildcard cert and single ip | Hosting Fit — September 8, 2011 @ 4:08 pm

  11. This is similar to my setup, however I have a problem. The “HTTPS=on” server environment variable is not set on those simple vhosts. It seems as if you need a full set of SSL* directives on each vhost in order for the env vars to be set.

    Comment by Huska — October 17, 2011 @ 12:50 pm

  12. Are you sure this works?

    According to the Apache documentation, it is not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts, unless you use Apache 2.2.12 or later web server, built with 0.9.8j or later OpenSSL.

    Is that the case?

    http://httpd.apache.org/docs/2.2/ssl/ssl_faq.html#vhosts2

    “It is possible, but only if using a 2.2.12 or later web server, built with 0.9.8j or later OpenSSL. This is because it requires a feature that only the most recent revisions of the SSL specification added, called Server Name Indication (SNI).

    The reason is that the SSL protocol is a separate layer which encapsulates the HTTP protocol. So the SSL session is a separate transaction, that takes place before the HTTP session has begun. The server receives an SSL request on IP address X and port Y (usually 443). Since the SSL request did not contain any Host: field, the server had no way to decide which SSL virtual host to use. Usually, it just used the first one it found which matched the port and IP address specified.”

    Comment by Luis Fernando Alen — January 13, 2012 @ 6:49 am

  13. Hallo Chris and hackbard,

    the pastebin links unfortunately are dead ends (okay, the post is a little old), so I can’t find out, where hackbard split his vhost entry. I also get a bad request (400) and a redirect to https://sitename.domain.com. I’m slightly better off though, as the redirect link at least works right, so users can manually reach the site. But it really looks ugly, so I’m trying to find a solution.
    hackbards idea might help with that, if I could get to see it. Any chance you remember?

    Comment by Linuxgirl — February 17, 2012 @ 9:05 am

RSS feed for comments on this post. TrackBack URL

Leave a comment