Skip to main content
.htaccess in Joomla
# Topics

.htaccess in Joomla

05 July 2026

One small text file in your Joomla root, the .htaccess file, decides whether your clean URLs work, whether common attacks get blocked, and whether your CSS and JavaScript arrive compressed. Most site owners never open it, yet it runs on almost every request to an Apache server. When it is missing or wrong, pages return "404 Not Found", the site looks broken, or it quietly stays less safe than it should be.

This article explains the Joomla .htaccess file from top to bottom. It covers the basics for site owners, the rename and SEF setup for administrators, and the rewrite rules, security blocks, and performance tricks that developers need to understand.

The .htaccess file is the doorman of an Apache Joomla site: it decides what gets in, where it goes, and how fast it arrives.

The goal is simple: help you understand what every block in the shipped file does, so you can use it with confidence and adapt it safely.

1. The Basics

1.1 What is the .htaccess File?

The .htaccess file (the name means "hypertext access") is a per-directory configuration file for the Apache web server. It lets you change how the server behaves for one folder and everything below it, without touching the main server configuration. The leading dot makes it a hidden file on Linux, which is why many file managers do not show it by default.

Joomla uses it for four main jobs:

  • Turn clean SEF URLs into requests Joomla can route.
  • Block some of the most common attack patterns in the URL.
  • Set a few security headers and access rules.
  • Serve pre-compressed CSS and JavaScript when they exist.

1.2 Why It Ships as htaccess.txt

Joomla does not install an active .htaccess file. It ships a ready-made template named htaccess.txt in the site root instead. There are two reasons. First, a hidden file is easy to overlook during an upload. Second, an .htaccess file with rewrite rules on a server that does not support them can break the whole site. Shipping it as a plain .txt keeps it inactive until you choose to use it.

To activate it, you rename the file:

htaccess.txt   →   .htaccess

This single rename is the step most beginners forget. The two files are byte-for-byte identical; only the name differs.

1.3 Where It Lives

The file sits in the Joomla web root, next to index.php and configuration.php:

public_html/
   index.php
   configuration.php
   htaccess.txt        ← the shipped template
   .htaccess           ← the active file after you rename it
   web.config.txt      ← the IIS equivalent (Windows only)

Apache reads .htaccess only when it is allowed to (see section 11). On most shared hosting it is allowed by default, which is exactly why .htaccess is so popular there.

Back to top

2. Turning On Clean URLs

2.1 The Two Joomla Settings

Clean URLs depend on two options in System → Global Configuration → Site, plus the file itself:

  • Search Engine Friendly URLs turns index.php?option=com_content&view=article&id=42 into /news/42-my-article. This works on any web server, with or without .htaccess.
  • Use URL Rewriting removes the index.php from the path, so the URL becomes /news/my-article. This option needs the web server's rewrite engine and the matching config file.

2.2 The Order That Avoids a Broken Site

Do the steps in this order:

  1. Rename htaccess.txt to .htaccess first.
  2. Then set Use URL Rewriting = Yes in Global Configuration.
  3. Open a few internal links and confirm they load.

If you switch on rewriting before the file exists, Joomla produces URLs without index.php, but Apache does not know how to route them, and every page except the home page returns a 404.

2.3 What Each Setting Produces

SEFURL RewritingExample URL
Off Off /index.php?option=com_content&view=article&id=42
On Off /index.php/news/42-my-article
On On /news/my-article

Only the last row needs .htaccess. The middle row is the safe fallback when rewriting is not available: the index.php stays in the path, but the URL is still readable.

Back to top

3. The Top of the File: Options and Headers

Before any rewriting happens, the shipped file sets a few server options and security headers. These run even if mod_rewrite is switched off.

Options +FollowSymlinks
Options -Indexes

+FollowSymlinks lets Apache follow symbolic links, which mod_rewrite requires. The file's own comments warn that some hosts forbid setting this in .htaccess; if your site errors, you comment the line out. -Indexes stops Apache from showing an automatic file list when a folder has no index file, so visitors cannot browse your directories.

