How to configure HTTPS on Apache 2

Introduction

Setting up several VirtualHost's on an Apache2 server is easy. Setting up several VirtualHost's on an Apache 2 server, some of them using SSL (HTTPS) is considerably less easy. The main problem is the documentation, not really easy to find, with examples of such configurations. Here, we will intend to give all the steps to get there, remaining at a minimal level of complexity. If you want more details, I suggest you have a look at this nice article by Artur Maj. This is where most of the inspiration comes from for the current article, together with real tests on a Debian Etch server. Thanks to his article, We will allow ourselves to skip the HTTPS, SSL and TLS definitions and prerequisites. We will consider that you have already installed SSL on your server installation, but haven't enabled it with VirtualHost's just yet.

Generating a key

To get things started, you will need a key. This key will be used by the VirtualHost you will define, only if you ask it to. To generate the key, create an ssl directory in your /etc/apache2/ directory (on a Debian Etch, that is) Then move inside that directory (cd ssl) and do the following:
mkdir crt mkdir key openssl req -new -x509 -days 365 -keyout key/vhost1.key -out crt/vhost1.crt -nodes -subj  '/O=VirtualHost Website Company name/OU=Virtual Host Website department/CN=www.virtualhostdomain.com'
This operation will create two files, crt/vhost1.crt and key/vhost1.key, that you will use in your VirtualHost definition to enable SSL encryption using that key.

Changing the VirtualHost config

Now move on to your Apache sites configuration. In most cases, you should have something like an /etc/apache2/sites-available/ and an /etc/apache2/sites-enabled directory. As sites-enabled should only contain links to sites-available, we are only interested in sites-available. So go there. Now you should have one default file there, as well as one file that defines the configuration of the VirtualHost you would like to setup to use HTTPS. Open the default config file. It should start with something like
NameVirtualHost *:80
or
NameVirtualHost *
Either way, change it to:
NameVirtualHost *:80 NameVirtualHost *:443
Now you have just told your webserver to accept both requests on port 443 and 80. *if* you restart your webserver at this point, you should get a warning message saying that no host is using the port 443. This is normal for me: I never really got around how to configure the whole thing correctly to avoid it throwing warnings at reload, but it is definitely not a big problem. Now let's proceed to the config of the VirtualHost itself. Open your VirtualHost config file. You should have something along the lines of:
<VirtualHost *> ServerAdmin webmaster@yourdomain.com DocumentRoot /var/www/vhost1 ServerName vhost1.yourdomain.com DirectoryIndex index.php ErrorLog /var/log/apache2/vhost1-error.log CustomLog /var/log/apache2/vhost1-access.log combined <Location /> Options Indexes FollowSymLinks AllowOverride All </Location> ... </VirtualHost>
Together with the new config, this should look like that:
<VirtualHost *:80> ServerAdmin webmaster@yourdomain.com DocumentRoot /var/www/vhost1 ServerName vhost1.yourdomain.com DirectoryIndex index.php ErrorLog /var/log/apache2/vhost1-error.log <Location /> RewriteEngine on RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R] </Location> </VirtualHost> <VirtualHost *:443> ServerAdmin webmaster@yourdomain.com DocumentRoot /var/www/vhost1 ServerName vhost1.yourdomain.com DirectoryIndex index.php ErrorLog /var/log/apache2/vhost1-error.log CustomLog /var/log/apache2/vhost1-access.log combined SSLEngine On SSLCertificateFile /etc/apache2/ssl/crt/vhost1.crt SSLCertificateKeyFile /etc/apache2/ssl/key/vhost1.key <Location /> SSLRequireSSL On SSLVerifyClient optional SSLVerifyDepth 1 SSLOptions +StdEnvVars +StrictRequire </Location> ... </VirtualHost>
Now if you restart your web server, you should be able to make it work straight away. Note that if you do that on a fresh server, you might receive a "Configtest failed" error message. This is most likely to be due to the Rewrite or SSL modules not being enabled. Just enable them:
sudo a2enmod rewrite sudo a2enmod ssl sudo /etc/init.d/apache2 restart
  2012-10-15 edit: as indicated by Gerard H. Pille in the comments to this article, Apache needs to be configured to answer on port 443 as well. This is generally a default setting in Debian/Ubuntu, but if you need to enable it, just locate the "Listen 80" in your Apache configuration directory and add a "Listen 443" on the next line. Restart Apache, and you should be done with it. 2016-03-18 edit: although this article is quite old, the main principles are still valid for Apache 2.2 and 2.4. If you need to generate a self-signed SSL certificate, we recommend this article which only diverts a little regarding the path where the certificates are stored.

Comments

