1

I am using the following to force HTTPS on my main website.

### Force SSL
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

If you want to view the full htaccess file, I have placed it below:

<IfModule mod_rewrite.c>

    RewriteEngine On
    RewriteBase /

    ### Blacklist via Referrers

    RewriteCond %{HTTP_REFERER} removed\.net [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.net [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.sx [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.com [NC,OR]
    RewriteCond %{HTTP_REFERER} removed\.org [NC]
    RewriteRule ^(.*)$ - [F,L]

    ### Force SSL
    #RewriteCond %{HTTPS} !=on
    #RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    ### Canonicalize codeigniter URLs

    # If your default controller is something other than
    # "welcome" you should probably change this
    RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
    RewriteRule ^(.*)/index/?$ $1 [L,R=301]

    # Removes trailing slashes (prevents SEO duplicate content issues)
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)/$ $1 [L,R=301]

    # Enforce NO www
    RewriteCond %{HTTP_HOST} ^www [NC]
    RewriteRule ^(.*)$ https://removed.com/$1 [L,R=301]

    # Removes access to the system folder by users.
    # Additionally this will allow you to create a System.php controller,
    # previously this would not have been possible.
    # 'system' can be replaced if you have renamed your system folder.
    RewriteCond %{REQUEST_URI} ^system.*
    RewriteRule ^(.*)$ /index.php/$1 [L]

    # Checks to see if the user is attempting to access a valid file,
    # such as an image or css document, if this isn't true it sends the
    # request to index.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]

</IfModule>

<IfModule !mod_rewrite.c>

    # Without mod_rewrite, route 404's to the front controller
    ErrorDocument 404 /index.php

</IfModule>

I am struggling to figure how the redirect loop is happening.

Update

I did not make it clear that my web server (Apache) is only configured with one virtual host on port 80 that gets HTTP and HTTPS traffic directed to it by the load balancer. The load balancer handles the SSL connection.

12

Thanks to HBruijn's comment, I understood why I was getting the redirect loop.

The traffic from the ELB will always be HTTP as it handles the HTTPS traffic to the user but to the server it's HTTP, so my previous rule will result in a loop.

After some research I found that the load balancer forwards a few userful headers like X-Forwarded-Proto. This can be used to determine if the client is using HTTP or HTTPS like so:

### Force HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

I hope the above helps someone else when trying to force HTTPS behind Amazon Web Services Load balancer.

  • 2
    Worked for me. I'm using cloudflare if that's at all relevant. – Novocaine Dec 15 '15 at 9:28
  • Thank you! This was the only one that didn't cause a rewrite loop for me. – Tania Rascia Jan 27 '16 at 22:22
  • Same thing for me on CloudFlare using the given HTML5BP .htacess file enabling the rule to force https – Gruber Apr 27 '16 at 7:36
  • Oh my gosh. I can't believe that AWS was screwing me up. I couldn't figure out why every single example didn't work until I came across this answer. Thanks! – Josh Woodcock Dec 20 '16 at 5:21
5

Rather than doing so in a .htaccess file, simply set the SSL Redirect in the non-SSL VirtualHost entry of your Apache configuration:

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

<VirtualHost _default_:443>
   ServerName www.example.com
   DocumentRoot /usr/local/apache2/htdocs
   SSLEngine On
# etc...
</VirtualHost>

which is much more efficient.

Additionally: my pet peeve, quoted from from the manual on .htaccess files:

You should avoid using .htaccess files completely if you have access to httpd main server config file. Using .htaccess files slows down your Apache http server. Any directive that you can include in a .htaccess file is better set in a Directory block in the main Apache configuration file(s), as it will have the same effect with better performance.

  • Does the above solution mean all pages that are not SSL will redirect to the homepage? That is not ideal to be honest. We use htaccess files as it's easier for deployments to multiple environments as we swap htaccess files for each environment. – Abs Mar 23 '15 at 12:37
  • 2
    I included the link so you could Read The Fine Manual and you would have seen that http://www.example.com/something?else=true will be redirected to https://www.example.com/something?else=true and NOT to the homepage. - With regards to .htaccess all I'm going to say is: to many people use them and continue to copy them without actually understanding either their use-case or their impact. – HBruijn Mar 23 '15 at 12:54
  • The above solution won't work for us as we make use of the AWS ELB that routes SSL traffic to our Apache server that is only configured for port 80. It results in a redirect loop when I put the above statement in our config file as both HTTP and HTTPS hit the same virtual host. Any idea why our htaccess results in a redirect loop? – Abs Mar 23 '15 at 15:35
  • 2
    That would have been useful information to include in your original question! - So allow me to translate: you do SSL off-loading in your loadbalancer. Translation: all requests to your webserver are plain HTTP, regardless of the actual protocol used by the client. Then you want to run a check on the webserver to enforce a SSL connection that is never going to be seen there. – HBruijn Mar 23 '15 at 19:57
  • Aha! You're right, thank you for that explanation. As a result I have found a solution. – Abs Mar 26 '15 at 10:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.