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.
I have my website in a shared hosting server.
can i enable https in my domain (www.peipians.com) ?
plz help me!
Thanks in advance.
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.
Thanks for a great article!
Would you happen to know how this should work for multiple ssl virtual hosts (name based not IP based)?
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 :)
I meant
open <tag>
close </tag>
open and close <tag/>
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:
<location />
…. directives ….
</location>
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’
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.
Shouldn’t the “LISTEN 443” appear somewhere in your article?
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.
Very very good, all is right
Hi, I want to configure apache2 with https
I have running a virtual box ubuntu 14.04 64-bits machine that running over Windows 7,
how I can configure apache2 with https if I do not have a domain “ServerAdmin webmaster@yourdomain.com” because is locally,
by the way
this is for education purpose
“Open your VirtualHost config file …”
pl tell me the location of this file.
Thanks for everything !
You’re awesome.
Hello!
I try to use Apache 2.4.10 on Debian 8.3 as a reverse-proxy server for my Microsoft Remote Desktop Services (on 2012R2). And all seems to be ok, but I can’t to make an RDP connection wich is tunnelling in https session (between Apache & MSRDS )
And there is a problem in the Apache log:
“RDG_OUT_DATA /remoteDesktopGateway/ HTTP/1.1” 404 5633 “-” “MS-RDGateway/1.0”
“RPC_OUT_DATA /rpc/rpcproxy.dll?localhost:3388 HTTP/1.1” 401 506 “-” “MSRPC”
“RPC_IN_DATA /rpc/rpcproxy.dll?localhost:3388 HTTP/1.1” 400 0 “-” “MSRPC”
error] (70007)The timeout specified has expired: proxy: prefetch request body failed to x.x.x.x from x.x.x.x
May be you know is there any way (may be special module) to resolve such trouble or Apache doesn’t support the for Microsoft’s non-standard HTTP behavior still?
Any comments appreciated. Thanks.
This was the answer I was looking for for over an hour! Thanks! You have saved me from losing my mind!
My site was displaying when I typed in the address again suddenly it was giving me 403 errors. In fact I had been loading the https version up until then so I hadn’t been aware that the http version was causing errors.