PrestaShop .htaccess: rules, redirects and recovery

Understand PrestaShop generated rules, add tested Apache protections and redirects, separate Nginx deployments and recover safely from a broken .htaccess.

mypresta.rocks · Updated 11/01/2026

Check your server topology before changing .htaccess. Preserve PrestaShop’s managed block, add only the rules you need and test recovery as carefully as the change.

What we would do

We would start with the working generated file and a specific problem to solve, rather than paste in a complete replacement. The right route depends on your existing PrestaShop version, hosting layers, modules, payment and ERP integrations, theme, public downloads and stored files. Include each shop domain, subdirectory, language and market in the inventory: a rule that works for the default storefront may fail for another route your customers use.

Make the change on a staging copy that reproduces the relevant server modules, override permissions and proxy policies, with representative data and the actual theme and integrations. Isolate it from live payments, customer emails and fulfilment exports. Rehearse the change, regeneration and recovery before a planned live switch. Keep independent hosting access and a private known-good file ready, agree who can restore it, and apply the reviewed change to the live shop's own configuration rather than upload staging's domain-specific generated block.

Choose the next action from the evidence

What you findRoute to takeWhat decides whether it is ready
A required directive is forbidden on shared hostingAsk the host to implement the policy at a supported level or provide an equivalent control.The host identifies the effective configuration and supplies a way to verify it.
Retired catalogue addresses need frequent changes by shop staffUse an approved redirect-management workflow; reserve server rules for policy that must run before the application.Staff can review source and destination mappings without editing unrelated routing.
A file-access rule affects pages but leaves a static download exposedTrace that file's serving layer with the host before changing the Apache rule again.The public file request is denied by the layer that actually serves it.
Checkout is slow although compression and static expiry already workInvestigate application and integration delays rather than extend cache lifetimes.Request timing identifies the delay without sharing personalised responses between customers.

If you want an assessment of the exposure, the PrestaShop Security Audit & Hardening Report provides a review and remediation plan; implementation is scoped separately.

Confirm which server processes the request

.htaccess is Apache-style per-directory configuration. Apache and compatible servers, including suitable LiteSpeed deployments, can process it. Supported directives and override permissions depend on the server configuration.

DeploymentWhere rules apply
Apache serving the shop.htaccess when AllowOverride or AllowOverrideList permits the directives
Compatible LiteSpeedThe supported Apache-style directives and server-specific configuration
Nginx with PHP-FPMNginx server/location configuration; .htaccess is not read
Nginx proxying to ApacheNginx rules at the proxy; Apache can still read .htaccess for forwarded requests
CDN or another proxy in frontEdge policy plus the actual origin configuration

The Server response header is a clue, not proof of this topology. A proxy can hide or replace it. Ask your host which layer serves PHP, images, downloads and errors, and which layer enforces access rules.

Confirm override permissions and loaded modules before adding directives. See the Apache .htaccess guide, LiteSpeed configuration reference and Nginx proxy documentation for their separate configuration models.

Preserve the generated block and inspect its contents

PrestaShop generates shop-specific rewrite rules through the SEO & URLs settings. In modern versions, open Shop Parameters > Traffic & SEO > SEO & URLs. Keep a private backup before saving settings or editing the file.

# ~~start~~
# PrestaShop-managed content
# ~~end~~

The full marker lines include explanatory comments. Keep the original lines intact. Core normally replaces the managed section and preserves custom text before and after it. Rules inside the section can disappear on regeneration. Rules outside it, including broken ones, can survive.

Place custom rules outside the markers according to their processing order. An early content redirect normally needs to run before the front-controller catch-all, so keeping it outside the block at the end may preserve it without making it effective. Directory/file directives follow their own scope and merging rules.

With missing or malformed markers, the generator can preserve old contents as custom text rather than replacing them as intended. Do not use a damaged file as the basis for a supposedly clean recovery.

What core generates

  • Shop-domain and physical-URI handling, image routes, webservice routes and front-controller dispatch.
  • Existing-resource checks so appropriate real files and directories can be served.
  • A REWRITEBASE environment value, for example through [E=REWRITEBASE:/shop/], derived from the shop's physical URI. This is different from a literal RewriteBase directive.
  • Conditional MultiViews handling, MIME/font rules and error-document routing.
  • Version-dependent security rules. PrestaShop 9 includes directory-listing and sensitive-file protection.
  • Conditional Expires, ETag and compression directives when Apache optimisation is enabled.

