Windows/Apache Web Server

Enabling SSL

Introduction

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, first from from Apache Haus and when that was discontinued in 2023, from Apache Lounge, both have 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 am not very knowledgeable about the technical aaspects of SSL certificates or encryption, so I do not go into the details of those much. This page was written to show what works on my Apache on Windows installation. Including how I install the certificates, how I check they are installed properly and problems I had installing them.


SSL/TLS Certificate Authorities

When you ask a Certificate Authority (CA) for an SSL/TLS certificate it verifies you own the domain you are getting the certificate for and sends you a digitally signed encrypted certifcate that you can use on your site.

Although called SSL (Secure Socket Layer) certificates they have not used that technique starting since 1999 when TLS (Transport Layer Security) was introduced. The SSL method was subject to several attacks such as RC4 Decryption in 2005, BEAST in 2011, CRIME in 2012, POODLE in 2014, and Logjam in 2015. The last SSL protocol was version 3 which was depricated in 2015. The latest certificates (in 2026) use TLS 1.3. All versions of SSL and anything before TLS 1.2, introduced in 2008, are now depricated

Some certificate checkers such as the one at Qualys SSL Labs will test for, or otherwise determine, which attacks your server is vulnerable to.

Qualys SSL Labs vulnerability checker

Qualys SSL Labs vulnerability checker
This site tested on March 23, 2026

They are still called SSL certicates because SSL was introduced in 1994, and TLS started to be used in 1999. SSL was depricated in 2015, so both methods were used for 16 years so it became standard to use the term SSL.

SSL Dragon has a nice history of SSL and TLS. Wikipedia has a list of which vulnerabilities various browsers were subject to.

There are around 100 SSLs/TLS CAs around, but just five provide the certificates for over 99% of HTTPS sites - Let's Encrypt, GlobalSign, Sectigo, GoDaddy, and DigiCert. Of those, Let's Encrypt manages over 60% of the certificates issued.

Some of the lists at the Common CA Database do not appear to include Let's Encrypt. This is because they sometimes list the Internet Security Research Group or ISRG who run it.


Certificate Types

The more reading I do, the more confused I get! Luckily, other people have written articles giving more details than I can give. What I do know is what works on my server which is currently running Apache 2.4.66 on Windows 11.

SSL/TLS certificates ensure that information between the user and a site is encrypted. But, can you be sure that the site belongs to who you think it does? A 2021 report by the Anti-Phishing Working Group (APWG) found that over 80% of phishing sites had SSL certficates.

Domain Validation (DV) Certificates

These are the cheapest, sometime free, certificates. To get them all you have to do is prove you have access to the site, for example by allowing a file to be uploaded to a site's root or better still, by adding a text record to your DNS CNAMEs. Some ACME (Automated Certificate Management Environment) clients can also respond to the validation request. The whole process can be automated and completed in minutes.

Organization Validation (OV) Certificates

These certificates have the same validation as DV certificates but also validates that the company or other entity associated with the site actually exists. Validation usually takes around three days to complete.

Extended Validation (EV) Certificates

These undergo the same validation as OV certificates but with extra steps used to validate the entity that requested them. Validation usually takes around five days to complete.

There are other types of certificates available, usualy as a variation of the DV, OV and EV certifciates. These could include Single Domain, as its name implies,used to secure a single domain. Multi-Domain (MD) or Subject Alternative Names (SAN) certificates these use a single certificate to secures multiple domains or subdomains, whether they share the same root domain. Wildcard certificates are used to secure a main domain and an unlimited number of subdomains under that main domain

Let's Encrypt supports DV certifciates only, not OV or EV ones. Let's Encrypt supports Single Domain, MD, SAN and Wildcard certificates. Let's Encrypt can issue either a single certificate for each domain or separate ones.


Certificate Formats, Encoding, and Encryption

Format and Encoding

