Use .htaccess files to configure Apache
A .htaccess file allows you to control the behavior
of the Apache web server on a per-app and per-directory basis.
Create a .htaccess file in an app’s web root directory to apply
the file’s directives to all requests for the app.
apps/APPNAME/public/.htaccessThe directives in a .htaccess file can be
overridden by a .htaccess file in a subdirectory.
Long lines can be split into multiple lines by
adding a backslash (\) to indicate the following
line should be considered part of the same line.
Create and edit .htaccess files
You can create and edit .htaccess files either
over SSH or with an SFTP client.
Learn how to edit files over SSH.
Show hidden .htaccess files
Files beginning with a dot (.) are often hidden in directory listings.
To show hidden files when using the ls command,
add the -a (all files) flag.
ls -a apps/APPNAME/public/To show hidden files in the Cyberduck SFTP client:
- Open Cyberduck.
- Click View in the menu bar.
- Select Show hidden files.
To show hidden files in the Filezilla SFTP client:
- Open Filezilla.
- Click Server in the menu bar.
- Select Force showing hidden files.
RewriteRule and RewriteCond
Apache’s RewriteRule and RewriteCond directives are the most commonly used
directives in .htaccess files.
See the
Apache mod_rewrite documentation
for all available options.
RewriteRule directive
The RewriteRule directive does one of the following depending on the flags used:
- Internally change the requested URL. This is the default behavior.
- Redirect the client to a different URL.
- Proxy a request to a different URL.
A RewriteRule directive can be used by itself or can be preceded by
one or more RewriteCond directive to conditionally apply the rule.
The format of a RewriteRule directive is:
RewriteRule PATH_PATTERN SUBSTITUTION [FLAGS]where the values of the placeholders above are:
| Placeholder | Value |
|---|---|
PATH_PATTERN | A regular expression that is matched against the requested path. |
SUBSTITUTION | The URL that replaces the original requested path with either a new URL path or a new absolute URL. |
FLAGS | The flags that control the behavior of the RewriteRule. |
The SUBSTITUTION can include the following:
- Regular expression back-references such as
$1. Use%1instead of$1for back-references from aRewriteCondthat immediately preceded theRewriteCond. - Server variables such as
%{REQUEST_URI}and%{QUERY_STRING}.
Commonly used FLAGS for the RewriteRule directive include:
| Flag | Purpose |
|---|---|
R,L or R=code,L | Redirect the client to the substitution URL. If the status code is not specified, a 302 status code is used. Always use L with R. |
NC | Make the pattern comparison case-insensitive. |
END | Stop rewriting processing entirely. |
L | Stop rewriting process and hand the rewritten request back to the URL parsing engine, possibly applying more RewriteRule directives. |
F | Return a 403 Forbidden response to the client. Use - as the substitution URL when using this flag. |
P | Proxy the request to the substitution URL. |
E=VAR:VAL | Set the value of an environment variable. |
UnsafeAllow3F | Allows substitutions that may be unsafe if the request URI has an encoded question mark, %3f, and the rewritten result has a ?. |
See the full list of available flags.
RewriteCond directive
The RewriteCond directive is used to conditionally apply a RewriteRule.
The format of a RewriteCond directive is:
RewriteCond TEST_STRING COND_PATTERN [FLAGS]where the values of the placeholders above are:
| Placeholder | Value |
|---|---|
TEST_STRING | The string that the COND_PATTERN will be matched against. |
COND_PATTERN | The pattern applied to TEST_STRING to determine if the RewriteCond evaluates to true. |
FLAGS | The flags that control the behavior of the RewriteCond. |
The TEST_STRING can include the following:
- Server variables such as
%{REQUEST_URI},%{QUERY_STRING},%{HTTP_HOST},%{REMOTE_ADDR}. - HTTP headers specified as
%{HTTP:header}such as%{HTTP:Authorization}. - Environment variables as
%{ENV:variable}such as%{ENV:FOO}.
The COND_PATTERN can be any of the following:
- A regular expression.
- A string comparison if preceded by
=. - A file attribute test:
-dto test ifTEST_STRINGis a directory.-fto test ifTEST_STRINGis a regular file.
Any type of COND_PATTERN can be preceded by ! to negate the result of the condition.
The optional FLAGS for the RewriteCond directive can be one of the following:
| Flag | Purpose |
|---|---|
NC | Make the test case-insensitive. |
OR | Combine the RewriteCond with the next RewriteCond using a “logical or”. If not specified, the default is a “logical and”. |
Redirect requests
Redirect requests for the domain old.example.com
to the same path at the domain new.example.com
using a 302 redirect.
RewriteCond %{HTTP_HOST} =old.example.comRewriteRule (.*) https://new.example.com/$1 [R=302,L]Redirect requests for any domain other than new.example.com
to the same path at the domain new.example.com
using a 302 redirect.
RewriteCond %{HTTP_HOST} !=new.example.comRewriteRule (.*) https://new.example.com/$1 [R=302,L]Forbid user agents
Reject requests for any path if the user agent matches either of three user agents.
RewriteCond %{HTTP_USER_AGENT} "=BadUserAgentOne/1.0" [OR]RewriteCond %{HTTP_USER_AGENT} "=BadUserAgentTwo/1.0" [OR]RewriteCond %{HTTP_USER_AGENT} "=AnotherBadUserAgent/2.2"RewriteRule .* - [F]Clean URLs
Send all requests to your app’s index.php file.
RewriteRule ^index\.php$ - [L]RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule . /index.php [L]In your PHP code, you can then use the value of $_SERVER['REQUEST_URI']
to determine the requested path.
Set cache expiration
Browsers and CDNs cache responses according to a response’s cache control headers.
Use Apache’s ExpiresActive, ExpiresDefault, and ExpiresByType directives to
add cache expiration headers.
See the
Apache mod_expires documentation
for more options.
The following example sets a default cache expiration of 300 seconds and a longer expiration of 3600 seconds for CSS files.
ExpiresActive OnExpiresDefault A300ExpiresByType text/css A3600Password protection
To require a valid username and password for all requests an app,
add the following the .htaccess file in the app’s public/ directory.
Replace SYSUSER and APPNAME with
the name of the app’s system user and the app’s name.
AuthType BasicAuthName "Authentication Required"AuthUserFile /srv/users/SYSUSER/apps/APPNAME/public/.htpasswdRequire valid-userTo instead password protect one or more files, use the following.
In addition to replacing SYSUSER and APPNAME,
replace FILENAME with the name of the file to password protect,
for example, sensitive-file.html
Use a wildcard to match multiple files, for example, *.csv.
See the Files directive documentation
for more options.
<Files FILENAME> AuthType Basic AuthName "Authentication Required" AuthUserFile /srv/users/SYSUSER/apps/APPNAME/public/.htpasswd Require valid-user</Files>Next, SSH into the server as the app’s system user
and run the following command.
Replace APPNAME with the name of the app.
touch ~/apps/APPNAME/public/.htpasswdUse the htpasswd-sp command to add or update credentials for a user.
You’ll be prompted for the password to set for the user.
Replace APPNAME with the name of the app
and replace AUTH_USER with the name of the user to add.
htpasswd-sp ~/apps/APPNAME/public/.htpasswd AUTH_USERRestrict IP addresses
Use the Require directive to enforce access control.
See the
Apache access control documentation
for more details.
Allow addresses
Only allow requests from specific addresses, block all other requests.
<RequireAny>Require ip 203.0.113.0Require ip 203.0.113.1</RequireAny>Allow requests from a range of IP addresses specified as a CIDR block.
<RequireAny>Require ip 203.0.113.0/24</RequireAny>Block addresses
Block requests from specific addresses, allow all other requests.
<RequireAny>Require all grantedRequire not ip 203.0.113.0Require not ip 203.0.113.1</RequireAny>Block requests from a range of IP addresses specified as a CIDR block, allow all other requests.
<RequireAny>Require all grantedRequire not ip 203.0.113.0/24</RequireAny>Custom error pages
Use the ErrorDocument directive to change an app’s error pages.
Any of these formats work:
ErrorDocument 403 "Sorry, access to this page is forbidden."ErrorDocument 500 http://example.com/server_error.htmlErrorDocument 503 /errors/service_unavailable.htmlThe format that uses an http or https URL will redirect the browser
to the specified page.
ErrorDocument 403 "Sorry, access to this page is forbidden."ErrorDocument 500 http://example.com/server_error.htmlErrorDocument 503 /errors/service_unavailable.htmlErrorDocument 403 "Sorry, access to this page is forbidden."ErrorDocument 500 http://example.com/server_error.htmlErrorDocument 503 /errors/service_unavailable.htmlCustom 404 for .php requests
The ErrorDocument directive will not handle 404 errors for
requests where the file name ends in .php.
For example, a request for /does-not-exist.php
will not be handled by the ErrorDocument.
To show a custom 404 page using a file named 404.php,
add the following to your app’s .htaccess file:
RewriteRule ^404\.php$ - [L]RewriteCond %{REQUEST_FILENAME} !-fRewriteCond %{REQUEST_FILENAME} !-dRewriteRule . /404.php [C]RewriteRule . - [R=404,L]Add response headers
Add response headers with the Header directive.
Header always set My-Header-Name "header value"See the Apache mod_headers documentation for more options including conditionally adding headers to responses.
Set environment variables
Use the SetEnv directive to
set environment variables that will be available within your PHP app’s code.
SetEnv NAME "value"Enable directory listing
When directory listing is enabled,
requests for directories that do not contain
an index.php, index.html, or index.htm file
will display a list of the files in the directory.
To enable directory listing for a specific directory,
create a .htaccess file in the directory and
add the following to the .htaccess file:
Options +IndexesYou can control how the directory listing appears with the IndexOptions directive.
For example, the following will display the listing
without file type icons and will also display file sizes and modification times.
Options +IndexesIndexOptions FancyIndexing SuppressIconSee the
Apache IndexOptions documentation
for more information on customizing directory listings.
Case-insensitive URLs
Use the CheckSpelling and CheckCaseOnly directives to
enable serving files that were requested using a request path
that does not match the case of the file name.
CheckSpelling onCheckCaseOnly onSee the Apache mod_speling documentation for more options.
Replace strings in responses
Replace strings in responses using the
AddOutputFilterByType and Substitute directives.
The following replaces all occurrences of the string old.example.com
with the string new.sitename.com.
AddOutputFilterByType SUBSTITUTE text/htmlSubstitute s/old.example.com/new.sitename.com/niThe options ni tell Apache to use a fixed string rather than a regular
expression (n) and to do a case-insensitive search (i).
To perform more than one substitution, add more Substitute directives.
AddOutputFilterByType SUBSTITUTE text/htmlSubstitute s/sitename.example.com/sitename.com/niSubstitute s/othersite.example.com/othersite.com/niMore information is available in the Apache mod_substitute documentation.