70

I have a dedicated server with Apache, on which I've set up some VirtualHosts. I've set up one to handle the www domain as well as the non-www domain.

My VH .conf file for the www:

<VirtualHost *>
  DocumentRoot /var/www/site
  ServerName www.example.com
  <Directory "/var/www/site">
    allow from all
  </Directory>
</VirtualHost>

With this .htaccess:

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]

Is there a simple way to redirect the www to the non-www version? Currently I'm sending both versions to the same DocumentRoot and using .htaccess but I'm sure I must be able to do it in the VirtualHost file.

DisgruntledGoat
  • 2,569
  • 4
  • 26
  • 34
  • http://stackoverflow.com/questions/42500012/apache-rewritecond-not-working-if-then/42512986#42512986 – rajeev Feb 28 '17 at 15:45

4 Answers4

122

Turns out mod_rewrite rules are fine in the VirtualHosts file, apart from the RewriteBase rule. I ended up with this:

<VirtualHost *>
  ServerName www.example.com
  RewriteEngine on
  RewriteCond %{HTTP_HOST} ^www.example.com
  RewriteRule ^/(.*)$ http://example.com/$1 [L,R=301]
</VirtualHost>

EDIT: on the advice of joschi in the comments, I'm now using this simplified version using the Redirect directive from mod_alias:

<VirtualHost *>
  ServerName www.example.com
  Redirect 301 / http://example.com/
</VirtualHost>
DisgruntledGoat
  • 2,569
  • 4
  • 26
  • 34
  • 3
    You do not need mod_rewrite for this. Use mod_alias and its RedirectPermanent directive instead. – joschi Mar 09 '10 at 06:58
  • @joschi: What would be the advantage of that? Is it faster? – DisgruntledGoat Mar 09 '10 at 17:10
  • 12
    You don't need the full-blown rewrite engine with all its checks and possibilities to just redirect the client. It would be (marginally) faster since mod_alias is not near as complex as mod_rewrite and you'd only need one directive (RedirectPermanent) instead of two with mod_rewrite. And last but not least IMHO it's easier to understand what happens in the configuration when someone looks at it the first time. – joschi Mar 10 '10 at 06:00
  • 1
    For some strange reason Redirect 301 .. did not work for us. We had to use the RewriteRule option. – so_mv Apr 05 '12 at 17:42
  • NOTE: Using PHP 5.3.0 on WAMPSERVER 2.0 on Windows Server 2008 R2 Enterprise, not including `:80` after `VirtualHost *` causes *everything* to return "Forbidden"! – Cees Timmerman Sep 04 '14 at 12:33
  • works fine (the second one) but it doesn't change url. still shows www in the url ? – akshayb Sep 21 '14 at 11:15
  • It is safer to omit the '301' unless you **really** want a **permanent** redirect. The default is 302 Found, which would work better for a lot of people. See http://jacquesmattheij.com/301-redirects-a-dangerous-one-way-street – jtpereyda Jan 05 '17 at 22:32
4

Be very careful with 301 redirects because, by default, a browser that receives the 301 redirect will store it permanently - meaning you will give up control what that browser will see when it tries to access the domain www.example.com.

See for example this discussion http://getluky.net/2010/12/14/301-redirects-cannot-be-undon/

So either make sure it does not get cached, or use mod_proxy (I recommend the mod_proxy).

If you are fine with letting the user see the URL change on the browser address bar, use mod_rewrite:

<VirtualHost *>
 ServerName www.example.com
 RewriteEngine on
 RewriteCond %{HTTP_HOST} ^www.example.com
 RewriteRule ^/(.*)$ http://example.com/$1 [L,R=301,E=nocache:1]
## Set the response header if the "nocache" environment variable is set
## in the RewriteRule above.
 Header always set Cache-Control "no-store, no-cache, must-revalidate" env=nocache
## Set Expires too ...
 Header always set Expires "Thu, 01 Jan 1970 00:00:00 GMT" env=nocache
</VirtualHost>

If you want the "redirect" to be invisible to the user, use mod_proxy:

<VirtualHost *>
 ServerName www.example.com
 ProxyRequests Off
 <Proxy *>
 Order Deny,Allow
 Deny from all
 Allow from 203.0.113.67
 </Proxy>
 ProxyPass / http://example.com/
 ProxyPassReverse / http://example.com/
</VirtualHost>

It should be noted that mod_proxy, when badly configured, can harm your network.

Ladadadada
  • 25,847
  • 7
  • 57
  • 90
  • 6
    The point of a 301 is that it's a *permanent* redirect; if you want a non-permanent redirect, you should use 302 or 307 instead. – nickgrim Nov 26 '13 at 10:04
2

You can add ServerAlias example.com to the VirtualHost but the performance will differ from a redirect.

Edit

Since you want to redirect and you don't need advanced functionality, it seems like using Redirect should suffice for you. You would put the Redirect under a VirtualHost directive.

A client side solution would be to use a meta refresh tag.

Warner
  • 23,440
  • 2
  • 57
  • 69
  • Can you explain a bit further? How would I redirect `www.example.com` to `example.com` using this method? – DisgruntledGoat Mar 09 '10 at 21:31
  • In your primary vhost, you have entries for both `ServerName` and `ServerAlias`. One has example.com and the other www.example.com. Then, both dns entries will access the documents specified in the same vhost. – Warner Mar 09 '10 at 21:56
  • I want to do a *redirect* though, not just an alias. – DisgruntledGoat Mar 10 '10 at 18:17
  • Then joshchi's recommendation may be a good approach for you. Seems like hairs are being split at this point. – Warner Mar 10 '10 at 18:50
1

well, you could create one virtual host for the SERVERNAME www.example.com and have it redirect to another virtual host with the servername example.com

Devin Ceartas
  • 1,458
  • 9
  • 12