A second block reinforces the same idea for the autoindex module:

<IfModule mod_autoindex.c>
    IndexIgnore *
</IfModule>

3.2 The nosniff Header

The file sets one security header for every response:

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
</IfModule>

This tells the browser not to guess ("sniff") the content type of a file. Without it, a browser might treat an uploaded image as JavaScript and run it. The <IfModule> wrapper means the rule applies only if Apache's mod_headers is loaded, so the file never errors on a server that lacks it.

3.3 Locking Down SVG Files

SVG images are XML and can contain scripts. The shipped file blocks that when an SVG is opened directly:

<FilesMatch "\.svg$">
  <IfModule mod_headers.c>
    Header always set Content-Security-Policy "script-src 'none'"
  </IfModule>
</FilesMatch>

This stops inline JavaScript from running when someone opens an SVG file straight from your media folder or embeds it with an <object> tag. It is a small but real defence against a malicious upload.

3.4 The Commented CORP and COEP Block

Just above the SVG rule, the file includes two cross-origin headers that are commented out by default:

#<IfModule mod_headers.c>
#    Header always set Cross-Origin-Resource-Policy "same-origin"
#    Header always set Cross-Origin-Embedder-Policy "require-corp"
#</IfModule>

They are off because they can break sites that legitimately load images, fonts, or embeds from other domains. Enable them only after you test that every third-party asset still loads. They are powerful, but they are not safe to switch on blindly.

Back to top

4. The Exploit-Blocking Rules

Once mod_rewrite is on, the file opens with a short list of rules that block the most common Joomla exploit attempts in the URL query string. Each rule inspects %{QUERY_STRING} and, on a match, returns a 403 Forbidden.

RewriteEngine On

# Block any script trying to base64_encode data within the URL.
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
# Block any script that includes a <script> tag in URL.
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
# Block any script trying to set a PHP GLOBALS variable via URL.
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block any script trying to modify a _REQUEST variable via URL.
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Return 403 Forbidden and show the root home page content.
RewriteRule .* index.php [F]

In plain words, the four conditions catch:

  • base64_encode(...) in the URL, a classic way to smuggle code.
  • An injected <script> tag, plain or URL-encoded as %3C...%3E.
  • Attempts to overwrite PHP's GLOBALS array.
  • Attempts to tamper with the _REQUEST variable.

The [OR] flag chains the conditions so that any one match triggers the block. The final [F] flag returns 403 Forbidden. These rules are a helpful baseline, not a firewall: keep Joomla updated and use a real Web Application Firewall for serious protection. If a legitimate request ever trips them, the comments tell you to disable the offending line with a leading #.

Back to top

5. The Custom Redirects Section

The file reserves a clearly marked space for your own redirect rules:

## Begin - Custom redirects
#
# If you need to redirect some pages, or set a canonical non-www to
# www redirect (or vice versa), place that code here. Ensure those
# redirects use the correct RewriteRule syntax and the [R=301,L] flags.
#
## End - Custom redirects

This block is intentionally empty. It is the right place for infrastructure-level redirects that should run before PHP starts. A common example forces a single canonical host:

# Redirect www to the bare domain with a permanent 301
RewriteCond %{HTTP_HOST} ^www\.example\.test [NC]
RewriteRule (.*) https://example.test/$1 [R=301,L]

Put it inside this section so a Joomla update that replaces the SEF rules does not wipe your customisation by accident. For editorial redirects (a renamed article keeping its old link), prefer Joomla's own Redirects component, which is editor-friendly and survives a site move. Use .htaccess for server-level rules such as forcing HTTPS or a canonical host. See the Redirects article for the difference.

Back to top

6. RewriteBase and Subfolders

Just before the core SEF section, the file has a commented line:

# RewriteBase /

It tells Apache the URL path that the rewrite rules are relative to. For a site in the web root you almost never need it. But when Joomla lives in a subfolder, for example https://example.test/blog/, or when the server's URL does not map directly to the physical file path, you uncomment and set it:

RewriteBase /blog