Do not assume the generator sets DirectoryIndex or PHP memory/upload limits. Those are separate host settings. Audit the generated output and any existing server-level policy before adding duplicates.

Give each custom rule group an adjacent comment stating its purpose, scope and maintainer. Keep the reason and expected request outcome with your private change record, so a later developer can distinguish an active requirement from an abandoned workaround. Record any module or hosting tool that writes the file as well as the person who edits it.

Add only missing file-access protections

Prevent direct access to secrets, source-control metadata, database dumps and backup copies. Do not store backups in the public document root. An index.php stub or disabled directory listing does not protect a known file URL.

For Apache 2.4 with the required authorisation support and permissions, this is an example named-file rule to adapt to your actual exposure:

<FilesMatch "^(composer\.(json|lock)|package(-lock)?\.json|parameters\.(php|yml)|settings\.inc\.php|\.env.*)$">
    Require all denied
</FilesMatch>

Also deny the Git directory at the serving layer, including access to files beneath it. A root-level example for an Apache .htaccess deployment is:

RedirectMatch 404 (^|/)\.git(?:/|$)

Review other sensitive extensions such as YAML, logs, SQL dumps, templates and backup files. A broad extension ban can also deny intended public attachments, so match the real exposure and test legitimate downloads. PHP configuration files should not be downloadable even if a PHP handler is misconfigured or a backup suffix is added.

Options -Indexes prevents automatic directory listings where permitted. PrestaShop 9 already generates it, so do not add it merely to duplicate the default. A forbidden Options or Require directive can cause an error; use the server's supported configuration rather than adding increasingly permissive exceptions.

Apache 2.2 used different authorisation syntax and is obsolete. Do not mix legacy Order/Deny recipes into a modern configuration without understanding compatibility and inheritance. On Nginx or a proxy serving files directly, apply equivalent protections there too.

A denial on a PHP page does not prove a download is protected

Suppose Nginx serves static files while Apache handles the storefront. You add an Apache deny rule and the shop still works, but that says nothing about a backup served directly by Nginx. On an isolated staging copy, place a harmless dummy file matching the intended protection in an agreed test location, request its exact public URL with GET, and confirm that its contents are not returned. If they are, have the host trace the request and apply the missing protection at the serving layer. Remove the dummy afterwards and test an intended public attachment too.

Set response headers with compatibility checks

Review headers already supplied by the host, proxy, core and security extensions. Avoid conflicting or duplicate values. The following Apache example requires mod_headers and permission to use the directives:

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

nosniff restricts MIME sniffing; it does not prevent every uploaded-file attack. A referrer policy limits outgoing referrer information but is not a substitute for keeping secrets out of URLs.

Evaluate X-Frame-Options: SAMEORIGIN against legitimate embedding and demo needs. A Permissions-Policy denying camera, microphone and geolocation can affect features that use those capabilities. Enable only policies that match the shop.

Roll out Content-Security-Policy using a deliberate inventory, report-only observation and payment/theme tests before enforcement. Check scripts, payment frames, consent, analytics and administrative tools. Do not use the deprecated X-XSS-Protection header as a replacement for current controls.

An IfModule guard skips a block when a module is absent; it does not grant override permission or prove that a security header is active. Check normal, redirect, error and proxied responses.

Configure compression and static caching

Check the actual Content-Encoding and transferred size first. Your host, Apache optimisation, Nginx or CDN may already compress responses. Text compression savings depend on the content and transport; do not expect a fixed percentage for every product page.

If compression is missing in an Apache deployment, a targeted example is:

<IfModule mod_deflate.c>
    <IfModule mod_filter.c>
        AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml
        AddOutputFilterByType DEFLATE application/javascript application/json image/svg+xml
    </IfModule>
</IfModule>

WOFF2 and common image formats are already compressed; do not assume an additional compression filter helps them. Check content types, existing filters, the Vary header and the browser's accepted encodings. Let the serving layer handle compression consistently.

