htaccess best practices

2024-02-16 PHPSECURITY

SEO and performance

set expiration header

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 week"
    ExpiresByType text/html "access plus 600 seconds"
    ExpiresByType text/plain "access plus 0 seconds"
    ExpiresByType text/xml "access plus 0 seconds"
    ExpiresByType text/css "access plus 1 week"
    ExpiresByType image/gif "access plus 1 week"
    ExpiresByType image/png "access plus 1 week"
    ExpiresByType image/jpg "access plus 1 week"
    ExpiresByType image/jpeg "access plus 1 week"
    ExpiresByType image/x-icon "access plus 4 week"
    ExpiresByType image/svg+xml "access plus 4 weeks"
    ExpiresByType video/mp4 "access plus 4 weeks"
    ExpiresByType video/ogg "access plus 4 weeks"
    ExpiresByType video/webm "access plus 4 weeks"
    ExpiresByType video/x-flv "access plus 4 weeks"
    ExpiresByType application/javascript "access plus 4 weeks"
    ExpiresByType application/json "access plus 0 seconds"
    ExpiresByType application/xml "access plus 0 seconds"
    ExpiresByType application/x-shockwave-flash "access plus 4 weeks"
    ExpiresByType application/ "access plus 4 weeks"
    ExpiresByType application/x-font-ttf "access plus 4 weeks"
    ExpiresByType application/font-woff "access plus 4 weeks"
    ExpiresByType application/font-woff2 "access plus 4 weeks"
    ExpiresByType font/opentype "access plus 4 weeks"

compress text file response

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript

enable file compression

<ifModule mod_gzip.c>
    mod_gzip_on Yes
    mod_gzip_dechunk Yes
    mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
    mod_gzip_item_include handler ^cgi-script$
    mod_gzip_item_include mime ^text/.*
    mod_gzip_item_include mime ^application/x-javascript.*
    mod_gzip_item_exclude mime ^image/.*
    mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*


Enable Url rewriting

RewriteEngine On

redirect HTTP requests to HTTPS

RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !=localhost
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Optional redirect every URL to www

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} !=localhost
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

pass the Authorization header to PHP

SetEnvIf Authorization "(.+)" HTTP_AUTHORIZATION=$1

this is also possible with a redirect rule

RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Run everything but real files through index.php

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [L]

you can also redirect all requests through index.php, expect a specific Forder for public resources

# if folder not "public", then rewrite to index.php
RewriteRule !^(public)/(.*)$ index.php [NC,L]


set headers for unknown content types

<IfModule mod_headers.c>
    # serve files as plain text if the actual content type is not known
    # (hardens against attacks from malicious file uploads)
    Header set Content-Type "text/plain" "expr=-z %{CONTENT_TYPE}"
    Header set X-Content-Type-Options "nosniff"

Prevent file browsing and disable the "MultiViews" option

<IfModule mod_negotiation.c>
    Options -MultiViews
    Options -Indexes

Block direct access for filters and specific files.
These lines should be placed under the line, on you pass the request to php files.
(Thenty only be observed in case these files are accessible)

# Block all direct access for these folders
RewriteRule ^(\.git|cache|bin|logs|backup|webserver-configs|tests)/(.*) error [F]
# Block access to specific file types for these system folders
RewriteRule ^(system|vendor)/(.*)\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ error [F]
# Block all direct access to files and folders beginning with a dot
# except for the .well-known folder, which is used for Let's Encrypt and security.txt
RewriteRule (^|/)\.(?!well-known) - [F]
# Block access to specific files in the root folder
RewriteRule ^(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$ error [F]

disable frame integration of the website in other sites

<IfModule mod_headers.c>
    Header append X-Frame-Options SAMEORIGIN

prevent svg xss attacks

<IfModule mod_headers.c>
    <FilesMatch "\.(?i:svg)$">
        Header set Content-Security-Policy "script-src 'none'"


❰ back