Forgetting this is one of the most common rewrite problems on subfolder installs. The home page works, but internal links resolve against the wrong base and return 404s. Set the base to match the folder, just / for the root.

Back to top

7. The Core SEF Section

This is the heart of the file: the rules that actually route clean URLs to Joomla. It has three parts.

7.1 The HTTP Authorization Fix

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

Some PHP setups (FastCGI) strip the HTTP Authorization header before PHP sees it. Joomla's Web Services API uses that header to read its bearer token. This line copies the header into an environment variable so the API can still find it. The - target means "do not rewrite the URL", only set the variable.

7.2 Routing the Web Services API

RewriteCond %{REQUEST_URI} ^/api/
RewriteCond %{REQUEST_URI} !^/api/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* api/index.php [L]

If the path starts with /api/, is not already api/index.php, and does not match a real file or folder, Apache rewrites it to the API entry point api/index.php. This is how a request like /api/index.php/v1/content/articles reaches Joomla's headless API. The [L] flag means "last rule, stop here".

7.3 Routing the Front End

RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]

This is the rule that makes clean URLs work. The two key conditions are !-f ("not a real file") and !-d ("not a real directory"). Together they say:

If the request points at a real file or folder, serve it directly. Otherwise, hand it to index.php and let Joomla figure out the route.

That is why /about-us reaches Joomla and becomes a page, while /images/logo.png is served straight from disk and never touches PHP.

7.4 Rewrite Versus Redirect

The SEF rules above are rewrites, and a rewrite is not the same as a redirect. The difference matters the moment you add your own rules.

  • A rewrite is internal and invisible. The browser asks for /about-us, Apache quietly serves index.php, and the address bar never changes. This is how clean URLs reach Joomla.
  • A redirect is external and visible. Apache tells the browser "go to this other URL instead", the browser makes a second request, and the address bar changes. This is how you send an old URL to a new one.

Use a rewrite when you want Joomla to handle a friendly URL. Use a redirect when a URL has genuinely moved, and send the right status code: 301 for a permanent move, 302 for a temporary one.

7.5 Common Rewrite Flags

The square brackets at the end of a RewriteRule or RewriteCond are flags that change what the rule does. The shipped file uses several of them; these are the ones worth knowing:

FlagMeaning
L Last rule: stop processing further rewrite rules in this pass.
END Stop all rewrite processing completely, with no further passes.
NC No case: match case-insensitively.
QSA Query String Append: keep the original query string and add to it.
R=301 Redirect the browser with a 301 (permanent); use R=302 for temporary.
F Forbidden: return 403 and stop. Used by the exploit-blocking rules.
G Gone: return 410, telling crawlers the URL is permanently removed.
OR On a RewriteCond, combine with the next condition as "either/or".

Reading the flags is the quickest way to understand an unfamiliar rule. [R=301,L], for example, means "redirect permanently and stop", the standard pair for a canonical or HTTPS redirect.

Back to top

8. The No-Rewrite Fallback

What happens if mod_rewrite is not available at all? The file has a small fallback that runs only in that case:

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 302 ^/$ /index.php/
    </IfModule>
</IfModule>

The !mod_rewrite.c condition means "only if mod_rewrite is not loaded". In that situation, a visitor to the bare domain is sent with a temporary 302 redirect to /index.php/, so the front controller still runs and the generated links (which include index.php) keep working. It is a safety net, not a feature you rely on: without mod_rewrite you cannot use the cleanest URL format.

Back to top

9. Compression and Caching

9.1 Serving Pre-Compressed Assets (GZIP and Brotli)

The last block in the file is a performance trick. If a pre-compressed .gz copy of a CSS or JavaScript file exists, and the browser accepts gzip, Apache serves the smaller file instead of compressing on the fly.

