Windows/Apache Web Server

Enabling SSL


In 2010, the idea of "HTTPS everywhere" was born by the Electronic Frontier Foundation (EFF), in collaboration with the Tor Project. In 2014, Google announced that websites using encryption woud get a slightly higher rank in its search algorithms. In 2016, Google updated its Chrome browser to explicitly identify sites that do not use HTTPS as "Unsecure".

None of which bothered me much as I do not ask for information from my visitors that requires a secure connection and my websites do not send anything worth securing. I knew it was something I should do, but never got around to it. In October 2022, I finally decided I should install the SSL certificates and use HTTPS instead of plain HTTP.

My installation of Apache is slightly unusual as I use a version compiled for Windows from Apache Haus that has the mod_ssl module already configured. I also run multiple virtual hosts on the server that all need certificates.

I spent some time obtaining the certificates as I wanted to ensure I knew what I was doing. My thanks to MikeMcQ in the Certbot Community Forum for his patience and who set me straight on a couple of concepts that I did not understand properly.


I did some reading about SSL certificates and confused myself a little. There are different SSL Certificate Authorities. I chose Let's Encrypt which is free, but the certificates have to be renewed every 3 months. There are different types of certificate, Let's Encrypt issues standard Domain Validation (DV) certificates. A variety of Automated Certificate Management Environment (ACME) clients are available to obtain and manage the certificates. I chose the recommended Certbot.

There are different certificate formats, Let's Encrypt and Certbot use the PEM format. SSL works by using a public/private key combination and there are two encryption methods for producing them, RSA and ECDSA. Let's Encrypt can use either, but I chose RSA, but that can be changed at any time by obtaining new certificates.


I downloaded the latest release and ran the installer, which creates a number of folders for the program. There seems to be a lot of commands for Certbot, but they are not too difficult to understand. There is always the Community Forum if further help is needed.

I was originally using Certbot version 1.31.0 which was released on October 4, 2022, but keep the program updated and have used version 2.6.0 which was released on May 9, 2023, and version 2.9.0 from February 8, 2024. Updating was simply running the installer. The certificate files are not affected by the upgrade.

Obtaining the SSL Certificates

Cerbot's documentation specifically says that:

Certbot for Windows currently cannot install the certificate in Apache or Nginx for you. As of the most recent release, you will have to edit your web server application’s configuration to install the certificate yourself after Certbot has obtained it.

At the time, I didn't realize the full implications of that. Once the certificates have been downloaded, Apache needs its configuration files edited so it can find them.

Certbot is a command line program and Cmd must be run as an administrator for it to work.

There are several methods of obtaining the certificates and I tried several of them while I was learning the program.

Apache Service Stopped: --standalone Option

For this method the Apache service must be stopped as Certbot needs access to port 80. This is because using the --standalone option, Certbot needs access to port 80.

At the command prompt type:

certbot certonly --standalone

Certbot is interactive and will ask you to enter a space or comma delimited list of domains for it to get certificates for. These are downloaded together in fullchain.pem. Following the onscreen instructions, Certbot will download the files and put them in its directories. The files will be in the "live" directory which are symbolic links to the "archive" directory.

The Certbot directoriesr

The Certbot directory structure
The actual certificates are in the archive folder, but there are symlinks to the latest ones in the live folder,
this is where the Apache configuration files should point to.

Apache Service Running : --webroot Option

I thought there should be a method of getting the certificates without stopping the Apache service and there is! Using what the --standalone method showed me I used:

certbot certonly --webroot -w C:\Apache24\htdocs\brisray -d -d -w C:\Apache24\htdocs\hmsgambia -d -d -w C:\Apache24\htdocs\icehouseoffroad -d -d

The command has to be typed on one line and the the -w swtiches are the webroot path and the -d switches are for the associated domain names. Notice I used the domain names with and without the www part in the URL.

If all goes well you will see something like this on the screen:

Successfully received certificate.
Certificate is saved at: C:\Certbot\live\\fullchain.pem
Key is saved at:         C:\Certbot\live\\privkey.pem
This certificate expires on 2024-06-22.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Configuring Apache on Windows for SSL

Perhaps configuring Apache to use the certificates is the hardest part of the process.

It helped that I used the Apache Haus Apache installers because that is mostly set up for SSL already. The Certbot documentation "Where are my certificates?", says to point the server to Certbot's folders rather than copy fullchain.pem and privkey.pem to the Apache conf/ssl directory which I had been doing. In his writeup of the process, Matt Zaske copied what had to be done from a Linux installation which can change Apache's configuration files.

I opened Apache's httpd-ssl.conf for editing and in the Server Certificate section added the line:

SSLCertificateFile "full-absolute-path-to-Certbot/live/fullchain.pem"

