Skip to content

Instantly share code, notes, and snippets.

@webrgp
Created March 28, 2016 13:48
Show Gist options
  • Save webrgp/407ecd55a95ae9cfe616 to your computer and use it in GitHub Desktop.
Save webrgp/407ecd55a95ae9cfe616 to your computer and use it in GitHub Desktop.
# ------------------------------------------------------------
# Many techniques here are taken from html5 boilerplate
# https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess
# ------------------------------------------------------------
# ------------------------------------------------------------
# MANAGE UPDATES & SITE OFFLINE
# Update and uncomment these rules when we need to work on the site
# while serving an offline message to visitors. Add permitted IPs as needed.
# ------------------------------------------------------------
# RewriteEngine on
# RewriteCond %{REMOTE_HOST} !^76\.89\.128\.240
# RewriteCond %{REQUEST_URI} !^/assets/utility-pages/offline-page.html
# RewriteCond %{REQUEST_URI} !^/assets/utility-pages/offline-page-cp.html
# RewriteCond %{REQUEST_URI} !^/assets/utility-pages/offline-logo.png
# RewriteRule ^(.*)$ http://www.website.com/bsd-offline-page.html [R=302,L]
# ----------------------------------------------------------------------
# Password protect a specific environment to avoid search engines indexing
# your site and still only use one .htaccess file across multiple environments
# https://gist.github.com/1974022
#
# To generate a new htpassword run this line on the command line:
# htpasswd -nb username password
# ----------------------------------------------------------------------
# SetEnvIf Host local.craft staging
# AuthType Basic
# AuthName "Under Construction"
# AuthUserFile /protected/server/path/above/web/root/.htpasswd
# Require valid-user
# Order allow,deny
# Allow from all
# Deny from env=staging
# Satisfy any
# ----------------------------------------------------------------------
# Proper MIME type for all files
# ----------------------------------------------------------------------
# JAVASCRIPT
# Normalize to standard type (it's sniffed in IE anyways)
# tools.ietf.org/html/rfc4329#section-7.2
AddType application/javascript js jsonp
AddType application/json json
# Audio
AddType audio/ogg oga ogg
AddType audio/mp4 m4a f4a f4b
# Video
AddType video/ogg ogv
AddType video/mp4 mp4 m4v f4v f4p
AddType video/webm webm
AddType video/x-flv flv
# SVG
# Required for svg webfonts on iPad
# twitter.com/FontSquirrel/status/14855840545
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
# Webfonts
AddType application/vnd.ms-fontobject eot
AddType application/x-font-ttf ttf ttc
AddType font/opentype otf
AddType application/x-font-woff woff
# Assorted types
AddType image/x-icon ico
AddType image/webp webp
AddType text/cache-manifest appcache manifest
AddType text/x-component htc
AddType application/xml rss atom xml rdf
AddType application/x-chrome-extension crx
AddType application/x-opera-extension oex
AddType application/x-xpinstall xpi
AddType application/octet-stream safariextz
AddType application/x-web-app-manifest+json webapp
AddType text/x-vcard vcf
AddType application/x-shockwave-flash swf
# ----------------------------------------------------------------------
# Gzip compression
# ----------------------------------------------------------------------
<IfModule mod_deflate.c>
# Force deflate for mangled headers
# developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
<IfModule filter_module>
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject
FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf
FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype
FilterChain COMPRESS
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>
<IfModule !mod_filter.c>
# Legacy versions of Apache
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>
</IfModule>
# ----------------------------------------------------------------------
# Expires headers (for better cache control)
# ----------------------------------------------------------------------
# These are pretty far-future expires headers.
# They assume you control versioning with filename-based cache busting
# Additionally, consider that outdated proxies may miscache
# www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
# If you don't use filenames to version, lower the CSS and JS to something like
# "access plus 1 week" or so.
<IfModule mod_expires.c>
ExpiresActive on
# Perhaps better to whitelist expires rules? Perhaps.
ExpiresDefault "access plus 1 month"
# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Your document html
ExpiresByType text/html "access plus 0 seconds"
# Data
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# Feed
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# Favicon (cannot be renamed)
ExpiresByType image/x-icon "access plus 1 week"
# Media: images, video, audio
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# HTC files (css3pie)
ExpiresByType text/x-component "access plus 1 month"
# Webfonts
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# CSS and JavaScript
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
</IfModule>
# ----------------------------------------------------------------------
# ETag removal
# ----------------------------------------------------------------------
# FileETag None is not enough for every server.
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
# Since we're sending far-future expires, we don't need ETags for
# static content. developer.yahoo.com/performance/rules.html#etags
FileETag None
# ----------------------------------------------------------------------
# Start rewrite engine
# ----------------------------------------------------------------------
# Turning on the rewrite engine is necessary for the following rules and features.
# FollowSymLinks must be enabled for this to work.
#
# Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN
# If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where 'foo' is your directory.
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
</IfModule>
# ----------------------------------------------------------------------
# Remove "www." from beginning of URLs
# http://stackoverflow.com/questions/234723/generic-htaccess-redirect-www-to-non-www
# ----------------------------------------------------------------------
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
</IfModule>
# ----------------------------------------------------------------------
# Force "www." to beginning of URLs
# http://stackoverflow.com/questions/4916222/htaccess-how-to-force-www-in-a-generic-way
# ----------------------------------------------------------------------
# If using this, make sure the "Remove www. from beginning of URLS" block is commented out
# <IfModule mod_rewrite.c>
# RewriteCond %{HTTP_HOST} !^$
# RewriteCond %{HTTP_HOST} !^www\. [NC]
# RewriteCond %{HTTPS}s ^on(s)|
# RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# </IfModule>
# ----------------------------------------------------------------------
# Force https:// for the Control Panel
# Exclude our local and development environment if we don't have ssl setup there
# ----------------------------------------------------------------------
# RewriteCond %{HTTPS} !=on
# RewriteCond %{HTTP_HOST} !^local\.(.*)$ [NC]
# RewriteCond %{HTTP_HOST} !^dev\.(.*)$ [NC]
# RewriteRule ^(admin/.*)$ https://%{SERVER_NAME}/$1 [R=301,L]
# ------------------------------------------------------------
# Remove trailing slashes from the end of the URL
# This rule must come before removal of index.php from the URL
# ------------------------------------------------------------
# RewriteCond %{REQUEST_METHOD} !=POST
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.+)/$ /$1 [R=301,L]
# ----------------------------------------------------------------------
# Prevent 404 errors for non-existing redirected folders
# ----------------------------------------------------------------------
# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the same name does not exist
# e.g. /blog/hello : webmasterworld.com/apache/3808792.htm
Options -MultiViews
# ----------------------------------------------------------------------
# UTF-8 encoding
# ----------------------------------------------------------------------
# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8
# Force UTF-8 for a number of file formats
AddCharset utf-8 .css .js .xml .json .rss .atom
# ----------------------------------------------------------------------
# A little more security
# ----------------------------------------------------------------------
# Do we want to advertise the exact version number of Apache we're running?
# Probably not.
# This can only be enabled if used in httpd.conf - It will not work in .htaccess
# ServerTokens Prod
# "-Indexes" will have Apache block users from browsing folders without a default document
# Usually you should leave this activated, because you shouldn't allow everybody to surf through
# every folder on your server (which includes rather private places like CMS system folders).
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
# Block access to "hidden" directories or files whose names begin with a period. This
# includes directories used by version control systems such as Subversion or Git.
<IfModule mod_rewrite.c>
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>
# Block access to backup and source files
# These files may be left by some text/html editors and
# pose a great security danger, when anyone can access them
<FilesMatch "(\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$">
Order allow,deny
Deny from all
Satisfy All
</FilesMatch>
# Increase cookie security
<IfModule php5_module>
php_value session.cookie_httponly true
</IfModule>
# Hide .git and _svn folders so they cannot be accessed
# But you shouldn't upload them in the first place
<IfModule mod_rewrite.c>
RewriteRule ^(.*/)*_svn/ / [F,L]
RewriteRule ^(.*/)*\.git/ / [F,L]
</IfModule>
# ------------------------------------------------------------
# Relative 301 redirects
# When necessary use rewrite rules like this so that they work in all environments
# These rules must come before removal of index.php from the URL
#
# Make sure the following rules come before this one:
# RewriteEngine on
# RewriteBase /
#
# Test new rules as 302 redirects
# ------------------------------------------------------------
# RewriteRule ^old-url/?$ /new-url [R=301,L]
# ------------------------------------------------------------
# Remove index.php from the URL
# using "File and Directory Check" Method and a bit more
# http://bit.ly/avy6iZ , http://bit.ly/lDLTQv
# ------------------------------------------------------------
# Default htaccess rule from Craft with one line removed
# as we already turned 'RewriteEngine On' above.
<IfModule mod_rewrite.c>
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment