Free tool · no signup
.htaccess security generator
Tick the protections you want and get a tested set of .htaccess rules for Apache: https redirect, hidden files, backups, security headers and a WordPress hardening block.
By the Bug Circuit security team · Last updated
What to switch on
# Hardening rules generated by Bug Circuit. Test on a staging copy first and keep a backup of your old .htaccess.
# Send every http:// request to https://. The X-Forwarded-Proto test stops a redirect loop behind a proxy or CDN.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# Do not list the files in a folder that has no index file.
Options -Indexes
# Do not print the Apache version on error pages. (ServerTokens can only be set in the main server config.)
ServerSignature Off
# Refuse the TRACE and TRACK methods.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) [NC]
RewriteRule .* - [F]
</IfModule>
# Hidden files such as .env, .htpasswd and .DS_Store must never be served.
<FilesMatch "^\.">
Require all denied
</FilesMatch>
# Backup, database dump and log files left in the web root.
<FilesMatch "(\.(bak|backup|old|orig|save|sql|sqlite|swp|log|dist)|~)$">
Require all denied
</FilesMatch>
# Source-control folders must not be reachable.
<IfModule mod_alias.c>
RedirectMatch 404 "/\.(git|svn|hg)(/|$)"
</IfModule>
# Basic security headers (needs mod_headers).
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>
- Add the redirect only after https works on every page, or visitors will see certificate errors. WordPress also needs its Site Address set to https.
- Options -Indexes needs AllowOverride Options (or All) in the server config. If the site returns a 500 error after you add it, remove that line or ask your host to allow it.
- These rules work on Apache and compatible servers (LiteSpeed). Nginx and most managed hosts ignore .htaccess: use the security headers generator for nginx.
- A typo can take the whole site down with a 500 error. Keep the old file so you can put it back, and check the site straight after saving.
Put these lines above any WordPress block (# BEGIN WordPress) so WordPress does not rewrite them.
How it works
What each rule protects
The https redirect sends every plain http request to https, with a check for the X-Forwarded-Proto header so it does not loop behind a CDN or proxy. Options -Indexes stops Apache listing the files in a folder that has no index page. The dotfile rule blocks files whose names start with a dot, such as .env, .htpasswd and .DS_Store, and a separate rule hides .git, .svn and .hg folders, so a deployed repository cannot be downloaded. The backup rule blocks leftovers such as backup.sql, site.old and error.log.
The headers block adds X-Content-Type-Options, X-Frame-Options, Referrer-Policy and Permissions-Policy, and optionally HSTS. TRACE and TRACK are refused, and the Apache version is hidden on error pages. These are safe defaults, not a complete policy: use the security headers generator for a Content-Security-Policy.
WordPress options
The WordPress block denies direct access to wp-config.php and to readme.html and license.txt, which reveal your WordPress version. You can also block xmlrpc.php, which attackers use for password guessing, but doing so breaks Jetpack, the mobile app and some publishing tools. The author scan rule stops /?author=1 requests that reveal usernames, and it leaves wp-admin alone because the admin screens use that parameter.
The most useful WordPress rule is the second file: a small .htaccess inside wp-content/uploads that stops files there running as PHP. Attackers who find an upload bug usually drop a PHP web shell into that folder, and this rule turns it into a download that does nothing.
Test before you trust it
A single typo in .htaccess returns a 500 error for the whole site. Keep the old file, add the new rules above any WordPress block, and load your home page and your admin login straight away. If you get a 500 error, remove the last block you added. The log, usually error.log in your hosting panel, names the line.
.htaccess works on Apache and compatible servers such as LiteSpeed. Nginx ignores it, and many managed WordPress hosts run Nginx, so ask your host first. On Nginx, use the security headers generator and your host's own settings.
Worked examples
Hide dotfiles and backups
Apache 2.4, the two blocking options ticked.
<FilesMatch "^\."> Require all denied </FilesMatch> <FilesMatch "(\.(bak|backup|old|orig|save|sql|sqlite|swp|log|dist)|~)$"> Require all denied </FilesMatch>
A request for /.env or /backup.sql now gets a 403 instead of your secrets.
Stop PHP running from uploads (WordPress)
Save this as wp-content/uploads/.htaccess.
<FilesMatch "\.(?i:php|phtml|phar|php[0-9])$"> Require all denied </FilesMatch>
Media files still load. A PHP file uploaded through a vulnerable plugin can no longer be run by visiting it.
Redirect to https behind a CDN
The https redirect option.
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]The second condition stops a redirect loop when a proxy talks to your server over http but the visitor used https.
Frequently asked questions
Does .htaccess work on Nginx?
Why does my site show a 500 error after adding these rules?
Where do I put the rules?
Is it safe to block xmlrpc.php?
Should I turn on HSTS?
Can I set ServerTokens here?
Do these rules make my site secure?
Keep reading
See what attackers see, for free
Run the free passive check on your website. No login, no impact on your site, results in seconds.
Ready for the full manual audit? See pricing