<IfModule mod_headers.c>
    # Serve a gzip-compressed CSS file if it exists and the client accepts gzip.
    RewriteCond "%{HTTP:Accept-encoding}" "gzip"
    RewriteCond "%{REQUEST_FILENAME}\.gz" -s
    RewriteRule "^(.*)\.css" "$1\.css\.gz" [QSA]

    # Same for JavaScript.
    RewriteCond "%{HTTP:Accept-encoding}" "gzip"
    RewriteCond "%{REQUEST_FILENAME}\.gz" -s
    RewriteRule "^(.*)\.js" "$1\.js\.gz" [QSA]

    # Send the right content type and stop double compression.
    RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1,E=no-brotli:1]
    RewriteRule "\.js\.gz$" "-" [T=text/javascript,E=no-gzip:1,E=no-brotli:1]
</IfModule>

Two details matter. The no-gzip and no-brotli flags stop Apache from compressing an already-compressed file a second time, which would corrupt it. A FilesMatch block then sets Content-Encoding: gzip and adds Vary: Accept-Encoding so proxies cache the compressed and uncompressed versions separately.

The file's own comment warns that if your host already gzips CSS and JS, this block causes a double-compression error (ERR_CONTENT_DECODING_FAILED in the browser console). If you see that, comment the GZIP section out. This block only helps if you actually generate .css.gz and .js.gz files; without them, it simply does nothing.

9.2 Browser Caching with mod_expires

Pre-compression makes the first download smaller; browser caching avoids the download entirely on the next visit. With mod_expires you tell browsers how long to keep static files. This is not part of the shipped file, so you add it in your own block:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg            "access plus 1 year"
    ExpiresByType image/png             "access plus 1 year"
    ExpiresByType image/webp            "access plus 1 year"
    ExpiresByType image/svg+xml         "access plus 1 year"
    ExpiresByType font/woff2            "access plus 1 year"
    ExpiresByType text/css              "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Typical durations are a year for images and fonts, which rarely change, and a month for CSS and JavaScript. Long expiry works best when your file names are versioned (for example style.4f2a.css): a changed file gets a new name, so the browser fetches the new one instead of serving a stale cached copy. Joomla's own media versioning helps here by appending a version query to its assets.

Back to top

10. The .htaccess on Other Web Servers

The .htaccess file is an Apache feature. Other servers handle the same jobs differently.

ServerReads .htaccess?How SEF is configured
Apache Yes Rename htaccess.txt to .htaccess.
LiteSpeed (commercial) Yes Reads the Apache .htaccess directly.
OpenLiteSpeed Only if enabled Turn on "Auto Load from .htaccess", or use its own rewrite settings.
Nginx No Add a try_files rule to the server config.
IIS (Windows) No Rename web.config.txt to web.config and install URL Rewrite.

The single most common migration mistake is copying an Apache .htaccess into an Nginx setup and expecting it to work. Nginx ignores the file completely. The same routing logic exists, but it must be written into the server config in Nginx's own syntax. See the Web Servers article for the per-server equivalents.

Back to top

11. Under the Hood (Developer View)

11.1 When Apache Reads the File

Apache checks for .htaccess on every request, and it reads not just the file in the target folder but the one in every parent folder up to the document root. This is flexible: you can drop rules into any folder without server access. It is also the cost: those file reads happen on every single request.

11.2 AllowOverride Controls Everything

Whether Apache reads .htaccess at all depends on the AllowOverride directive in the main server config:

<Directory /var/www/html>
    AllowOverride All      # read .htaccess and honour its directives
</Directory>

If AllowOverride is None, Apache ignores the file entirely, and your rewrite rules do nothing no matter how correct they are. On a server you control, the faster pattern is to set AllowOverride None and move the rules into the virtual host, so Apache stops looking for the file:

# Same Joomla rules, but in the <VirtualHost> instead of .htaccess
<Directory /var/www/html>
    Options +FollowSymlinks -Indexes
    AllowOverride None
    # ... paste the RewriteRule blocks here ...
</Directory>

This removes the per-request file reads and is measurably faster at scale. On shared hosting you rarely have this choice, so .htaccess stays.

11.3 How the Server Hands Off to Joomla

After the rewrite, Joomla reads the request from the $_SERVER superglobal that Apache populates. A few values drive how Joomla builds URLs and detects HTTPS:

