mirror of
https://github.com/phanan/htaccess.git
synced 2018-11-08 13:39:40 +01:00
270 lines
9.7 KiB
Markdown
270 lines
9.7 KiB
Markdown
|
# .htaccess Snippets
|
||
|
A collection of useful .htaccess, all in one place. I decided to create this repo after getting so tired (and bored) with Googling everytime there's a need of forcing `www` for my new website.
|
||
|
|
||
|
**Disclaimer**: While dropping the snippet into an `.htaccess` file is most of the time sufficient, there are cases when certain modifications might be required. Use with your own risks.
|
||
|
|
||
|
## Table of Contents
|
||
|
- [Rewrite and Redirection](#rewrite-and-redirection)
|
||
|
- [Security](#security)
|
||
|
- [Performance](#performance)
|
||
|
- [Miscellaneous](#miscellaneous)
|
||
|
|
||
|
## Rewrite and Redirection
|
||
|
Note: It is assumed that you have `mod_rewrite` installed and enabled.
|
||
|
|
||
|
### Force www
|
||
|
``` apacheconf
|
||
|
RewriteEngine on
|
||
|
RewriteCond %{HTTP_HOST} ^example\.com [NC]
|
||
|
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301,NC]
|
||
|
```
|
||
|
|
||
|
### Force www in a Generic Way
|
||
|
``` apacheconf
|
||
|
RewriteCond %{HTTP_HOST} !^$
|
||
|
RewriteCond %{HTTP_HOST} !^www\. [NC]
|
||
|
RewriteCond %{HTTPS}s ^on(s)|
|
||
|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||
|
```
|
||
|
This works for _any_ domain. [Source](https://stackoverflow.com/questions/4916222/htaccess-how-to-force-www-in-a-generic-way)
|
||
|
|
||
|
### Force non-www
|
||
|
It's actually [recommended](http://no-www.org/) to remove `www` from your domain. Surprise surprise!
|
||
|
``` apacheconf
|
||
|
RewriteEngine on
|
||
|
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
|
||
|
RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
|
||
|
```
|
||
|
|
||
|
### Force HTTPS
|
||
|
``` apacheconf
|
||
|
RewriteEngine on
|
||
|
RewriteCond %{HTTPS} !on
|
||
|
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
|
||
|
```
|
||
|
|
||
|
### Force Trailing Slash
|
||
|
``` apacheconf
|
||
|
RewriteCond %{REQUEST_URI} /+[^\.]+$
|
||
|
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
|
||
|
```
|
||
|
|
||
|
### Redirect a Single Page
|
||
|
``` apacheconf
|
||
|
Redirect 301 /oldpage.html http://www.yoursite.com/newpage.html
|
||
|
Redirect 301 /oldpage2.html http://www.yoursite.com/folder/
|
||
|
```
|
||
|
[Source](http://css-tricks.com/snippets/htaccess/301-redirects/)
|
||
|
|
||
|
### Redirect an Entire Site
|
||
|
``` apacheconf
|
||
|
Redirect 301 / http://newsite.com/
|
||
|
```
|
||
|
This way does it with links intact. That is `www.oldsite.com/some/crazy/link.html` will become `www.newsite.com/some/crazy/link.html`. This is extremely helpful when you are just "moving" a site to a new domain. [Source](http://css-tricks.com/snippets/htaccess/301-redirects/)
|
||
|
|
||
|
## Security
|
||
|
### Deny All Access
|
||
|
``` apacheconf
|
||
|
Deny from All
|
||
|
```
|
||
|
|
||
|
But wait, this will lock you out from your content as well! Thus introducing...
|
||
|
|
||
|
### Deny All Access Except Yours
|
||
|
``` apacheconf
|
||
|
Order deny, allow
|
||
|
Deny from All
|
||
|
Allow from xxx.xxx.xxx.xxx
|
||
|
```
|
||
|
`xxx.xxx.xxx.xxx` is your IP. If you replace the last three digits with 0/12 for example, this will specify a range of IPs within the same network, thus saving you the trouble to list all allowed IPs separately. [Source](http://speckyboy.com/2013/01/08/useful-htaccess-snippets-and-hacks/)
|
||
|
|
||
|
Now of course there's a reversed version:
|
||
|
|
||
|
### Allow All Access Except Spammers'
|
||
|
``` apacheconf
|
||
|
Order deny, allow
|
||
|
Allow from All
|
||
|
Deny from xxx.xxx.xxx.xxx
|
||
|
Deny from xxx.xxx.xxx.xxy
|
||
|
```
|
||
|
|
||
|
### Deny Access to Hidden Files and Directories
|
||
|
Hidden files and directories (those whose names start with a dot `.`) should most, if not all, of the time be secured. For example: `.htaccess`, `.htpasswd`, `.git`, `.hg`...
|
||
|
``` apacheconf
|
||
|
RewriteCond %{SCRIPT_FILENAME} -d [OR]
|
||
|
RewriteCond %{SCRIPT_FILENAME} -f
|
||
|
RewriteRule "(^|/)\." - [F]
|
||
|
```
|
||
|
|
||
|
### Disable Directory Browsing
|
||
|
``` apacheconf
|
||
|
Options All -Indexes
|
||
|
```
|
||
|
|
||
|
### Disable Image Hotlinking
|
||
|
``` apacheconf
|
||
|
RewriteEngine on
|
||
|
RewriteCond %{HTTP_REFERER} !^$
|
||
|
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
|
||
|
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
|
||
|
```
|
||
|
|
||
|
### Password Protect a Directory
|
||
|
First you need to create a `.htpasswd` file somewhere in the system:
|
||
|
``` bash
|
||
|
htpasswd -c /home/fellowship/.htpasswd boromir
|
||
|
```
|
||
|
|
||
|
Then you can use it for authentication:
|
||
|
``` apacheconf
|
||
|
AuthType Basic
|
||
|
AuthName "One does not simply"
|
||
|
AuthUserFile /home/fellowship/.htpasswd
|
||
|
Require valid-user
|
||
|
```
|
||
|
|
||
|
## Performance
|
||
|
### Compress Text Files
|
||
|
``` apacheconf
|
||
|
<IfModule mod_deflate.c>
|
||
|
|
||
|
# Force compression for mangled headers.
|
||
|
# http://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>
|
||
|
|
||
|
# Compress all output labeled with one of the following MIME-types
|
||
|
# (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
|
||
|
# and can remove the `<IfModule mod_filter.c>` and `</IfModule>` lines
|
||
|
# as `AddOutputFilterByType` is still in the core directives).
|
||
|
<IfModule mod_filter.c>
|
||
|
AddOutputFilterByType DEFLATE application/atom+xml \
|
||
|
application/javascript \
|
||
|
application/json \
|
||
|
application/rss+xml \
|
||
|
application/vnd.ms-fontobject \
|
||
|
application/x-font-ttf \
|
||
|
application/x-web-app-manifest+json \
|
||
|
application/xhtml+xml \
|
||
|
application/xml \
|
||
|
font/opentype \
|
||
|
image/svg+xml \
|
||
|
image/x-icon \
|
||
|
text/css \
|
||
|
text/html \
|
||
|
text/plain \
|
||
|
text/x-component \
|
||
|
text/xml
|
||
|
</IfModule>
|
||
|
|
||
|
</IfModule>
|
||
|
```
|
||
|
[Source](https://h5bp.com)
|
||
|
|
||
|
|
||
|
### Set Expires Headers
|
||
|
_Expires headers_ tell the browser whether they should request a specific file from the server or just grab it from the cache. It is advisable to set static content's expires headers to something far in the future.
|
||
|
If you don't control versioning with filename-based cache busting, consider lowering the cache time for resources like CSS and JS to something like 1 week. [Source](http://h5bp.com)
|
||
|
``` apacheconf
|
||
|
<IfModule mod_expires.c>
|
||
|
ExpiresActive on
|
||
|
ExpiresDefault "access plus 1 month"
|
||
|
|
||
|
# CSS
|
||
|
ExpiresByType text/css "access plus 1 year"
|
||
|
|
||
|
# Data interchange
|
||
|
ExpiresByType application/json "access plus 0 seconds"
|
||
|
ExpiresByType application/xml "access plus 0 seconds"
|
||
|
ExpiresByType text/xml "access plus 0 seconds"
|
||
|
|
||
|
# Favicon (cannot be renamed!)
|
||
|
ExpiresByType image/x-icon "access plus 1 week"
|
||
|
|
||
|
# HTML components (HTCs)
|
||
|
ExpiresByType text/x-component "access plus 1 month"
|
||
|
|
||
|
# HTML
|
||
|
ExpiresByType text/html "access plus 0 seconds"
|
||
|
|
||
|
# JavaScript
|
||
|
ExpiresByType application/javascript "access plus 1 year"
|
||
|
|
||
|
# Manifest files
|
||
|
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
|
||
|
ExpiresByType text/cache-manifest "access plus 0 seconds"
|
||
|
|
||
|
# Media
|
||
|
ExpiresByType audio/ogg "access plus 1 month"
|
||
|
ExpiresByType image/gif "access plus 1 month"
|
||
|
ExpiresByType image/jpeg "access plus 1 month"
|
||
|
ExpiresByType image/png "access plus 1 month"
|
||
|
ExpiresByType video/mp4 "access plus 1 month"
|
||
|
ExpiresByType video/ogg "access plus 1 month"
|
||
|
ExpiresByType video/webm "access plus 1 month"
|
||
|
|
||
|
# Web feeds
|
||
|
ExpiresByType application/atom+xml "access plus 1 hour"
|
||
|
ExpiresByType application/rss+xml "access plus 1 hour"
|
||
|
|
||
|
# Web fonts
|
||
|
ExpiresByType application/font-woff "access plus 1 month"
|
||
|
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
|
||
|
ExpiresByType application/x-font-ttf "access plus 1 month"
|
||
|
ExpiresByType font/opentype "access plus 1 month"
|
||
|
ExpiresByType image/svg+xml "access plus 1 month"
|
||
|
</IfModule>
|
||
|
```
|
||
|
|
||
|
### Turn eTags Off
|
||
|
By removing the ETag header, you disable caches and browsers from being able to validate files, so they are forced to rely on your Cache-Control and Expires header. [Source](http://www.askapache.com/htaccess/apache-speed-etags.html)
|
||
|
``` apacheconf
|
||
|
<IfModule mod_headers.c>
|
||
|
Header unset ETag
|
||
|
</IfModule>
|
||
|
FileETag None
|
||
|
```
|
||
|
|
||
|
|
||
|
## Miscellaneous
|
||
|
|
||
|
### Set PHP Variables
|
||
|
``` apacheconf
|
||
|
php_value <key> <val>
|
||
|
|
||
|
# For example:
|
||
|
php_value upload_max_filesize 50M
|
||
|
php_value max_execution_time 240
|
||
|
```
|
||
|
|
||
|
### Custom Error Pages
|
||
|
``` apacheconf
|
||
|
ErrorDocument 400 /errors/breakingbad.html
|
||
|
ErrorDocument 401 /errors/notrespassing.html
|
||
|
ErrorDocument 403 /errors/mordor.html
|
||
|
ErrorDocument 404 /errors/halflife3.html
|
||
|
ErrorDocument 500 /errors/notabugitsafeature.html
|
||
|
```
|
||
|
|
||
|
### Force Downloading
|
||
|
Sometimes you want to force the browser to download some content instead of displaying it. The following snippet will help.
|
||
|
``` apacheconf
|
||
|
<Files *.md>
|
||
|
ForceType application/octet-stream
|
||
|
Header set Content-Disposition attachment
|
||
|
</Files>
|
||
|
```
|
||
|
|
||
|
### Allow Cross-Domain Fonts
|
||
|
CDN-served webfonts might not work in Firefox or IE due to [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). The following snippet from [HTML5Boilerplate](http://h5bp.com) should make it happen.
|
||
|
``` apacheconf
|
||
|
<IfModule mod_headers.c>
|
||
|
<FilesMatch "\.(eot|otf|ttc|ttf|woff)$">
|
||
|
Header set Access-Control-Allow-Origin "*"
|
||
|
</FilesMatch>
|
||
|
</IfModule>
|
||
|
```
|