URL rewrite rules
The program has a single entry point, index.php, and routes everything through it. Without URL rewriting, nothing but the home page works.
Docker installs need none of this — the image is already configured.
The three rule sets below are equivalent. They do the rewriting and keep files that should never be public out of reach (logs, database dumps, config,
.env,composer.jsonand so on). Copy the whole block; do not take only the finallocation /.
Nginx
BaoTa: Website → your site → URL rewrite, paste, save.
# Only index.php may execute; every other .php is refused
if ($uri ~* "^/(?!index\.php(/|$)).*\.php(/|$)") { return 404; }
location ~* ^/(runtime|kernel|config|vendor)/ { return 404; }
location ~ /\.(?!well-known) { return 404; }
location ~* \.(log|sql|sqlite|db|db-wal|db-shm|bak|old|save|orig|swp|swo|tmp|ini|lock)$ { return 404; }
location ~* (~|composer\.(json|lock)|package(-lock)?\.json)$ { return 404; }
location / {
try_files $uri $uri/ /index.php?s=$uri&$args;
}Why the first rule is an if rather than a location: in BaoTa's config template, include enable-php-XX.conf comes before the rewrite include, and nginx evaluates regex location blocks in the order they appear, stopping at the first match. A location ~ \.php$ written here would never be reached and would silently do nothing. An if runs earlier, during the rewrite phase, so ordering does not matter.
Apache
Nothing to do. The .htaccess in the project root already handles it — just make sure your upload did not skip it.
Confirm that Apache has mod_rewrite enabled and that AllowOverride is not set to None for the site.
IIS
Windows + IIS needs the URL Rewrite 2.0 module. Put the following in web.config in the site root (or paste it into the rewrite box in BaoTa for Windows):
<rules>
<!-- 1. Program directories -->
<rule name="acg_deny_dir" stopProcessing="true">
<match url="^(runtime|kernel|config|vendor)(/|$)"/>
<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
</rule>
<!-- 2. Dotfiles and dot directories (ACME challenges still allowed) -->
<rule name="acg_deny_dotfile" stopProcessing="true">
<match url="(^|/)\.(?!well-known)"/>
<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
</rule>
<!-- 3. Sensitive extensions -->
<rule name="acg_deny_ext" stopProcessing="true">
<match url="\.(log|sql|sqlite|db|db-wal|db-shm|bak|old|save|orig|swp|swo|tmp|ini|lock)$"/>
<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
</rule>
<!-- 4. Editor backups and dependency manifests -->
<rule name="acg_deny_file" stopProcessing="true">
<match url="(~|composer\.(json|lock)|package(-lock)?\.json)$"/>
<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
</rule>
<!-- 5. Only index.php may execute -->
<rule name="acg_deny_php" stopProcessing="true">
<match url="^(?!index\.php(/|$)).*\.php(/|$)"/>
<action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="Not Found" statusDescription="Not Found"/>
</rule>
<!-- 6. Front controller -->
<rule name="acg_rewrite" stopProcessing="true">
<match url="^(.*)$"/>
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="index.php?s={R:1}" appendQueryString="true"/>
</rule>
</rules>URL Rewrite 1.x does not support
CustomResponse. Replace it with<action type="AbortRequest"/>, at the cost of an empty response body.Do not use
requestFilteringhiddenSegmentsinstead. It matches a segment anywhere in the path, so it would also 404 the/admin/config/...settings pages and plugin assets underassets/vendor/andassets/.../config/.
Running other PHP software in the same web root?
All three rule sets allow only index.php to execute. If you have also dropped phpMyAdmin, adminer or similar into the site root, they will be blocked — move such tools to their own site.
Verifying
Request these; all of them should return 404:
your-domain/composer.json
your-domain/runtime.log
your-domain/config/database.phpThen open any product page. If it loads, rewriting is working.
