skip to Main Content

I’m hoping someone can help me, as for years I’ve always tried different approaches to redirecting and came across an interesting one on a project I’m working on.

I need HTTP to redirect to HTTPS
AND
I need non-www to redirect to www but only if //domain.com without any subdomains
AND
I need subdomain.domain.com to still work so do not redirect the subdomain, i’m using wildcard (*) in apache to handle any subdomain as these will be detected in php with $_SERVER and handled for specific tasks.

This is what I have so far however the non-www (//domain.com) ends up in an endless redirect

RewriteEngine On
Options -Indexes

RewriteCond %{HTTPS} off [OR]
# add www if not subdomain
RewriteCond %{HTTP_HOST} ^[^.]+.[^.]+$
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
   
RewriteCond %{HTTPS} off [OR]
# remove www if subdomain
RewriteCond %{HTTP_HOST} ^www.([^.]+.[^.]+.[^.]+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]

Apache virtual hosts two different files one for non SSL and one for SSL using lets encrypt

<VirtualHost *:80>
    DocumentRoot /var/www/html/www.domain.com
    ServerName domain.com
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot /var/www/html/www.domain.com
    ServerName www.domain.com
    ServerAlias *.domain.com
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =www.domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
    ServerName www.domain.com
    ServerAlias *.domain.com
    DocumentRoot /var/www/html/www.domain.com
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
</VirtualHost>

<VirtualHost *:443>
    ServerName domain.com
    DocumentRoot /var/www/html/www.domain.com
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/domain.com-0001/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.com-0001/privkey.pem
</VirtualHost>

All your help greatly appreciated!

2

Answers


  1. You don’t need to setup different rules for SSL in both www and other subdomains. All you need to do is have a rule to enforce HTTPS and another to enforce www in case you’re stumbling on the root domain:

    RewriteEngine On
    Options -Indexes
    
    # Makes sure HTTPS is used
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    
    # Adds www if not subdomain
    RewriteCond %{HTTP_HOST} ^example.com$
    RewriteRule ^ http://www.example.com%{REQUEST_URI} [L,R=301]
    

    Important to specify the root domain on RewriteCond for the www prepending, or at least use a less generic rule, such as ^[a-z0-9-_]+.[a-z0-9-_]+$.

    Login or Signup to reply.
  2. however the non-www (//domain.com) ends up in an endless redirect

    It is due to your first redirect rule which should be changed to:

    Options -Indexes
    RewriteEngine On
    
    # add www and https for main domain
    RewriteCond %{HTTP_HOST} !^www. [NC,OR]
    RewriteCond %{HTTPS} !on
    RewriteCond %{HTTP_HOST} ^(?:www.)?([^.]+.[^.]+)$ [NC]
    RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]
    
    # remove www if subdomain   
    RewriteCond %{HTTP_HOST} ^www. [NC,OR]
    RewriteCond %{HTTPS} !on
    RewriteCond %{HTTP_HOST} ^(?:www.)?(?!www.)([^.]+.[^.]+.[^.]+)$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
    

    Make sure to test it after clearing browser.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search