I then commented out or deleted the other directives in the section

In the Server Private Key: section add the line:

SSLCertificateKeyFile "full-absolute-path-to-Certbot/live/privkey.pem"

Then I commented out or deleted the other directives in that section and saved the file

I opened Apache's httpd-vhosts.conf for editing and in every virtual host entry, including the default, change the listening port to 443, the default port for HTTPS transfers, then added the lines:

SSLEngine on
SSLCertificateFile "full-absolute-path-to-Certbot/live/fullchain.pem"
SSLCertificateKeyFile "full-absolute-path-to-Certbot/live/privkey.pem"

Each virtual host needs a new block of directives to listen on port 80 and redirect it to the https version. So for each virtual host create this:

VirtualHost *:80
ServerAlias */ 
Redirect permanent /

Then saved the file and restarted the Apache service so the changes coul take affect.

The trailing slash on the redirects is needed to handle subdirectories. Without it, people get redirected to the homepage.

Updating the SSL Certificates

When Certbot is installed it creates a task in the Windows scheduler to look for new certificates and download any new ones twice a day. The command in Task Manager is:

Powershell.exe -NoProfile -WindowStyle Hidden -Command "certbot renew"

The command does not work! Whenever it runs, Windows pops up a notification asking what to do with the file:

Windows asking what to do with the Certbot task

Windows asking what to do with the Certbot task

One of the reasons it does not work is because the task is set to be run when an administrator is logged in. The problem is that my Server in the Cellar is rarely logged into as an admin. Besides, there's nothing in Certbot's script to restart the server once the new certificates have been obtained. This needs to be done to load the new certificates. I checked what was happening after renewing the certificates manually. Places like the Qualys SSL Labs SSL checker show the details of the old certificate until the server is restarted.

The SSL certificates have life of 90 days. Checking for new certficates twice a day seems overkill.

If the standalone switch was used when obtaining the certificates, then the domains have to be specfied when renewing them, if the --webroot method as used, then do not, and the server can remain running while they are renewed..

The certificates can be renewed without stopping the server but requires at least a graceful restart. A simple batch file or PowerShell script can do this by including httpd -k restart. The problem with that simple two line script is that the server is going to restart whether the renew command is successful or not as do Certbot's --pre-hook and --post-hook switches. The script could be altered to check the certificate install date but it's easier to use Certbot's --deploy-hook switch which only gets run if the renewal is successful.

The command to do that is:

certbot renew --deploy-hook "\Apache24\bin\httpd.exe -k restart"

Notice that unlike a normal command line, Certbot needs the httpd file extension to be specified. Without it, the command will not run.

I ran the above command, but as I had only just renewed the certificates anyway, Certbot returned:

The following certificates are not due for renewal yet:
C:\Certbot\live\\fullchain.pem expires on 2024-06-23 (skipped)
No renewals were attempted.
No hooks were run.

To ensure the command worked, I forced the renewal using:

certbot renew --deploy-hook "\Apache24\bin\httpd.exe -k restart" --force-renewal

This time, Certbot returned:

Congratulations, all renewals succeeded:
C:\Certbot\live\\fullchain.pem (success)

There was no mention of the --deploy-hook command being run, but I checked the server status and it had been.

The certificates can be renewed within 30 days of their expiration, but they can be checked fairly often, Certbot's predefined task is twice a day. When I created my own task, using certbot renew --deploy-hook "\Apache24\bin\httpd.exe -k restart", I made it just once a week.

Open Port 443

Port 443 is the default port for secure HTTPS transfers and it should be open on your router port forwarding section of its control panel and it should point to the IP address of your web server.

Port 443 open on the router

Port 443 open on the router

Testing the Configuration

It is difficult to tell whether HTTPS is working properly when sitting at the server, but there are a lot of websites that can check your site and its certificates for you. Just search for "ssl checker". If everything is configured properly then you should see something like this:

Qualys SSL Labs

My result from Qualys SSL Labs

Ionos SSL Certificate Checker

My result from Ionos SSL Certificate Checker

HTTP to HTTPS Without a Certificate

3 out of 4 isn't bad

One of my sites is a little weird in the way it was set up years ago. I've got the domain name and a friend of mine registered which points to the server. Because I don't own that domain name I cannot get a SSL certificate for it. Because the https handshaking occurs before any files are exchanged, I cannot redirect to Redirect permanent / works for the http version of but there's no way it will work for the https version which browsers report as "This site can’t be reached".

Unsecured Content

The website checker Detectify once offered free checks for personal, non-commercial sites. I took advantage of that and was grandfathered in when they no longer offered it. Shortly after I added the SSL certificate they did a scan of the site and something new turned up in the report they make. Three of my pages came up with the warning that there were files being served as Mixed Content (HTTPS vs HTTP). Looking at the report it said that the three pages were displaying HTTP content through the HTTPS connection. What was happening?

