Creating Apache redirects

Apache HTTP Server provides multiple methods to redirect URLs. This article covers some approaches and examples for Apache 2.4

What is a redirect?

Apache can create a redirect that points from one vhost to another vhost on the server or to another external site. Common reasons for using this feature are to force HTTP traffic to https and to move domain names.

Although complex rewrite configurations are not officially supported by the Global Linux Rackspace team, we are providing this information as a reference for customers who may choose to implement it at their discretion.

When to use redirects

  • Moving your website to a new domain.
  • Enforcing HTTPS connections.
  • Redirecting www to non-www (or vice versa).
  • Restructuring your website URLs.
  • Handling old URLs after site migration.
  • Consolidating multiple domains into one.

Verify Apache version and module are enabled

$ sudo apache2 -v
# or on CentOS/RHEL
$ sudo httpd -v

# Check if modules are enabled (Ubuntu/Debian)
apache2ctl -M | grep -E 'alias|rewrite'

# Check on CentOS/RHEL
httpd -M | grep -E 'alias|rewrite'

Enable Module if needed

# Ubuntu/Debian
sudo a2enmod alias
sudo a2enmod rewrite

# CentOS/RHEL (usually enabled by default)
# Edit /etc/httpd/conf.modules.d/00-base.conf
# Ensure these lines are present and uncommented:
# LoadModule alias_module modules/mod_alias.so
# LoadModule rewrite_module modules/mod_rewrite.so

Understanding Redirect Types

|  Code   |       Type          |          Use Case                    |     SEO Impact
| **301** | Permanent Redirect  | Domain changes, permanent URL moves  | Passes ~90-99% of link equity
| **302** | Temporary Redirect  | Temporary maintenance, A/B testing   | Does not pass link equity
| **303** | See Other           | POST to GET redirect                 | Specialized use
| **307** | Temporary Redirect  | Maintains request method             | Modern alternative to 302
| **308** | Permanent Redirect  | Maintains request method             | Modern alternative to 301

Key Decision: Use 301 for permanent changes, 302/307 for temporary redirects.

Simple Redirect

The Redirect directive is the fastest and simplest method for straightforward redirects.

For understanding the basics of Regular Expression, please visit the Regular Expression Building Blocks Apache and Nginx article.

  • Locate your virtual host file or .htaccess
  • Add a simple Redirect.
Syntax:

Redirect [status] [URL-path] [destination-URL]

Example 

# Redirect old page to new page
    Redirect 301 /old-page.html https://example.com/new-page.html

# Redirect all pages under /old-directory/ to new location
    Redirect 301 /old-directory/ https://example.com/new-directory/

# Redirect everything to new domain
    Redirect 301 / https://new-domain.com/
    

Test Configuration

`<VirtualHost *:80>
        DocumentRoot /var/www/example.com/httpdocs
        ServerName example.com
        Redirect 301 / https://example.com/      <-----
        ServerAlias www.example.com
    </VirtualHost>

      <VirtualHost *:443>
         DocumentRoot /var/www/example.com/httpdocs
         ServerName example.com
         ServerAlias www.example.com
          SSLEngine on
          SSLCertificateFile /etc/pki/tls/certs/2017-example.com.crt
          SSLCACertificateFile /etc/pki/tls/certs/CABundle.crt
          SSLCertificateKeyFile /etc/pki/tls/private/2017-example.com.key
       </VirtualHost>`
# Test configuration syntax
  $ sudo apache2ctl configtest
  # or # 
  $ sudo httpd -t

# If OK, reload Apache
  $ sudo systemctl reload apache2
  # or # 
  $ sudo systemctl reload httpd

# Test with curl
  $ curl -I http://example.com/old-page.html

Pattern-Based Redirects

Use RedirectMatch for pattern matching with regular expressions.

Syntax:

RedirectMatch [status] [regex-pattern] [destination-URL]

Example 

# Redirect all .php files to .html equivalents
    RedirectMatch 301 ^/(.*)\.php$ https://example.com/$1.html

