0

I have this apache config:

<VirtualHost *:80>
DocumentRoot "/home/example/public_html/"
ServerName www.example.com

<Directory "/home/example/public_html/">
  allow from all

  RewriteEngine on
  RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
</Directory>
</VirtualHost>

The redirect never seems to fire and just serves files from http. I've tried all sorts of combinations, but nothing seems to work.

mod_rewrite is enabled (using LoadModule rewrite_module modules/mod_rewrite.so)

Can anyone help?

Noodles
  • 1,386
  • 3
  • 18
  • 29
  • 1
    I am a fan of RedirectMatch over mod_rewrite . So `RedirectMatch permanent ^(.*)$ https://www.example.org$1` Not sure what is in your config. – Zoredache Aug 14 '17 at 22:24
  • 4
    [Apache 2.4 documentation: When not to use mod_rewrite](http://httpd.apache.org/docs/2.4/rewrite/avoid.html#redirect). In this case you should _not_ even have a `DocumentRoot` defined. This is the absolute simplest use of the `mod_alias Redirect` directive, and the official documentation tells you _eaxactly_ how to do it. – Colt Aug 14 '17 at 22:26
  • 3
    And by the way, `allow from all` is Apache 2.2, not Apache 2.4. – Colt Aug 14 '17 at 22:31
  • If you do fix it, use `Redirect permanent "/" "https://www.example.com/" ` instead of what the documentation says (`Redirect "/" "https://www.example.com/" `). Otherwise you will throw status 302 instead of 301 – Colt Aug 14 '17 at 22:36
  • Thanks to you both, TIL about RedirectMatch (I thought there was only Redirect). I've modified the config to remove DocumentRoot and added RedirectMatch and it seems to be working as expected. – Noodles Aug 14 '17 at 22:36
  • 2
    Just use `Redirect`. If you want the whole site to be `https` there is no reason to add any complexity (possible mistake, something broken, etc.). The _only_ thing you really need beyond the example is `permanent` to make sure you throw status code 301 instead of the default 302. – Colt Aug 14 '17 at 22:36

2 Answers2

6

This is way overcomplicated. You only need two (or three) directives to redirect everything to HTTPS, e.g.

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com
    Redirect permanent "/" "https://www.example.com/"
</VirtualHost>

This will redirect both with and without www to the canonical HTTPS site.

Esa Jokinen
  • 46,944
  • 3
  • 83
  • 129
  • Will this redirect `http://example.com/somepage` to https variant as well, or only base url? – Joshua Burns Jul 24 '19 at 03:45
  • This will redirect every request beginning with the base URL, as explained in the documentation for [mod_alias `Redirect`](https://httpd.apache.org/docs/2.4/en/mod/mod_alias.html#redirect): "Then any request beginning with URL-path will return a redirect request to the client at the location of the target URL. Additional path information beyond the matched URL-path will be appended to the target URL." – Esa Jokinen Jul 24 '19 at 04:16
2

The other answer already gives the solution, I thought I'd add why your code might not work as intended.

mod_rewrite is enabled

However, mod_rewrite directives in a directory (or .htaccess) context are not inherited by default. (mod_rewrite behaves somewhat differently to other modules in this respect.)

So, if you had a .htaccess file in the /public_html directory that uses mod_rewrite (eg. a default WordPress installation perhaps) then this will completely override the mod_rewrite directives in the parent <Directory> container in the server config. So, your redirect will never happen.

However, if you moved the mod_rewrite directives out of the <Directory> container and directly into the <VirtualHost> container then this might work OK. mod_rewrite directives in a virtual host (or server config) context will execute before .htaccess. For example:

<VirtualHost *:80>
DocumentRoot "/home/example/public_html/"
ServerName www.example.com

RewriteEngine on
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

<Directory "/home/example/public_html/">
    Require all granted   
</Directory>
</VirtualHost>

Note that this is purely theoretical. You don't need mod_rewrite at all here, use Esa Jokinen's solution instead.

Note also that allow from all is Apache 2.2 syntax. This is deprecated on Apache 2.4 and should be replaced with the equivalent Require directive. See Apache docs - Upgrading to 2.4 from 2.2

MrWhite
  • 12,647
  • 4
  • 29
  • 41