Choose browser-cache lifetimes according to how assets change. A year can suit fingerprinted immutable images/fonts; a month can suit versioned CSS/JavaScript. Unversioned assets need a shorter policy or a reliable invalidation strategy. Replacing an image does not guarantee a new URL. If staff replace a theme stylesheet at the same address and returning customers still see the old layout, inspect the browser's cache use and the asset version, not just the file on disk. Purging the CDN does not purge a fresh copy already held in a customer's browser. Fix the versioning workflow before extending that asset's lifetime.

This conservative example sets expiry only for listed static types and contains no default for other responses:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 day"
    ExpiresByType image/png "access plus 1 day"
    ExpiresByType image/webp "access plus 1 day"
    ExpiresByType font/woff2 "access plus 1 day"
    ExpiresByType text/css "access plus 1 hour"
    ExpiresByType application/javascript "access plus 1 hour"
</IfModule>

ExpiresDefault applies beyond those listed types and can inadvertently affect dynamic content. Review product, cart, checkout, account and payment responses separately, including their Cache-Control and Expires headers. Browser caching and shared full-page caching are separate policies. See the Apache mod_expires reference.

Keep connection reuse and ETag policy consistent with the whole server/CDN deployment. There is no universal benefit to adding a Keep-Alive directive or removing ETags. Existing generated rules may already manage them.

Design narrow redirects and preserve routing

Use a 301 for a permanent move and a 302 for a temporary move when those semantics fit the request. A 410 is a Gone response, not a redirect to a replacement page. Test with a temporary redirect before committing a broadly cached permanent rule.

For example, this shop-relative Apache rule redirects only GET or HEAD requests for a retired editorial path to its replacement. It assumes .htaccess is in the shop root:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(?:GET|HEAD)$
RewriteRule ^old-size-guide/?$ new-size-guide [R=302,L]

Place it before the generated dispatcher rules and test it in the actual base URI. Confirm whether retaining the original query string is appropriate. Internal rewrites can re-enter per-directory processing, so a rule must not catch its own target or front-controller path.

For a worked subdirectory check, suppose the shop is installed at /shop/. Request /shop/old-size-guide and confirm that the example resolves to the intended /shop/new-size-guide, without escaping to the domain root or acquiring a second /shop/ prefix. Repeat with a trailing slash and with a harmless query string, checking whether the query is retained as intended. Also request the destination directly: it must display the replacement rather than return to the retired address. Change the temporary status only after these outcomes pass and the mapping is approved as permanent. A browser may retain a cached permanent redirect after you restore the server file, so file rollback alone may not restore the previous behaviour.

Use native language routing rather than a generic catch-all language-prefix redirect. Any necessary custom route policy must account for the shop subdirectory, actual renamed admin directory, existing resources, APIs, friendly module routes, PHP endpoints, methods and all active languages. Do not redirect payment or form POSTs with an untested content rule.

For content migrations, check the installed module’s support for exact/path/prefix matching, 301/302/410 management and redirect reporting against the SEO Revolution help page. Server rules remain useful for policy that must run before PrestaShop starts.

Check the final destination, status and chain length. A redirect does not guarantee preservation of search rankings. Preserve useful mappings and avoid loops or unnecessarily redirecting every removed page to the homepage.

Recover a broken .htaccess safely

A new 500 after an edit makes that change a good starting point, but other failures can coincide. Read the web-server error log for a syntax error, missing module or forbidden directive.

  1. Use SFTP, SSH or the hosting file manager, enabling hidden-file display if needed. Keep a dated private copy of the broken file for diagnosis.
  2. Temporarily restrict public access at the host/proxy before replacing or removing .htaccess. Removing it can remove access restrictions as well as rewrites.
  3. Restore a known-good backup if you have one. If you must start clean, move the broken file outside the public root and create a fresh writable .htaccess with appropriate ownership and permissions.
  4. Reach the back office through a working route and save the SEO & URLs/friendly-URL settings to regenerate shop-specific rules. If necessary, cycle the Friendly URL setting deliberately and restore its intended final value.
  5. Check that generation succeeded and the file contains the correct domain/base URI and one intact managed block.
  6. Compare the backup and restore only understood custom rules, one group at a time. Retest after each group.
  7. Clear relevant application caches and, if cached failures or redirects persist, the applicable proxy/CDN cache.