VariableWhat Joomla uses it for
REQUEST_URI The requested path, to route the page.
HTTP_HOST The domain, to build absolute links.
HTTP_AUTHORIZATION The API bearer token (set by the fix in section 7.1).
HTTPS To decide whether the connection is secure.

11.4 Testing the API Route

Because the file routes /api/ to api/index.php and preserves the Authorization header, you can confirm the Web Services API works with a single request:

curl -H "X-Joomla-Token: <your-token>" \
     https://example.test/api/index.php/v1/content/articles

A JSON list of articles means the rewrite and the Authorization fix both work. A 404 on the same call usually means .htaccess is not active or AllowOverride is off.

11.5 Behind a Reverse Proxy or CDN

Many Joomla sites sit behind a CDN or reverse proxy such as Cloudflare. The .htaccess file still runs on the origin server, but the request has already passed through another layer first, and that changes two things.

First, the proxy often terminates HTTPS and then talks to your server over plain HTTP. Apache sees HTTPS as off, so a plain "Force HTTPS" rewrite can loop forever: the visitor arrives over HTTPS at the proxy, your server sees HTTP and redirects to HTTPS, the proxy forwards it again as HTTP. The fix is to check the forwarded header instead of HTTPS:

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Second, set Behind Load Balancer = Yes in Global Configuration → Server, so Joomla trusts the forwarded protocol and builds https:// links correctly. Without it, you can get mixed-content warnings or redirect loops even when the .htaccess rule itself is right.

Back to top

12. Security Beyond the Shipped Rules

The shipped file is a baseline. On a server where you can edit .htaccess freely, a few extra rules harden the site further. Add them in your own block, not inside the Joomla SEF section.

12.1 Force HTTPS

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

Back it up with Global Configuration → Server → Force HTTPS = Entire Site, so Joomla enforces it too.

12.2 Block Sensitive Files

Some files should never be downloadable. The most important is configuration.php, which holds your database password. You can deny direct access to risky paths:

<FilesMatch "^(configuration\.php|\.env|.*\.(bak|old|log))$">
    Require all denied
</FilesMatch>

# Block the .git folder
RedirectMatch 404 /\.git

Note that modern Joomla already places much of its code outside the web root and protects core folders, but backup copies such as configuration.php.bak are a frequent leak that these rules close.

12.3 Keep Headers Consistent

Joomla ships a System - HTTP Headers plugin that sets most security headers from the backend. The .htaccess file sets X-Content-Type-Options: nosniff at the server. If both set the same header with different values, the one that runs last wins, usually the server or a proxy. Decide where each header lives and keep the two layers in sync.

12.4 Optional Hardening

The rules below are not in the shipped file and not required, but they close common gaps. Add only the ones you understand, test after each, and keep them in your own block, never inside the Joomla SEF section.

Stop PHP running in upload folders. An attacker who manages to upload a script often drops it in a media folder such as images/. Place a small second .htaccess file inside that folder to refuse PHP execution. You scope it by location this way because the <Directory> directive is not allowed in an .htaccess file:

# images/.htaccess
<FilesMatch "\.php$">
    Require all denied
</FilesMatch>

Disable the TRACE method. The HTTP TRACE method is almost never needed and can echo back request headers. Refuse it:

RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]

Deny more sensitive files. Extend the block from section 12.2 to cover dependency manifests and database dumps, which sometimes get left in the web root:

<FilesMatch "^(composer\.(json|lock)|.*\.sql)$">
    Require all denied
</FilesMatch>

Add stronger response headers. Beyond nosniff, these headers improve security but need testing, because a strict policy can block third-party fonts, scripts, or embeds:

<IfModule mod_headers.c>
    # Force HTTPS for two years, including subdomains. Add only once HTTPS is solid.
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
    # Send only the origin as referrer to other sites.
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    # Switch off browser features the site does not use.
    Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
</IfModule>