Mixed Content (HTTPS vs HTTP) warning from Detectify

Mixed Content (HTTPS vs HTTP) warning from Detectify

Chrome, my usual browser had the usual secured padlock, so I tried the site Edge, Firefox, and Opera. The browser that showed any sign that something was amiss was Firefox and that showed a small warning triangle by the padlock.

Firefox padlocks: secure and with a warning

Firefox padlocks: secure and with a warning

Why was this HTTP content still displaying and why didn't the browsers seem to treat it very seriously?

I opened the developer section of the browsers by pressing F12, and they all seemed to say the same thing:

Mixed Content: The page was loaded over HTTPS, but requested an insecure element. This request was automatically upgraded to HTTPS, For more information...

I took a look the pages and sure enough there were HTTP links in them. The browsers had automatically changed those to HTTPS requests and downloaded the content. They were only images, but would they have issued a stronger warning or not download the content at all if a HTTPS connection was not available or if the link was to a different file type?

As there were no warnings given by most browsers, I looked around to see if there was some sort of online checker. There are sites that will check individual pages for HTPP vs HTPPS content, but there are others that will attempt to crawl an entire site. Two of the best I have found are JitBit SSL Check and Missing Padlock - SSL Checker. HTTPS Checker has a free downloadable checker. It works very well but the free edition is limited to 500 pages, this is OK for my sites.

These tools are very useful for finding mixed content, and especially useful for finding pages that now have content completely blocked by my sites' Content Security Policy (CSP) rules. Some pages that were flagged by these tools was found to be missing content. The browser developer tools gave the following error:

Mixed Content: The page was loaded over HTTPS, but requested an insecure plugin resource. This request has been blocked; the content must be served over HTTPS.

Needless to say, the pages hghlighted by Detectify and the other tools are being checked and the links upgraded.

Google Search Console

My sites use Google Search Console and I got a shock when I visited the statistics pages a little while after installing the SSL Certificates - both the Google search impressions and traffic being sent from them had dropped to next to zero!

The statistics in Google Search Console dropped to next to zero after installing the SSL Certificates

The statistics in Google Search Console dropped to next to zero after installing the SSL Certificates

What was happening?

It happened because of the way I originally added the sites, I used the domain name starting with HTTP; after adding the SSL Certifcates the sites now use HTTPS and are not being recorded by the Console.

What do do about it?

A new property has to be created. Do this by clicking on the dropdown in the top left of the Google Search Console page and choose "Add property" from the dropdown.

The Google Search Console 'Add property' dropdown

The Google Search Console "Add property" dropdown

Recently Google Search Console added a choice of what happens next. You can add a URL prefix, for example HTTPS, or you can register the entire domain. As I do not use subdomains, I opted to register the entire domain for each of my sites. My choice just requires the main domain name without HTTP or HTTPS. In order to do this you must have access to the DNS records for the sites because those need to be edited.

The Google Search Console property types

The Google Search Console property types

The Google Search Console will then give you a verification code that needs to be pasted into the DNS TXT record for the domain. There may be problems doing this as explained in Multiple TXT fields for same subdomain. Some registrars will allow separate entries with each entry enclosed in quotes, others will allow each entry on new lines, others need a new text record.

I found that for my DNS records that I needed to created a TXT record rather than trying to edit an existing one...

Adding a TXT entry to a DNS record

Adding a TXT entry to a DNS record

Once the entry has been made, Google Search Console will then verify that it has been done properly. One nice thing is that the sitemap used by them will be copied to the new property. The bad news is that the statistics will start afresh for the new property and will take a while to populate properly.

Google Search Console domain ownership verification

Google Search Console domain ownership verification

If there is an error verifying the domain, one of the other methods must be used as discussed above.

Sources and Resources

Apache Haus
Certbot Community Forum
Certbot Documentation
Certbot Latest Releases
Certbot on Windows: Automation is Possible - Matt Zaske's experience with Certbot with Apache on Windows
Electronic Frontier Foundation
HTTPS Checker - Checks a HTTPS site for insecure content. The online checker is not free but the downloadable one is
Ionos SSL Certificate Checker - checks that the certificates are installed properly
JitBit SSL Check - Checks a HTTPS site for insecure content
Let's Encrypt
Missing Padlock SSL Checker - Checks a HTTPS site for insecure content
Multiple TXT fields for same subdomain (Stack Exchange / Server Fault) - Adding TXT records to the DNS records
Qualys SSL Server Test - checks that the certificates are installed properly
SSL Certificate Formats (Tutorials Teacher)
Tor Project