Simply regenerating over the broken file may preserve the faulty custom rule outside the markers. A snippet containing only RewriteEngine On enables rewriting but does not restore PrestaShop's image, dispatcher or webservice rules.

If generation fails, check write access, the configured physical URI, Apache rewrite support and override policy. Do not solve permissions by making the whole shop world-writable. If the file changes again after generation, review modules using the htaccess-creation hook and hosting-panel automation.

On pure Nginx/PHP-FPM, repair the Nginx configuration, run nginx -t and reload only after validation. Restoring .htaccess does not fix that server's routes.

Test generated boundaries and critical routes

Use staging to verify marker behaviour before relying on it. Keep a recoverable original and do not introduce deliberately invalid rules into production.

  1. Put harmless labelled comments above and below the existing managed block.
  2. Regenerate from the back office, then compare the result. Both outside comments should remain and the generated section should be replaced.
  3. Regenerate again and check that there is one marker pair and no duplicated custom rule group.
  4. For a recovery rehearsal, retain the broken-file copy privately, regenerate into a fresh file and confirm the required rewrite and access rules return.
  5. Restore approved custom groups incrementally and confirm the result survives another regeneration.

Malformed or duplicate markers deserve manual correction from a known-good baseline. The preservation mechanism is not a parser that validates the intent of custom rules.

AreaTest
StorefrontHomepage, category, product, language variants and canonical redirects
AssetsProduct images, CSS, JavaScript, fonts and intended public attachments
Customer flowGuest/registered cart, authentication, address, carrier, sandbox payment and confirmation
IntegrationsModule routes, API, callbacks and scheduled jobs
SecurityKnown harmless test files in protected paths return a denial, without exposing real secrets
Headers/cacheCompression and static expiry work; personalised pages do not inherit unintended shared caching
RecoveryBack-office access and rollback work with a fresh generated file

Inspect response headers in your browser’s Network panel. For command-line checks, set SHOP_URL to your shop's real origin and use curl --head --location --max-redirs 5 "$SHOP_URL". Test known paths and GET responses as well as HEAD, since routes can behave differently by method. Keep a before-and-after record of each tested path, method, status, destination and relevant response headers, alongside the expected outcome. For a protected dummy file, check the response body as well as the status: its contents must not be returned, and the result must match the intended denial. Keep real secrets and customer data out of the evidence.

File rules complement updates and authentication. For traffic limits see the bot-protection guide; for the wider deployment checks use the security guide and performance guide.

What to ask your developer or agency

  • Which layer handles each affected request, and which differences between staging and production remain untested?
  • What requirement justifies each custom rule, where is it placed, and which generated or host policy would overlap with it?
  • Who can regenerate the file, and which modules, deployment tasks or hosting-panel tools can change it afterwards?
  • Where are the request results, including the affected languages, payment callbacks, downloads and administrator route?
  • Who will watch the planned switch, which failures trigger rollback, and how will that person restore access if the back office is unreachable?

Agree the stop conditions before release. A checkout, callback, legitimate download or administrative route that fails after the change is a reason to pause and restore the approved configuration. A better header score does not outweigh a broken purchase journey.

Questions owners ask

Can I copy the file from another shop?

Use it to understand a rule, not as your generated baseline. Domains, physical URIs, image routes and module requirements can differ. Regenerate for your own shop and transfer only the understood custom change.

What if my only editing access is through the back office?

Arrange working SFTP or hosting file-manager access before the change. A broken web-server configuration can make the editor unreachable, so back-office access alone is not a recovery route.

Should every response have the same headers and cache policy?

Set expectations for each response type and serving layer. A private account page, a static font and a payment callback have different requirements; a scan of the homepage cannot validate them all.

If I find a real exposed backup, is a deny rule enough?

Preserve a private copy and relevant access logs, remove the file from public storage, and purge any cached copies at the CDN or proxy. Recheck the public URL through the normal serving chain. Ask your security maintainer to assess possible access and whether exposed credentials need rotation. Closing the URL does not establish whether the file was already downloaded; follow the breach-response guide if compromise is suspected.

Loading...
Back to top