Joomla's System - HTTP Headers plugin can set most of these from the backend instead. Pick one place, the plugin or the file, and keep it consistent (see section 12.3). Add HSTS only when every page reliably loads over HTTPS, because once a browser sees the header it refuses plain HTTP for the whole max-age, even if you later turn HTTPS off.

Branded error pages. Apache's default error screens look nothing like your site. Route them through Joomla so the visitor stays on a branded page:

ErrorDocument 404 /index.php
ErrorDocument 403 /index.php

Joomla then renders its own error page, which you can style by overriding templates/your_template/error.php. Keep the target as /index.php so the path still resolves if the site moves to a subfolder or a new domain.

Back to top

13. SEO and Metadata

The .htaccess file shapes SEO before any extension does. Search engines reward sites that are fast, secure, and consistent, and all three start here:

  • Clean URLs: with the file active and URL Rewriting on, paths are short and readable, which both users and crawlers prefer.
  • One canonical host: use the custom redirects block to force HTTPS and pick either www or the bare domain, then 301-redirect the other. Serving the same page on two hosts splits ranking signals.
  • Correct status codes: a permanent move must return 301, not 302. The [R=301,L] flags matter for passing link equity.
  • Speed: the GZIP block and long cache headers improve Core Web Vitals, which feed Google's ranking.

None of this needs an SEO extension. It is configuration you set once in the file and in Global Configuration, and it pays off on every page.

Back to top

14. Common Mistakes and Pitfalls

14.1 Forgetting the Rename

Symptom: the home page works, but every other page returns 404 after you switch on Use URL Rewriting.

Fix: rename htaccess.txt to .htaccess. The file must be active before rewriting is turned on.

14.2 The Hidden File You Cannot See

Symptom: you renamed the file but your FTP client or file manager does not show it, so you are not sure it exists.

Fix: enable "show hidden files" in your client (or ls -a on the command line). Files beginning with a dot are hidden by default.

14.3 AllowOverride Is Off

Symptom: the file exists, is named correctly, yet rewriting still does nothing.

Fix: the server has AllowOverride None. Ask your host to allow overrides, or move the rules into the virtual host (see section 11.2).

14.4 The Subfolder RewriteBase

Symptom: rewriting works in the web root but breaks when Joomla lives in a subfolder.

Fix: uncomment and set RewriteBase /subfolder to match the install path.

14.5 Double Compression

Symptom: CSS and JavaScript fail to load and the console shows ERR_CONTENT_DECODING_FAILED.

Fix: your host already gzips assets. Comment out the GZIP block at the bottom of the file.

14.6 Edits Lost After an Update

Symptom: your custom rules disappear after a Joomla update or a fresh upload.

Fix: a major update can ship a new htaccess.txt; if you re-rename it, your edits are gone. Keep your rules only inside the "Custom redirects" block, and keep a backup copy of your live .htaccess.

14.7 Blocking Yourself with the Exploit Rules

Symptom: a legitimate URL with an unusual query string returns 403 Forbidden.

Fix: one of the exploit-blocking conditions matched by accident. Comment out the specific RewriteCond line with a leading #, as the file's own notes suggest.

Back to top

15. Best Practices

If you remember only a few things from this article, remember these:

  • Rename htaccess.txt to .htaccess before turning on URL Rewriting.
  • Put your own rules only inside the "Custom redirects" block, so updates do not erase them.
  • Keep a backup of your live .htaccess before you edit it.
  • On a subfolder install, set RewriteBase to the folder path.
  • Force HTTPS and one canonical host with [R=301,L], and match it with Joomla's Force HTTPS.
  • If the host already compresses assets, comment out the GZIP block.
  • On a server you control, move the rules into the virtual host and set AllowOverride None for speed.
  • Block configuration.php backups, .env, and .git from the web.
  • Use Joomla's Redirects component for editorial redirects; use .htaccess for server-level rules.
  • Treat the exploit-blocking rules as a baseline, not a replacement for updates and a real firewall.
Back to top

16. Quick Reference

ACTIVATE     Rename htaccess.txt → .htaccess
SEF SETTINGS System → Global Configuration → Site
             SEF URLs = Yes, Use URL Rewriting = Yes
