How to Redirect an HTTPS Website From WWW to non-WWW (or the other way around)

I like to run my sites without a www. You’re looking at this site like that i.e.

Some traffic always arrives at which sometimes breaks things, especially with dynamic sites.

This problem can be solved using the Apache module mod_rewrite. But I’ve had problems with that and it’s an overcomplicated way to do things.

The problem is more easily solved using Apache’s Redirect directive supplied by mod_alias.

What we’re going to do is to:

  1. Generate an SSL certificate for both WWW and non-WWW hostnames.
  2. Create a new VirtualHost for the undesired hostname (www or non-www) that redirects the visitor.

Generate a multi-hostname SSL certificate

This is required because traffic arriving at the WWW hostname e.g. first has to complete the HTTPS interaction before it can receive the redirect response from Apache.

You can get a wildcard SSL from Let’s Encrypt but it’s more work than getting a multi-hostname certificate.

You can read my guide on doing that here or use the following command (for and hostnames):

# certbot certonly --expand -d -d

You can now use this certificate and key in the WWW and non-WWW VirtualHost files.

Step 2 - Preparation

First, make sure that the mod_alias module is enabled and reload Apache:

# a2enmod alias
# systemctl reload apache2

Next, remove the undesired hostname (usually it’s a ServerAlias) from the existing VirtualHost file. In the following I want to redirect all traffic from to

This would be the relevant section of the VirtualHost file for this site:


    DocumentRoot /var/www/example-com


This becomes:


    DocumentRoot /var/www/example-com


Step 3 - Create the new, redirecting HTTPS WWW VirtaulHost

Create a new VirtualHost file for which will include the Redirect instruction and the certificate you just generated:


    DocumentRoot /var/www/example-com

    Redirect permanent /

    SSLCertificateFile /etc/letsencrypt/live/
    SSLCertificateKeyFile /etc/letsencrypt/live/
    Include /etc/letsencrypt/options-ssl-apache.conf


Reload Apache again to get the new config live.

Apache will now reply with an instruction to the requesting client that the requested URL/page/file etc has a new location with a 301 Permanent Move response.

Here’s the curl output for requesting

# curl -Ia
HTTP/1.1 301 Moved Permanently
Date: Mon, 31 Jul 2023 07:47:59 GMT
Server: Apache/2.4.57 (Debian)
Cache-Control: max-age=172800
Expires: Wed, 02 Aug 2023 07:47:59 GMT
Content-Type: text/html; charset=iso-8859-1

Everything after the hostname i.e. /guides/openssl-benchmark/index.html is preserved in the redirect response.