Reading through just a couple of sites it's easy to confuse yourself; CER, CSR, CTR, DER, KEY, P7B, PEM, PFX, and other files are all mentioned. Luckily there are articles such as SSL Certificate Formats and SSL Certificate Formats Explained around that help me understand what they are.

It's nice to know that a CSR file is a Certificate Signing Request that is sent to the CA to request a certificate, but all I really need to know is which certificate files wook on my Apache on Windows setup. PEM (Privacy-enhanced Electronic Mail) formatted certificates work.

There may be two or more PEM files that you receive. The files called chain or full-chain contain the certificates for not just the site but go all the way back to the root CA. So my chain.pem file contain those for my site, Let's Encrypt and ISRG who own Let's Encrypt and are their CA. Key.pem holds the keys for my certificate.

These files must not go with the public site files. Instead they go outside of those folders and are pointed to in the Apache configuration files.

Encryption

The public keys for the certificate need to be encrypted. There are two methods of doing this, and both use mathematical formula. RSA which comes from the names of it's 1977 creators - Ron Rivest, Adi Shamir, and Leonard Adleman. The other is ECC (Elliptic Curve Cryptography). The formula was developed independently by Neil Koblitz and Victor Miller 1n 1985.

Neither have been proved to be broken but there are differences between thm. ECC can provide the same level of security with a smaller size. This in turn makes it faster, which decreases page loading times. I first used RSA encrytion but now use ECC.

Other sites have articles comparing RSA and ECC encryption methods such as ECC Vs RSA Difference, ECDSA vs RSA: Everything You Need to Know, and What are the differences between RSA, DSA, and ECC encryption algorithms?


Domain Validation and Challenges

In order to get an SSL Certifcate you must be able to prove to the CA that you have control of the domain you are getting the certificate for. This is done through domain validation or challenge.

How this is done depends on the capabilities of your ACME. The methods used are email, HTTP and DNS.

In an email address challenge the email address usually comes from the address used in your DNS records or the server configuration files. The ACME may need to write the email address itself to a text record in the domain's CNAME records.

For a HTTP-01 challenge, the ACME creates a folder named .well-known/acme-challenge in the root of the domain folder. In this folder it creates a token that the CA recognises and validates against. As it's name implies, Port 80 must be open for this to work and the challenge cannot be redirected to Port 443.

A problem for me is that all calls to Port 80 are redirected to Port 443 so this meant that the Apache server service had to be stopped for an HTTP-01 challenge to work.

A DNS-01 challenge means creating a text record in the CNAME records of the domain you want a SSL Certificate for. In order to do this, the ACME client must have access to the API key provided by your DNS provider and not all provide the keys.

DNSExit API Key

DNSExit API Key

I use DNSExit as my DNS provider and that does give you the API key. It can be found in "My Account" section when I sign into their website. The ACME creates a text TXT record in the CNAME records of the domain named _acme-challenge or something similar along with the token used by the CA.

DNSExit ACME TXT entry in the DNS record

DNSExit ACME TXT entry in the DNS record

Let's Encrypt has a page that describes the various challenges it uses and their best use.


ACME Clients

The Automatic Certificate Management Environment (ACME) protocol passes JSON-formatted messages over HTTPS and was introduced in May 2013, by the Internet Security Research Group (ISRG) for their Let's Encrypt service.

Let's Encrypt maintains a list of ACME Clients that are compatible with them.

I originally used Certbot version 1.31.0 which was released on October 4, 2022, and kept 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.

Certbot 2.9.0 ran well on Windows but in November 2023, it was announced that it will be the last version that would run on the OS. I continued to use that version until December 2025, but found that in January 2026, it stopped working.

The next ACME client I used was simple-acme which I used to get new SSL Certificates in March 2026.

It is very remiss of me, but I did not realize that Apache has its own ACME client already included in it. It requires the Apache modules mod_md and mod_watchdog to be enabled in the configuration files. Sites such as this one on Github.

