.htaccess directives fail to redirect www to non-www URLs

There’s nothing actually “wrong” with the config/directives you’ve posted, but it seems you don’t have a valid SSL cert that covers the www subdomain so you can’t redirect from https://www.example.com/ without the user accepting the invalid cert (this is the “error”) – which they should never do.

When requesting HTTPS, the browser establishes a secure connection with the server before any server-side scripts/redirects are even processed. If the security cert is invalid (as in this case), the user sees a warning in the browser and are unable to continue (unless the user jumps through hoops and accepts the invalid cert – which they should never do, as already mentioned). If there is no SSL cert at all then the server simply fails to connect.

So, there’s nothing actually “wrong” with the config you’ve posted. Providing you have a valid cert installed for the www subdomain then a request for http://www.example.com/ would be redirected to https://www.example.com/ by the mod_rewrite directive in the <VirtualHost *:80> container and then your directives in .htaccess would redirect from https://www.example.com/ to https://example.com/ (canonicalising the hostname). Yes, that’s two redirects, but there’s nothing wrong with two redirects here. And two redirects would actually be a requirement if implementing HSTS.

When testing multiple redirects (a redirect “chain”) with CURL then you need to use the -L flag, otherwise it does not follow the first redirect. For example:

curl -I -L http://www.example.com/

But in this case, without a valid cert installed for the www subdomain you get a warning back from CURL and further requests are stopped:

curl: (51) SSL: no alternative certificate subject name matches target host name ‘www.example.com’

However, you could optimise this a bit (if HSTS is not a concern) and redirect directly to the canonical hostname (ie. example.com) from the <VirtualHost *:80> container. You can also do this with a simple mod_alias Redirect. You don’t need mod_rewrite for this.

For example, instead of the following in <VirtualHost *:80>:

RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com (OR)
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} (END,NE,R=permanent)

you replace this with:

Redirect 301 / https://example.com/

There’s no need to check the requested host (ie. SERVER_NAME) anyway in the vHost container, since it can’t be anything other than the two hostnames you’ve defined with the ServerName and ServerAlias directives. (Assuming you have a default vHost:80 defined earlier that catches all “invalid” requests? Either way, they will all be redirected to your canonical hostname anyway.)

With this in place, any request for HTTP (ie. http://example.com/ or http://www.example.com/) will be redirected directly to https://example.com in a single redirect (the redirect in .htaccess is not required in this instance). This naturally circumvents the security cert issue for any request to HTTP only.

HOWEVER, any direct request the user makes to https://www.example.com/ will still be subject to the SSL cert warning until a valid cert is installed.

Aside: Due to rewriting all requests to the /public subdirectory (which contains index.php – the “front-controller” I assume), the additional /index.php in the document root is entirely superfluous.