Forcing SSL in Apache without hard-coding the hostname
I think that I have this sorted (thanks mainly to the question How to redirect non-www to www without hardcoding using .htaccess?), but I still don't entirely understand a couple of things.
I would like to force all non-SSL connections to my server to be routed to SSL. I have only one vhost (and that will reliably remain the case for the lifetime of the server), but I would like to avoid hard-coding the domain name, partly so that the httpd.conf
files for Staging and Production remain identical.
I know I can force requests to use SSL with a mod_rewrite
rule like
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
or
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
I have two relatively simple questions, though:
- Should I prefer one of those
RewriteCond
statements over the other for any reason? Presumably if I use the%{SERVER_PORT}
variable, any connections on, say, port 8000 would continue to be served in the clear? Is there some reason I should avoid using the%{HTTPS}
variable that I'm overlooking? - Will that
%{HTTP_HOST}
variable in theRewriteRule
statement be respected and automagically substitute in whatever theHost:
header was from the request? Is there some circumstance under which this might not work?
In case it makes a difference, we're running Apache 2 on RedHat with mod_ssl
and the site used Drupal 7.
Sorry for what is a relatively stupid question; Apache sysadmin is by no means a core part of my job, so I'm trying to muddle through as best I can. Thanks, all!
Solution 1:
I've always used something like the following:
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Because occasionally, I like to serve HTTP over ports other than 80. Well, I don't like to do it, but sometimes needs must, etc.
%{HTTPS}
will be true, for example, if SSL is being used over port 80.
I think I usually use
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
%{HTTP_HOST}
will always be whatever is set as the Host:
header by the client.
It occurs to me, however.. that there's another way to do this.
<VirtualHost *:80>
ServerName mysite.example.com
Redirect permanent / https://mysite.example.com/
</VirtualHost>
You'll notice there's no DocumentRoot in the above block. If you're redirecting everything, you don't need one.
If you only wanted to redirect a bit of your site to SSL, you could just do
Redirect permanent /secure https://mysite.example.com/secure
I think the Redirect option is more preferable for full site HTTPS forcing, because it's one less level of insanity (as provided so kindly by mod_rewrite).
It might even be faster, as there'd be one less module to load / run.