SUBFOLDER    Uncomment RewriteBase /subfolder
ROUTE FRONT  RewriteRule .* index.php [L]  (after !-f and !-d)
ROUTE API    RewriteRule .* api/index.php [L]  (paths under /api/)
AUTH FIX     E=HTTP_AUTHORIZATION  keeps the API token alive
EXPLOIT      Blocks base64_encode, <script>, GLOBALS, _REQUEST [F]
FLAGS        [L] stop  [F] 403  [R=301,L] redirect  [QSA] keep query
NOSNIFF      Header always set X-Content-Type-Options "nosniff"
GZIP         Serves .css.gz / .js.gz if present; turn off on double-compress
CACHING      mod_expires: images/fonts 1yr, CSS/JS 1mo
FALLBACK     No mod_rewrite -> RedirectMatch 302 ^/$ /index.php/
ALLOWOVERRIDE Must be All (or rules in vhost) or .htaccess is ignored
CANONICAL    Custom redirects block + [R=301,L]
PROXY        Check X-Forwarded-Proto; Behind Load Balancer = Yes
HARDEN       Optional: no-PHP uploads, TRACE off, HSTS, ErrorDocument
OTHER SERVERS LiteSpeed reads it; Nginx and IIS do not
Back to top

17. Summary

The .htaccess file is the most influential text file in an Apache Joomla site, yet it hides behind a leading dot and ships inactive on purpose. Once you know what each block does, it stops being mysterious:

  • Activation: rename htaccess.txt to .htaccess, then enable URL Rewriting.
  • Routing: the SEF section sends anything that is not a real file or folder to index.php, and /api/ requests to api/index.php.
  • Defence: it blocks common URL exploits, sets the nosniff header, and locks down SVG scripts.
  • Speed: it can serve pre-compressed assets and lets you add cache and HTTPS rules.
  • Portability: it is an Apache feature; LiteSpeed reads it, but Nginx and IIS need their own config.

If your Joomla site throws 404s after you enable clean URLs, breaks its CSS after an upload, or loses your custom rules after an update, the cause is almost always in this one file. A careful read of the rewrite rules, the RewriteBase, and the AllowOverride setting usually finds the problem fast. It is exactly the kind of quiet foundation work that keeps a Joomla site fast, safe, and reliable for years, and it is worth getting right once rather than fighting it on every page.

Back to top
.htaccess in Joomla
Peter Martin
Peter Martin
Joomla Specialist

Peter is a Joomla specialist and a Linux admin for fast, secure and scalable websites.

Frequently Asked Questions

What is the Joomla .htaccess file used for?

The Joomla .htaccess file controls URL rewriting, redirects, security settings and caching. It helps improve SEO, website performance and protection against common attacks.

How do I enable SEO-friendly URLs in Joomla?

Rename htaccess.txt to .htaccess and enable Search Engine Friendly URLs in Joomla Global Configuration. Make sure your server supports Apache's mod_rewrite.

Can I redirect old URLs with Joomla .htaccess?

Yes. You can create permanent (301) redirects in the .htaccess file to preserve SEO value and automatically send visitors to the correct pages.

Is it safe to edit the Joomla .htaccess file?

Yes, provided you create a backup first. A small syntax error can make your website temporarily inaccessible, so always test changes after saving.

Can I force HTTPS using Joomla .htaccess?

Yes. You can redirect all HTTP traffic to HTTPS with a simple rule in the .htaccess file, ensuring secure connections and supporting better SEO.

What are the most useful Joomla .htaccess security settings?

Common settings include blocking directory browsing, preventing access to sensitive files, disabling script execution in upload folders and protecting against common exploits.

Can I use .htaccess on Nginx or IIS web servers?

The .htaccess file works on Apache, LiteSpeed and OpenLiteSpeed web servers because they are compatible with Apache's configuration format. Nginx does not support .htaccess, so the rules must be converted to the Nginx configuration. On IIS, similar functionality is configured in the web.config file.