Hi. It is very unlikely that you can enable https on a shared hosting if you don't have that option in your contract. This being said, their is generally a possibility to add the option to the cost of additional services.

I think it doesn't (you have to have at least different virtual public addresses). You *can* have several subdomains of the same domain, using a multiple subdomains SSL feature, but having SSL for multiple domains on the same machine (or same IP) is still a problem, as far as I am aware...
Now with all the cloud stuff and the virtualization of machines, it is kind of a little less problematic, but that is still kind of a technical headache (afaik)...

Hi,

I am using Apache Tomcat server version 5, i want to change HTTP connection to HTTPS connection. Can any one please suggest me how to do in clear.

Thanks in Advance..

Praveen.

Hi,

Currently i try to setup localhost with https function. I have apache in my pc and and openssl. I using Window Xp But, up till now i still unable to UP the https function. Wish you can help me. Thanks.

Sorry Hasanul, we don't support non-open technologies stacks (i.e. Windows) for a lot of reasons. You might want to have a look at the microsoft knowledge base for that (I hear they are doing a "big effort" of interoperability these days).
Good luck!

Hi

Im searching how to use https only in login page. This is because is a web that if not I can't use mysql cache. Do you know the apache rule?

Thanks

This looks strange:

SSLRequireSSL On
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars +StrictRequire

You open a location tag and then immediately close it, then some directives and then closing the location tag again - you do this with all location tags

Is this Apache syntax, or just a typo on your part?

I tried both as prescribed and with

SSLRequireSSL On
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars +StrictRequire

and no matter what i get:

SSL received a record that exceeded the maximum permissible length.

(Error code: ssl_error_rx_record_too_long)

Any tips on what this could be?

Probably just a typo on my part (for the opening and closing location tags), but I probably left it at the time to remember where to put it (at which level) later if needed. Thanks for pointing it out.

Hmmm ... I must've bungled it up

I re-instated the weird tags and now I get what I expected. A warning that the certificate cannot be trusted and access after that

Gotta say it out loud: APACHE IS WEIRD!

a convention like: open tag = - closing tag = - openandclosetag = should not be messed with :)

You shouldn't confuse the Apache configuration file syntax with XML. It is not XML.
In Apache config files,

actually means "the start of the section regarding location '/' " (the document root at the top of the pages hierarchy).
Just like
means "the start of the section regarding location '/abc' ". And the end of any Location section is indicated by a

It's not weird; it's only that it was invented before XML became popular.

I adding some juducious quoting would have helped making this understandable. The missing tags above are ', and '.

Hmmm - my first post is stripped of location tags which makes it hard to understand

All the directive blocks in my first post is enclosed like this:

&lt;location /&gt;

.... directives ....

&lt;/location&gt;

Good job with me.

Just two small issues: I've tested it today on ubuntu desktop 10.04 and I get just a pair of easy-to-solve errors. Both in this step:
openssl req -new -x509 -days 365 -keyout key/vhost1.key -out crt/vhost1.crt -nodes -subj ‘/O=VirtualHost Website Company name/OU=Virtual Host Website department/CN=www.virtualhostdomain.com

The first is "unknown option Website" and I fixed it by changing in this way:
/etc/apache2/ssl$ sudo openssl req -new -x509 -days 365 -keyout key/vhost1.key -out crt/vhost1.crt -nodes -subj ‘/O=VirtualH/OU=Virtual/CN=www.virtualhostdomain.com

Now I get another error "Subject does not start with '/'." and I fixed it by doing this way:
sudo openssl req -new -x509 -days 365 -keyout key/vhost1.key -out crt/vhost1.crt -nodes -subj /O=VirtualH/OU=Virtual/CN=127.0.0.1’

[...] I am currently looking for the way to set up apache to serve https requests, and I found this article which I intend to follow closely. Will log my progress here in the [...]

The problem with "Unknown option Webisite" is fixed by replacing the matched single quotes in the openssl command with ordinary single quotes. You probably cut and pasted the code into your console, right? Wordpress blogs automatically translate single and double quotes into matched quotes, and it can screw up code.

Great tutorial Yannick! I've generated my keys, but I'm going to have to go to bed before trying the rest tomorrow.

Interesting question. The Listen directive is usually enabled on port 443 on Debian/Ubuntu installations (/etc/apache2/ports.conf), so the process to enable it is not really necessary on that architecture, but yes, technically, there needs to exist a "Listen 443" somewhere so that Apache can tell inetd that it will answer to port 443 (generally it also already answers to port 80). Thanks.

[&#8230;] and having a bit of trouble setting up my VirtualHost with SSL. I followed the instructions here but every time I try to restart apache, it tells me it cannot restart because of multiple [&#8230;]