While testing an ACME client it is best to use Let's Encrypt's staging environment at https://acme-staging-v02.api.letsencrypt.org/directory or you will risk reaching Let's Encrypt's rate limits.

Several ACME client's already have this URL in them and in Cerbot is invoked by using --test-cert or --dry-run and in simple-acme by using --test in the command line.

Both Certbot and simple-acme have a lot of documentation for their command line switches and plugins. Unfortunately, it all needs to be read in order to understand how to use them.


Certificate Lifetimes

Currently (March 2026) Let's Encrypt SSL certificates last 90 days before they expire. Renewing them can be done when they have a third of their total lifetime left. So for a 90 day certificate they can be renewed after 60 days.

In December 2025, Let's Encrypt announced that the lifetime of their certificates, as well as other CAs, will be reduced. The announcement says that the lifetime will be reduced to 64 days on February 10, 2027, and then further reduced to 45 days on February 16, 2028.


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
ServerName example.com
ServerAlias example.com */example.com 
Redirect permanent / https://example.com/
VirtualHost

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\brisray.com\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\brisray.com\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


TLS Encryption and Vulnerabilities

Secure Sockets Layer (SSL) is a misnomer as since 1999 the encryption protocol used is Transport Layer Security (TLS). In 2025, the only TLS encryption protocols recommended are version 1.2 (from August 2008) and 1.3 (from August 2018). If version 1.3 is not availablethe fallback is 1.2. Several sites can check whih version of TLS is used and any vulnerabilities associated with older versions. Among the sites are CDN77, Digicert, and Test TLS.

Information about a website's SSL Certificates and TLS versions can be found via a browser's development tools.

In Chrome, Edge, Firefox, and Opera open the Dveloper Tools by navigating to the web site and press the F12 key. In the page that opens navigate to the "Privacy and security" section. Information about the SSL Certificate and TLS version used will be displayed.

SSL Certificate and TLS version viewed in the Developer Tools of a browser

SSL Certificate and TLS version viewed in the Developer Tools of a browser

To enable only TLS versions 1.2 and 1.3 in the httpd-ssl.conf file you need the line:

SSLProtocol -all +TLSv1.3 +TLSv1.2

As my version of the mod_ssl module currently only supports TLS 1.2, the line in my httpd-ssl.conf file is:

SSLProtocol -all +TLSv1.2


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 ihor4x4.com and a friend of mine registered icehouseoffroad.com 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 https://icehouseroad.com to https://ihor4x4.com. Redirect permanent / https://ihor4x4.com works for the http version of icehouseoffroad.com 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

7 Different Types of SSL Certificates Explained (Sertigo)
ACME Client Implementations (Let's Encrypt)
Automatic Certificate Management Environment (Wikipedia)
Apache Lounge - a version of Apache web server compiled for Windows
Apache Module mod_md - This module manages common properties of domains for one or more virtual hosts. It supervises and renews TLS certificates via the ACME protocol
Apache Module mod_ssl - This module provides Apache with TLS support
Apache Module mod_watchdog - This module defines programmatic hooks for other modules to periodically run tasks such as mod_md
Apache SSL/TLS Strong Encryption: How-To
Challenge Types (Let's Encrypt)
CDN77 - TLS checker
Digicert - TLS checker
ECC Vs RSA Difference (Cheap SSL Web)
ECC vs RSA Comparison (SSL Insights)
ECDSA vs RSA (Inforsec Insights)
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
Let's Encrypt ACME Clients
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
simple-acme - A ACME for Windows for Let's Encrypt
SSL Certificate Formats (SSL Mentor)
SSL Certificate Formats (Tutorials Teacher)
SSL Certificate Formats Explained (Inventive)
Test TLS - TLS checker
The Complete History of SSL and TLS Versions (SSL Dragon)
Tor Project
Version history for TLS/SSL support in web browsers (Wikipedia)
What are the differences between RSA, DSA, and ECC encryption algorithms? (Sectigo)