You are here
Configuring Apache for Virtual Hosts and SSL Connections on Ubuntu 10.04 using Apache 2.2
There is a lot of noise out there when it comes to blog entries about getting Apache VirtualHosts working and especially with SSL. While I've had it working in my sandbox for a couple of years now I recently had to get to the bottom of this mess and really understand what the bare minimum for a set up was. Reading the Apache documentation was helpful for most of my issues, but it still left me with a couple of questions. I hope the following contributes to your understanding of Apache as opposed to proving to just be more noise.
A note on Apache's config structure
When apache boots up it first looks to your apache.conf file. For our purposes here, it's worth mentioning that this file tells the system to include configuration in httpd.conf, posts.conf, and all of your vhost definition files in sites-enabled. In other words, you could put all of your configuration in apache.conf if you wanted one massive configuration file, but apache has organized the configuration into separate files to be included as to make the configuration less cumbersome for humans.
In order to accomplish our goal we have the following steps to carry out.
Enable the SSL mod in Apache using the a2enmod program
sudo a2enmod ssl
Tell Apache to listen to specific ports by using the "Listen" Directive
Default ports are 80 and 443 for SSL traffic. We can tell Apache to monitor these ports for activity using the following lines in the ports.conf file (or any other file imported by apache.conf. You may see these Directives listed in other places):
Listen 80 Listen 443
Use the "NameVirtualHost" Directive and enable the "default servers"
Check out Apache's sites-available directory. For me that's located at /etc/apache2/sites-avalailable/. In that directory you will find files 'default' and 'default-ssl'. These are our first Virtual Hosts we will enable and they will become the 'default hosts'. This is a requirement of Apache and is mentioned in the Apache documentation on Virtual Hosts (http://httpd.apache.org/docs/current/vhosts/). All of the settings in the default host definitions will get passed down to all other Virtual Host definitions using the same IP address / Port # combination. In these files you will find two lines to take note of for the future:
NameVirtualHost 127.0.1.1:80 <VirtualHost 127.0.1.1:80>
The "NameVirtualHost" Directive tells Apache to allow "Virtual Name Hosts" for a specific IP address on a specific port. A "Virtual Name Host" simply means a VirtualHost definition that is called when a specific URL name is asked for. For now, note the VirtualHost entry in this file that has a corresponding IP address / port # combination with the NameVirtualHost Directive. If your VirtualHost entries do not have this match with a "NameVirtualHost" directive, they will not work.
!! Beware of the wildcard for IP address, having a wildcard in the "NameVirtualHost" directive's IP address and a specific IP address in your VirtualHost definition will not work !!
By using the a2ensite command you will make a symbolic link to the file in the sites-enabled directory which gets included in the apache.conf file.
sudo a2ensite default sudo a2ensite default-ssl
Create VirtualHost definitions and enable them
In this case, if a request for foo.com comes to IP address 127.0.1.1 through port 80, Apache will look for a VirtualHost definition that is assigned to 127.0.1.1:80 and has ServerAlias defined as foo.com. Here is a potential match:
<VirtualHost 127.0.1.1:80> ServerName foo.com ServerAlias *.foo.com foo.com DocumentRoot /home/user/workspace/foo.com/ </VirtualHost>
We could then include this text in the Apache.conf file or just make a seperate foo.com file placed in sites-available and use a2ensite for the definition like we did for the default and default-ssl definitions.
Configure your /etc/hosts file
Now you need to tell your system that specific domains go to specific IP addresses. If you are using linux then you can do this by editing your /etc/hosts file. In the case of foo.com that Apache is configured to listen for on IP address 127.0.1.1, you would add the following line to your /etc/hosts file:
127.0.1.1 foo.com
Restart Apache
Now you can restart apache to see the effects of you changes.
Something like:
apache2ctl restart
Or:
/etc/init.d/apache2 restart
Troubleshooting: Look at the Apache host config
The apache 2.2 documentation says you can run /usr/local/apache2/bin/httpd -S to check your config but I found apache2ctl -S worked for me. When I first ran this command I had a bunch of VirtualHost files all unorganized and not matching the NameVirtualHost directives very well. When you run this command the result should be fairly simple to read. Something similar to this:
127.0.1.1:80 is a NameVirtualHost
default server localhost (/etc/apache2/sites-enabled/000-default:4)
port 80 namevhost localhost (/etc/apache2/sites-enabled/000-default:4)
port 80 namevhost foo.com (/etc/apache2/sites-enabled/foo.com:13)
127.0.1.1:443 is a NameVirtualHost
default server localhost (/etc/apache2/sites-enabled/default-ssl:5)
port 443 namevhost localhost (/etc/apache2/sites-enabled/default-ssl:5)
port 443 namevhost store.foo.com (/etc/apache2/sites-enabled/store.foo.com:13)
Notes on the SSL configuration
Given the example above, I would have a VirtualHost entry something like this:
<VirtualHost 127.0.1.1:433> ServerName store.foo.com ServerAlias store.foo.com DocumentRoot /home/user/workspace/foo.com/ </VirtualHost>
In the settings of your enabled default-ssl file, it defines SSLCertificateFile and SSLCertificateKeyFile directives. If I didn't want store.foo.com to use these bogus 'snakeoil' certificates and keys, I can override the default by including them in my VirtualHost definition:
<VirtualHost 127.0.1.1:433> ServerName store.foo.com ServerAlias store.foo.com DocumentRoot /home/user/workspace/foo.com/ SSLCertificateFile /etc/ssl/certs/ssl-cert-REAL.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-REAL.key </VirtualHost>