HTAccess

From WebarchDocs
Jump to navigation Jump to search

Using .htaccess files

Following are some common uses for .htaccess files.

All the Webarchitects, Ecohost and Ecodissident shared hosting servers are running Apache and allow the use of .htaccess files to configure the server, however the Webarchitects and Ecodissident servers are set to only allow some directives for security reasons.

Custom Error Pages

Create static (or dynamic) error pages and then specify them in the .htaccess file for the site, for example:

ErrorDocument 404 /404.html

The Webarchitects shared hosting servers have the following error documents set, these can be overridden as above.

ErrorDocument 404 /wsh/404.shtml
ErrorDocument 401 /wsh/401.shtml
ErrorDocument 500 /wsh/500.shtml
ErrorDocument 403 /wsh/403.shtml

See the Apache documentation for more options and details.

Redirect based on hostname

If your hosting has several host names and you want to redirect people to different pages based on the hostname they used to access the site you can add something like this to you main .htaccess file for the site:

# Redirect requests for http://www.example.org/old-page.html 
# to http://www.example.org/new-page.html
<IfModule mod_rewrite.c>
  RewriteCond %{HTTP_HOST} ^www\.example\.org 
  RewriteRule ^/old-page.html$ new-page.html [R,L] 
<IfModule>

Or to redirect everything from one domain to another:

# Redirect requests for http://www.example.org/
# to http://www.example.net/
<IfModule mod_rewrite.c>
  RewriteCond %{HTTP_HOST} ^www\.example\.org
  RewriteRule ^/?(.*) https://www.example.net/$1 [R,L] 
<IfModule>

Allowed Overides

On the older Webarchitects and Ecodissident shared hosting servers we don't have AllowOveride All set, but have:

AllowOverride AuthConfig Indexes FileInfo Limit

On the newer servers running Apache 2.4 we have:

AllowOverride Options=Indexes,MultiViews,XBitHack,IncludesNOEXEC,ExecCGI AuthConfig FileInfo Limit Nonfatal=Override

Some web applications, like Drupal generate .htaccess files which contain directires which are not allowed and this results in servers errors, so Options lines and php settings need to be commented out, for more on this see the Drupal page.

Enforcing HTTPS

If your site has a valid SSL/TLS certificate you can use a .htaccess file to ensure that the site is only accessed via HTTPS with the following directives:

# Redirect HTTP to HTTPS
# https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</IfModule>

# Strict Transport Security Header, this prevents clients 
# with STS support from accessing the site using HTTP
# https://stackoverflow.com/questions/24144552/how-to-set-hsts-header-from-htaccess-only-on-https
Header set Strict-Transport-Security "max-age=31536000" env=HTTPS

# You might want to consider using some of the following rules
# but only do this if you know what your are doing and test them
# first, they are only supported by some Apache versions
# https://serverfault.com/a/668302
#SSLOptions +StrictRequire
#SSLRequireSSL
# Use the following if you only want the site to work with one domain name
#SSLRequire  %{HTTP_HOST} eq "example.org"

Or an approach using If rather than mod_rewrite:

<If "req('X-Forwarded-Proto') != 'https'">
  RedirectMatch 301 ^(?!/\.well-known/acme-challenge/).* https://www.example.org.uk$0
</If>

Generating directory file listings

If you want Apache to generate a listing of files in a directory, like here for example, then add a .htaccess file like this to the directory where you want the listing:

Options +Indexes
DirectoryIndex some-file-that-does-not-exist.html

To customise the HTML and CSS you need to use the ReadmeName and HeaderName directives, to specify different HTML to be used for the top and bottom of the page,for example:

HeaderName /top.html
ReadmeName /bot.html

For more information see the Apache Module mod_autoindex documentation.

Serve .html files using mod-php

If you have .html files that have PHP in them you can force these to be processed as PHP by creating a .htaccess file containing:

# Force .php .html and .htm files to be served as PHP by handler
AddHandler x-httpd-php .php .html .htm
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule \.(html|htm|php)$ - [H=application/x-httpd-php]
</IfModule>
# Force .php .html and .htm files to be served as PHP by type
AddType application/x-httpd-php .php .html .htm
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule \.(html|htm|php)$ - [T=application/x-httpd-php]
</IfModule>

HTTP Basic Authentication

Password protecting a directory

To password protect a directory create a .htaccess file (or if one already exists add to it) and put this in it (changing example to your username):

AuthUserFile /home/example/private/.htpasswd
AuthType Basic
AuthName "My Private Directory"
require valid-user

Password protecting a file

To password protect a specific file, for example wp-login.php, add the following to your existing .htaccess file or if it doesn’t exist create one with the following in it (changing /home/example to the path to the private directory for your account):

<FilesMatch "wp-login.php">
  AuthName "Authorised Users"
  AuthType Basic
  AuthUserFile /home/example/private/.htpasswd
  require valid-user
</FilesMatch>

The AuthName variable value can contain any plain text message you wish.

Password protecting a URL

The above two examples for password protecting a directory or file doesn't work with a content management system like Drupal which will allow you to login via http://example.org/user/login, this isn't a file or a directory, it is a path appended to index.php (env var PATH_INFO) or login via a query string, http://example.org/?q=user/login, (env var QUERY_STRING). So you need a mod_rewrite rule to catch the query string and a Location rule to match the path:

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{QUERY_STRING} user/login [NC]
  RewriteRule .* http://%{HTTP_HOST}/user/login? [R=301,L]
</IfModule>
<LocationMatch "/user/login">
  AuthName "Authorised Users"
  AuthType Basic
  AuthUserFile /home/example/private/.htpasswd
  require valid-user
</LocationMatch>

Generating a .htpasswd file

After adding the directives to a .htaccess file you need to generate a .htpasswd and then upload it to your private directory, this is how to create the file via the command line on a computer with the htpasswd script installed (htpasswd is in the apache2-utils debian package) :

htpasswd -sc .htpasswd username 

If you want to add a username / password to an existing file:

htpasswd -s .htpasswd username 

If you don’t have access to the command line on a computer with htpasswd installed then you can use a online service to generate a .htpasswd file, or get in touch and we can help you.

Combining HTTPS and HTTP Authentication

With Apache, by default, a combination of a Redirect from HTTP to HTTPS and HTTP Authentication and an initial request for the unencrypted version of the site will result in an unencrypted prompt for the username and password before the redirect to HTTPS. Clearly this isn't wanted for two reasons, first it means that the username and password are sent unencrypted and secondly the user is prompted twice for the username and password (the first time via HTTP and the second time via HTTPS).

See this thread, this thread and this thread for discussion about the issue and work-arounds. A solution that works:

The way to get around this is to use SSLRequireSSL and a HTTPS 403 error document, for example:

# Force HTTPS before Authentication
# https://serverfault.com/a/668302
SSLRequireSSL
ErrorDocument 403 https://www.example.org/

Add the above before the access control directives.

And if you want to use the default Webarchitects error pages:

ErrorDocument 404 https://example.org/wsh/404.shtml
ErrorDocument 403 https://example.org/wsh/403.shtml

Further reading

The Apache documentation:

Errors caused by .htaccess files

Some content management systems and plugins for example WordFence and Drupal generate .htaccess files which contain Apache directives which we don't allow them to contain for security reasons, these are easy to track down by looking at the ~/logs/error.log which you have access to.