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!


19 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

  14. Hi Chris, thanks for the helpful post. I’ve stuck with the separate files for each site as per ubuntu set up. I’ve put the NameVirtualHost directives in the 000-default and then the first SSL site turns on SSL and has the cert paths etc. Seems to work OK though don’t like the way it is reliant on order. Great to have this up and running though, great post!
    James

    Comment by James Crisp — July 5, 2012 @ 12:04 am

  15. Actually wildcard ssl certificate should work for https://domain.com as well as https://xxx.domain.com where xxx is any subdomain name (see https://secure-sites.us/ for an example)

    More info on exactly what wildcard ssl certificates cover can be found at http://answers.ssl.com/1861/wildcard-ssl-certificate

    Comment by Jason Moran — November 2, 2012 @ 1:43 pm

  16. you did nice work your post is awesome its increase my knowledge.the post is best i can never read before this type of post nice sharing

    Comment by sac longchamp discount — March 22, 2013 @ 2:09 am

  17. They told me it couldn’t be done! I am the happiest web developer now. (But I’m poor after purchasing that wildcard certificate.)

    In case you’re still wondering, it works fine with * instead of the IP address in the VirtualHost declaration:

    NameVirtualHost *:443
    Listen 443
    
       ServerName a.example.org
       DocumentRoot /var/www/a
       SSLEngine on
       SSLCertificateFile /etc/ssl/wildcard_server.crt
       SSLCertificateKeyFile /etc/ssl/private/wildcard_server.key
       # etc...
    
    
       ServerName b.example.org
       DocumentRoot /var/www/b
       SSLEngine on
       SSLCertificateFile /etc/ssl/wildcard_server.crt
       SSLCertificateKeyFile /etc/ssl/private/wildcard_server.key
       # etc...
    

    Note, however, that my Apache needed the SSL particulars in each VirtualHost declaration, else I would get this error message: “Server should be SSL-aware but has no certificate configured [Hint: SSLCertificateFile]” upon restarting Apache, before even attempting to connect to the httpd daemon over port 443.

    Server version: Apache/2.2.22 (Ubuntu)

    Comment by Kevin — June 10, 2013 @ 7:27 pm

  18. […] If you’ve only got a single IP address and are using VHOSTs, then I’d go for the wildcard certificate as Apache only allows one cert per static IP. There’s a walkthrough on how to set Apache up this way here […]

    Pingback by UCC or WildCard SSL? - Just just easy answers — September 7, 2013 @ 12:25 am

  19. […] That should get you up and running with a neato dev environment. If you need to run SSL, I wrote a post on Creating Self-Signed Certs on Apache 2.2 and Virtual Hosts and Wildcard SSL Certificates with Apache 2.2. […]

    Pingback by CB1 Ubuntu 10.10 Linux Development Setup | CB1, INC. — November 22, 2014 @ 6:34 pm

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.