# Redirect /blog/ or /news/ to /articles/
    RedirectMatch 301 ^/(blog|news)/(.*)$ https://example.com/articles/$2
    
# Redirect all .htm files to .html
    RedirectMatch 301 ^/(.*)\.htm$ https://example.com/$1.html
    

Apply and Test

# Test configuration syntax
  $ sudo apache2ctl configtest
  # or # 
  $ sudo httpd -t

# If OK, reload Apache
  $ sudo systemctl reload apache2
  # or # 
  $ sudo systemctl reload httpd

# Test with curl
  $ curl -I http://example.com/page.php

Using mod_rewrite

When to Use mod_rewrite:

  • Multiple conditions required
  • Query string manipulation needed
  • Complex URL transformations
  • Conditional redirects based on user agent, referrer, etc.
    Syntax:
    
    RewriteRule [pattern] [substitution] [flags]
Common Flags:
R=301 - Redirect with 301 status
R=302 - Redirect with 302 status
L - Last rule (stop processing)
NC - Case-insensitive
QSA - Query String Append
Example: Force WWW Prefix
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
    
</VirtualHost>
Remove WWW Prefix
<VirtualHost *:80>
    ServerName www.example.com

    RewriteEngine On
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
    
</VirtualHost>
Force HTTPS
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
    
</VirtualHost>
Redirect Based on Query String
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    # If URL contains ?id=123, redirect to new URL
    RewriteCond %{QUERY_STRING} ^id=123$
    RewriteRule ^/product\.php$ /new-product-page.html? [R=301,L]
    
</VirtualHost>
Redirect Multiple Old URLs
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    # Redirect multiple old pages
    RewriteRule ^/about-us$ /about [R=301,L]
    RewriteRule ^/contact-us$ /contact [R=301,L]
    RewriteRule ^/services/web-design$ /services/design [R=301,L]
    
</VirtualHost>
Multiple Conditions
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    
    # Don't redirect if already HTTPS and www
    RewriteCond %{HTTPS} on
    RewriteCond %{HTTP_HOST} ^www\. [NC]
    RewriteRule ^ - [L]
    
    # Force HTTPS
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
    
    # Force WWW (after HTTPS is set)
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
    
</VirtualHost>
Conditional Redirects with If Directive
# Force WWW with If

<VirtualHost *:80>
    ServerName example.com
    
    <If "%{HTTP_HOST} != 'www.example.com'">
        Redirect 301 "/" "https://www.example.com/"
    </If>
    
</VirtualHost> 

# Redirect Based on User Agent

<VirtualHost *:80>
    ServerName example.com
    
    <If "%{HTTP_USER_AGENT} =~ /mobile|android/i">
        Redirect 302 "/" "https://m.example.com/"
    </If>
    
</VirtualHost>

# Block and Redirect Specific IPs

<VirtualHost *:80>
    ServerName example.com
    
    <If "%{REMOTE_ADDR} == '192.168.1.100'">
        Redirect 403 "/" "https://example.com/blocked.html"
    </If>
    
</VirtualHost>
Maintenance Mode Redirect
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    
    # Exclude maintenance page itself
    RewriteCond %{REQUEST_URI} !^/maintenance\.html$
    
    # Exclude images and CSS for maintenance page
    RewriteCond %{REQUEST_URI} !^/assets/
    
    # Redirect all other requests
    RewriteRule ^(.*)$ /maintenance.html [R=302,L]
    
</VirtualHost>
Redirect All Except Specific Pages
<VirtualHost *:80>
    ServerName example.com
    
    RewriteEngine On
    
    # Don't redirect these pages
    RewriteCond %{REQUEST_URI} !^/allowed-page\.html$
    RewriteCond %{REQUEST_URI} !^/another-allowed-page\.html$
    
    # Redirect everything else
    RewriteRule ^(.*)$ https://new-site.com/$1 [R=301,L]
    
</VirtualHost>

Note - You can use a third-party module as well to test your Redirect.