The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
If an Apache site loads index.php but returns 404 or 403 for CSS, JavaScript, and images, PHP is usually not the root problem. The request is most often reaching the wrong virtual host, mapping to the wrong DocumentRoot, being denied by a <Directory> rule, or failing to resolve the directory index. Fix those layers first; then verify the PHP handler and, if applicable, the PHP-FPM filesystem path.
What “Apache only serves PHP files” actually means
Apache does not have a special mode in which PHP files work and static files are ignored. Each request is processed through several independent decisions:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems| Layer | What Apache must decide | Typical symptom when it is wrong |
|---|---|---|
| Virtual-host selection | Which <VirtualHost> matches the request address, port, and Host header |
The edited configuration has no effect, or another site appears |
| Filesystem mapping | Which file path results from the URL and the selected DocumentRoot |
PHP exists under one tree while CSS and images are looked for under another; static requests return 404 |
| Directory-index resolution | Which file is opened when the URL names a directory such as / |
/index.php works, but / shows a listing or a directory error |
| Static-file authorization | Whether the requested directory and file are allowed by Apache and the operating system | Images, stylesheets, or scripts return 403 |
| PHP execution | Whether a PHP request is handed to mod_php or PHP-FPM | PHP downloads as text, returns 502/503, or fails after the handoff |
A PHP-only proxy rule can be perfectly normal: a rule matching *.php deliberately sends only PHP requests to a PHP handler. CSS, JavaScript, fonts, and images should remain ordinary files served from the selected document root. If those files fail, broadening the PHP rule is not the fix.
Start with the three checks that locate most faults
1. Prove which virtual host received the request
Apache chooses a virtual host using the listening address and port, then the request’s Host header. Within a matching address and port, ServerName and ServerAlias determine the match. If none matches, the first listed virtual host for that address and port can act as the default.
#1 Best Overall
- Check that the browser hostname exactly matches
ServerNameor one of theServerAliasvalues. - Check that the vhost listens on the port the client actually uses, such as
*:80for HTTP or*:443for HTTPS. - Inspect Apache’s active vhost dump (commonly
apachectl -Sor the equivalent command supplied by your distribution) rather than relying only on the file you edited. - Test the same address with the intended
Hostheader when DNS or a reverse proxy is involved. A request sent to an IP address can select a different vhost than a request sent to the site name.
If the wrong vhost is selected, its DocumentRoot, access rules, directory index, and PHP handler explain all of the symptoms. Correct the name, alias, address, port, or enabled-site order before changing application files.
2. Verify the selected DocumentRoot
After choosing a vhost, Apache maps a URL beneath that vhost’s DocumentRoot. For example, with DocumentRoot /srv/www/example/public, a request for /css/site.css maps to /srv/www/example/public/css/site.css. The public directory must contain the complete web tree, not only the PHP entry point.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →- Confirm that the PHP entry file, stylesheets, JavaScript, images, fonts, and any upload or asset directories intended to be public are beneath the same root.
- Check the path letter-for-letter. Linux filesystems are case-sensitive, so
/Images/logo.pngand/images/logo.pngare different requests. - Look for a deployment mistake in which PHP files were copied to the configured root but the asset directory remained in a project, release, or old web-root directory.
- Make sure a container, chroot, or mounted volume exposes the same directory to Apache that you inspected on the host.
3. Check the directory index and PHP handler separately
A request for / is a directory request. Apache’s mod_dir checks the resources named by DirectoryIndex. Its documented default is index.html, so an application whose entry point is index.php should set the PHP file explicitly.
Rank #2
- Used Book in Good Condition
PHP execution is a second decision. The server needs either an in-process mod_php handler or a PHP-FPM handoff through mod_proxy and mod_proxy_fcgi. A working DirectoryIndex does not prove that the PHP runtime is reachable, and a working PHP handler does not prove that static paths are correct.
Use a vhost whose root and access scope describe the same public tree
A minimal PHP-FPM-style layout looks like this:
<VirtualHost *:80>
ServerName example.test
ServerAlias www.example.test
DocumentRoot /srv/www/example/public
<Directory /srv/www/example/public>
Require all granted
DirectoryIndex index.php index.html
</Directory>
# Use the PHP-FPM socket or TCP endpoint supplied by your system.
# The filesystem path must be the real path to the PHP files.
ProxyPassMatch ^/(.*.php(/.*)?)$ fcgi://127.0.0.1:9000/srv/www/example/public/$1
</VirtualHost>
The example is a configuration shape, not a copy-and-paste endpoint for every operating system. Socket names, package names, enabled modules, and PHP versions differ. The important relationships are:
DocumentRootpoints to the directory containing the entire public site.- The
<Directory>block names that exact same directory and grants the access the site requires. DirectoryIndexincludes the application’s real entry file.- The PHP-FPM mapping handles PHP requests while leaving non-PHP files to normal filesystem mapping.
- The path after the FastCGI host and port is a filesystem path visible to FPM, not a URL alias or a virtual-host name.
Keep the PHP handler in the vhost that owns the site. A rule in another vhost, an unmatched include, or a broad global rule can make troubleshooting misleading because PHP may execute through a configuration different from the one serving static files.
How Apache resolves the two requests that expose this problem
Requesting /index.php
- Apache matches the address, port, and
Hostheader to a vhost. - It joins the URL path to that vhost’s
DocumentRoot. - Because the path ends in
.php, a PHP handler may intercept it. - With PHP-FPM, Apache passes the script’s real filesystem path to the FPM socket or TCP endpoint.
- FPM interprets the script and returns the generated response through Apache.
Requesting /
- The same vhost and document-root selection occurs.
- The resulting path is a directory, so
mod_dirsearches the configuredDirectoryIndexlist. - If
index.phpis listed and exists, Apache internally resolves the request to that file and invokes the PHP handler. - If no index resource exists and directory listing is enabled, a listing may appear. If listing is disabled, Apache returns a directory-forbidden response instead.
This explains why a direct PHP URL can work while the bare site URL does not: the first request tests PHP mapping, whereas the second also tests directory-index configuration.
A disciplined troubleshooting sequence
- Validate syntax before reloading. Run
apachectl configtest, or the equivalent configuration-check command for your platform. Resolve every syntax error before attempting a reload. - Dump the active vhosts. Use the platform’s vhost inspection command and confirm the hostname, address, port, enabled configuration file, and default ordering. Do not assume a file on disk is active.
- Compare the request hostname with the vhost names. Verify the browser’s hostname, the
Hostheader used by any proxy,ServerName, and everyServerAlias. - Inspect
DocumentRoot. Confirm that the directory contains the exact CSS, JavaScript, image, and PHP paths requested by the page. - Compare the
<Directory>path. The authorization block should refer to the same public directory, or to a deliberate parent/child rule that you understand. Check thatRequire all grantedor the site’s intended authorization is present. - Check URL casing and generated paths. Use the browser’s network panel or access log to identify the exact failing URL. Correct references such as
/css/app.cssversus a file stored asCSS/app.css. - Set the directory index. Add
DirectoryIndex index.php index.htmlwhen the application usesindex.php, and ensure that file exists in the directory named byDocumentRoot. - Identify the PHP model. Determine whether the site uses mod_php or PHP-FPM. For FPM, verify that
mod_proxyandmod_proxy_fcgiare available and that the configured socket or TCP endpoint is running. - For FPM, verify the script path. Compare the path in
ProxyPassMatchwith the path visible to the FPM process. Apache aliases and virtual-host namespaces are not understood by FPM; FPM needs the actual filesystem location. In containers, that location must be valid in the FPM container as well as in Apache’s environment. - Reload only after checks pass. Then reproduce one failing request and inspect Apache’s access and error logs together with the PHP-FPM log when FPM is used.
Use the response status to choose the next check
| Response or behavior | Most useful next checks |
|---|---|
| 404 Not Found for CSS, images, or JavaScript | Selected vhost, DocumentRoot, exact file existence, URL casing, and any rewrite or alias that changes the path |
| 403 Forbidden for static files or directories | <Directory> authorization, parent-directory traversal permissions, filesystem permissions, and whether the requested path is intentionally blocked |
Directory listing at / |
Whether index.php exists in the root and whether DirectoryIndex includes it; do not treat the listing as evidence that PHP is broken |
| PHP source downloads or appears as text | Whether a PHP handler is configured for this vhost and whether the relevant module or FPM mapping is enabled |
| 502 or 503 on PHP requests | FPM process state, socket or port, Apache proxy modules, network reachability, and the FastCGI path |
| PHP error after a successful handoff | The application’s runtime error, its dependencies, environment variables, and the PHP-FPM log; static-file mapping may already be correct |
PHP handler choices: mod_php and PHP-FPM
Both models can execute PHP, but they differ operationally. The current PHP manual recommends PHP-FPM with Apache’s mod_proxy_fcgi for modern deployments.
| Concern | mod_php | PHP-FPM through mod_proxy_fcgi |
|---|---|---|
| Process model | PHP runs inside Apache worker processes. | A separate PHP-FPM service interprets scripts; Apache proxies the request. |
| Apache MPM compatibility | Must fit the Apache process model and module combination used by the installation; legacy setups commonly depend on a prefork-style arrangement. | Works with Apache’s proxy modules and keeps PHP outside Apache’s worker process model. |
| Connection setup | No FastCGI socket or TCP endpoint is needed. | Uses a Unix socket or TCP endpoint, which must be running and reachable. |
| Restart boundary | Changing PHP generally involves the Apache process lifecycle. | Apache and FPM can be restarted or tuned as separate services. |
| Path handling | Apache resolves the script directly. | The FastCGI mapping must pass FPM the exact real filesystem path; aliases alone are insufficient. |
| Deployment direction | Common in older installations. | The recommended approach for modern Apache/PHP deployments. |
Do not switch handler models merely because static files fail. A wrong document root or authorization rule affects both models. Change the handler only when PHP itself is not being interpreted, the selected vhost has no handler, or the existing runtime is incompatible with the deployment.
Rank #4
Common configuration mistakes and their precise fixes
The file you edited is not enabled
Apache may be loading a distribution-generated site, a different include, or an earlier vhost. The active vhost dump and configuration check reveal this faster than repeatedly editing the same file. Enable or include the intended configuration using your operating system’s normal site-management process, then validate and reload.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
PHP and assets are in different trees
A project may contain /var/www/example/index.php while its built assets are under /var/www/example/public. If DocumentRoot points to the first directory, Apache can find the PHP file but not the files beneath the public tree. Point the vhost at the real public directory and place the complete browser-facing tree there.
The <Directory> block does not match the root
Changing DocumentRoot without changing the corresponding authorization block can leave the new directory inaccessible. Keep the two paths aligned and check parent-directory traversal permissions. A syntactically valid configuration can still produce 403 responses.
Best Value
- Used Book in Good Condition
DirectoryIndex was never changed from its default
Direct navigation to /index.php bypasses the need for directory-index discovery. Add the application’s actual index file to the vhost or an intentionally inherited directory context. Do not “fix” a listing by enabling unrelated rewrites before confirming index resolution.
A PHP-only proxy rule was broadened to catch everything
Sending images and stylesheets through FPM adds needless work and can create incorrect path handling. Keep the pattern limited to PHP requests. Static failures should be corrected in the root, file layout, access rules, URL casing, or aliases.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallThe FPM endpoint is alive but receives the wrong path
FPM interprets the PHP file path Apache supplies; it does not know Apache aliases, URL prefixes, or vhost namespaces. A 502 can indicate a dead socket or port, while a PHP “file not found” error can indicate a path mismatch even when FPM is running. Compare the proxy mapping with the path mounted inside the FPM process, especially in containerized deployments.
Verification checklist after the fix
- The intended hostname selects the intended vhost on the correct port.
- The active vhost’s
DocumentRootcontains the PHP entry point and every public asset requested by the page. - The matching
<Directory>block authorizes that directory and its required files. DirectoryIndexincludesindex.phpwhen the application uses it.- Static URLs use the exact case and directory names present on disk.
- PHP is handled by the selected runtime rather than downloaded or returned as source.
- For FPM, Apache can reach the configured socket or port and the passed filesystem path exists from FPM’s perspective.
- A clean configuration test succeeds before reload.
- Access, Apache error, and FPM logs agree with the observed status code for a fresh request.
Once these checks pass, a page that loads PHP, CSS, JavaScript, and images is no longer relying on accidental vhost ordering or a coincidental file location; each request is being resolved by the configuration intended for that site.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

