First Identify the Source of the 404
A 404 status can originate at different levels. The web server may fail to pass the request to index.php, or Yii2 may receive the request but fail to find the route.
| Symptom | Cause | Where to Look |
|---|---|---|
| Default Apache or Nginx 404 page | The rewrite rule did not run, or the document root is incorrect | VirtualHost, server block, .htaccess, try_files |
| Yii2-styled error page | The request reached the application, but the route was not found | urlManager, rules, controllers, and actions |
/index.php/site/index works, but /site/index does not | The pretty URL is not being passed to the entry point | mod_rewrite or try_files |
Even the URL containing index.php does not work | The site root or PHP handling is incorrect | document root, PHP-FPM, index.php |
Start with these two requests:
curl -I https://example.test/index.php/site/index
curl -I https://example.test/site/index
If the first URL opens but the second returns a server-generated 404, the problem occurs before Yii2. If both requests reach Yii2, check the application routes.
Check enablePrettyUrl and showScriptName
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [],
],
],
enablePrettyUrl enables parsing of pretty URLs, while showScriptName = false removes index.php from generated links. This setting does not configure Apache or Nginx: the request must still reach the entry point.
During troubleshooting, leaverulesempty and test the standard/site/indexroute. This makes it easier to distinguish a rewrite problem from an error in a custom rule.
Check the Document Root
In Yii2 Advanced, the public directory of the frontend application must be frontend/web, not the project root or the frontend directory. This directory contains index.php, assets, and the .htaccess file.
/var/www/project/frontend/web/index.php
For the Basic Template, the public directory is web:
/var/www/project/web/index.php
If the document root points to frontend/web, the rewrite rules must apply to that exact directory. The server may not read a file located in the repository root at all.
Apache: mod_rewrite and .htaccess
Check the Rewrite Module
apachectl -M | grep rewrite
The output must include rewrite_module. After changing modules or the VirtualHost configuration, reload the Apache configuration.
Allow .htaccess Processing
When AllowOverride None is set, Apache ignores rules from .htaccess. For the public directory, you can configure:
<Directory /var/www/project/frontend/web>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Then validate the configuration:
apachectl configtest
systemctl reload apache2
Use Minimal Rules
The frontend/web/.htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
Existing files and directories are served directly, while all other requests are routed to Yii2. Do not add RewriteBase unless necessary: an incorrect value often breaks an application installed in a subdirectory.
Verify the VirtualHost
<VirtualHost *:80>
ServerName example.test
DocumentRoot /var/www/project/frontend/web
<Directory /var/www/project/frontend/web>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Make sure the domain is served by this exact VirtualHost. An error in ServerName, the hosts file, or the virtual host order may route the request to the default configuration.
Nginx: location and try_files
Nginx does not read .htaccess. Routing must be configured in the active server block:
server {
listen 80;
server_name example.test;
root /var/www/project/frontend/web;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ .php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
}
try_files first looks for an existing file or directory, then passes the request to index.php. $query_string preserves GET parameters.
A common mistake is using try_files $uri $uri/ =404;. In that case, a nonexistent path ends with a server-generated 404 and never reaches Yii2. Another possible cause is that the correct location / block is placed in a different server block from the one serving the domain.
nginx -t
systemctl reload nginx
If even /index.php/site/index does not open, check the PHP-FPM socket or address, access permissions, and the SCRIPT_FILENAME value.
When baseUrl Is Required
baseUrl is required when the application is published under a subdirectory rather than at the domain root, for example at https://example.test/app. When the application is installed on a dedicated domain, Yii2 usually detects the base path automatically.
'components' => [
'request' => [
'baseUrl' => '/app',
],
],
The value must match the external URL prefix, not the filesystem path. Do not specify /var/www/project/frontend/web. An incorrect baseUrl causes incorrect links, assets, and redirects, but it does not replace rewrite configuration.
For a subdirectory installation, align the external prefix, the web server rule, and request.baseUrl. When using a reverse proxy, verify that the prefix is passed to the application.
Troubleshooting Sequence
- Open
/index.php/site/index. If it does not work, fix the document root and PHP handling. - Open an existing static file from
frontend/webto confirm that the public directory is correct. - Enable Pretty URLs, disable the script name, and temporarily remove custom rules.
- Check
/site/index. A server-generated 404 points to Apache or Nginx, while a Yii 404 page points to a routing problem. - For Apache, check the module,
AllowOverride, the location of.htaccess, and the active VirtualHost. - For Nginx, check
root,location /,try_files, and the activeserverblock. - Restore custom rules after the standard route works.
- For a subdirectory installation, compare the external URL with
baseUrl.
Cache and Configuration Reloading
After changes, Apache or Nginx must reload its configuration. PHP-FPM usually does not need to be restarted for rewrite changes, but it may be necessary after modifying the pool or PHP settings.
To rule out application cache issues, use the project's standard console command:
php yii cache/flush-all
Run it from the directory containing the console yii file. It requires a configured console application. Also test the URL with curl or clear the browser cache, especially after permanent redirects.
Clearing the cache does not fix an incorrect document root or enable rewrite. If the 404 is generated by the web server itself, clearing the Yii cache will not change the result.
Checklist
DocumentRootorrootpoints tofrontend/weborweb.- The URL containing
index.phpopens the standard Yii2 route. enablePrettyUrlis enabled, andshowScriptNameis disabled.- In Apache,
mod_rewriteis loaded,.htaccessis allowed, and the rules are located in the public directory. - Nginx uses
try_files $uri $uri/ /index.php?$query_string;. - The domain is served by the expected VirtualHost or
serverblock. - Existing files are served directly, while all other requests reach
index.php. baseUrlis configured only when there is an actual URL prefix.- After changes, the configuration has been validated and the web server has been reloaded.
- Custom rules are restored after
/site/indexhas been tested successfully.