When one Apache virtual host runs PHP but another downloads .php files, displays their source, or returns 502/503, the failure is usually in one of two places: Apache selected a different virtual host than you expected, or the selected host has no working PHP handler. Fix the selection first, then configure one PHP execution model—preferably PHP-FPM through mod_proxy_fcgi on Apache 2.4.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
The quickest reliable path is to inspect the parsed vhost map with apachectl -S, send a request with the exact Host header, identify the PHP-FPM socket or port, and place a narrowly scoped handler in the vhost that actually receives the request.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
1. Confirm Apache is using the virtual host you edited
PHP directives in a virtual-host block have no effect if the request is being handled by another block. Apache first chooses the best listening IP-and-port combination. For name-based virtual hosts on that listener, it compares the request’s Host header with each ServerName and ServerAlias. If no name matches, Apache uses the first vhost for that address and port as the default.
Read the parsed vhost map
Run:
apachectl -S
The output shows the address and port Apache is listening on, the default vhost, every ServerName and alias, and warnings about duplicate names. Check all of these against the hostname you type in the browser. A duplicate ServerName or ServerAlias can make the first declaration win even though a later file appears to contain the correct PHP settings.
Check both HTTP and HTTPS listeners. A host defined on *:80 is not automatically the same host as one defined on *:443, and an address-specific vhost can take precedence over a wildcard address. Make sure the name is present in the correct TLS vhost as well as the plain-HTTP one if your test uses HTTPS.
Test the listener with an explicit Host header
Testing the IP directly can be misleading because the IP does not identify a name-based vhost. Send the hostname explicitly:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →curl -H "Host: example.test" -i http://127.0.0.1/
Use the actual listener address, port, and hostname for your installation. The response status and headers are useful, but the most important evidence is which vhost log receives the request. For HTTPS, perform the equivalent test against the TLS listener while preserving the intended hostname so certificate and name-based selection are tested together. If DNS still points elsewhere, this test lets you isolate Apache from DNS and the browser cache.
Give each vhost unambiguous logs
Use separate access and error logs for each site, or include %v in the log format so the server name is recorded with each request. Request a known missing path, such as /this-file-should-not-exist, and confirm which log records the 404. Then inspect PHP-related messages in that same vhost’s error log. If the request lands in another site’s log, stop changing PHP directives and correct the name, alias, address, port, or file ordering first.
A browser request can hide this mistake because two sites may share a stylesheet, index page, or redirect. A deliberately unique 404 response or a temporary marker in the intended document root makes the selected vhost obvious. Remove any temporary marker after testing.
2. Identify how PHP is supposed to execute
Apache can hand PHP files to an embedded module (mod_php) or forward them to a separate PHP-FPM process manager. These are different architectures and require different handlers. Do not copy a mod_php recipe into a PHP-FPM installation, or assume that a PHP-FPM socket will work without mod_proxy_fcgi.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #2
- Used Book in Good Condition
| Characteristic | mod_php | PHP-FPM with mod_proxy_fcgi |
|---|---|---|
| Process model | PHP is embedded in Apache workers. | PHP runs in a separate PHP-FPM process manager. |
| Apache MPM compatibility | Typical non-ZTS builds require the prefork MPM. | Works with threaded event or worker MPMs. |
| Operations | PHP lifecycle is tied to Apache workers and restarts. | PHP can be restarted and managed independently, with its own process controls. |
| Handler style | SetHandler application/x-httpd-php for PHP files. |
SetHandler using a proxy:fcgi TCP endpoint or Unix socket. |
| Current deployment guidance | Useful for existing compatible installations. | Preferred by Apache and PHP documentation for modern deployments. |
The preference for PHP-FPM is a project recommendation, not a requirement to migrate every legacy server immediately. First establish which model is installed and which Apache MPM is active.
Check loaded modules and the MPM
Inspect Apache’s loaded-module list using the module-list command supplied by your distribution, or the equivalent output from apachectl. You are looking for the PHP module when using mod_php, or for mod_proxy and mod_proxy_fcgi when using PHP-FPM. Also identify whether Apache is running prefork, worker, or event MPM. A non-thread-safe, non-ZTS mod_php build generally cannot be combined safely with worker or event; PHP-FPM avoids that limitation.
Do not enable both execution models casually. A global mod_php handler can intercept files before the vhost’s intended FPM rule, while a second proxy rule can make troubleshooting ambiguous. Choose one model for the host, remove or disable conflicting mappings, and then verify the effective configuration again.
3. Configure PHP-FPM in the selected virtual host
For Apache 2.4, PHP-FPM through mod_proxy_fcgi is the preferred integration. It provides process isolation, independent PHP restarts, and compatibility with threaded MPMs. The handler must point to the PHP-FPM endpoint used by your pool; do not substitute a path from another machine or distribution.
Use a TCP endpoint
A pool listening on TCP port 9000 can be wired with a real-file guard:
<FilesMatch ".php$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:fcgi://127.0.0.1:9000"
</If>
</FilesMatch>
Replace 127.0.0.1:9000 with the address and port configured in the PHP-FPM pool. The -f condition means Apache forwards only an existing regular file. That matters for front-controller applications: a request such as /index.php/products can execute the real index.php, while a nonexistent /products.php is not blindly sent to PHP.
Ensure the pool is actually listening on that interface and port. A pool bound to a Unix socket will not answer on TCP, and a pool bound only to a different address will produce a gateway failure. If several PHP versions are installed, each pool may use a different port; copy the endpoint from the pool serving this site rather than assuming that 9000 is universal.
Use a Unix socket
Many installations expose PHP-FPM through a Unix socket. The Apache form is:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →<FilesMatch ".php$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost/"
</If>
</FilesMatch>
Use the exact socket path created by your PHP-FPM pool. A socket that does not exist, is owned by an inaccessible user or group, or is blocked by filesystem permissions produces a gateway error rather than PHP output. The trailing fcgi://localhost/ portion is part of Apache’s Unix-socket syntax; retain it while changing the socket path to the one on your host.
When permissions are the problem, check the socket’s owner, group, and mode together with the account used by Apache. Changing permissions broadly can expose the socket to unintended processes; prefer the pool’s intended group relationship. A stale socket after a PHP-FPM restart can also indicate that Apache and the pool are using different configured paths.
Keep the rule in the right scope
Place the FilesMatch and SetHandler in the virtual host that apachectl -S and your logs prove is serving the request. A handler in a different vhost, or only in a global configuration file that is overridden elsewhere, explains why one site executes PHP while another downloads it.
Check path handling and front controllers
Some applications use FallbackResource or rewrite rules to send non-file routes to one front controller. A PHP handler that catches every filename-shaped URL before fallback routing can turn valid application routes into 404 or 500 responses. Restricting the handler with the file-existence test allows the fallback mechanism to process paths that are not real PHP files.
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 matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 114. Configure mod_php only when that is your installed model
With mod_php, Apache must load the PHP module and map files ending in .php to the PHP handler. A typical mapping is:
<FilesMatch ".php$">
SetHandler application/x-httpd-php
</FilesMatch>
The module must actually be loaded; merely adding SetHandler does not install or activate PHP. Confirm the module list, confirm that the PHP build is compatible with the active MPM, and put the mapping in the vhost receiving the request. If Apache runs event or worker MPM with a usual non-ZTS PHP build, use PHP-FPM instead of forcing mod_php into an unsupported combination.
If the module is loaded globally but only one host should execute PHP, check how the distribution’s configuration files apply handlers and whether a later vhost or directory rule changes the content handler. The effective behavior, not the location of the text you edited, is what matters.
5. Match the symptom to the failed layer
| What you see | Most likely cause | How to verify and correct it |
|---|---|---|
| The wrong site’s HTML appears | The hostname did not match, names are duplicated, or the request reached the default vhost. | Run apachectl -S, send an explicit Host header, inspect per-vhost logs, and make names unique. |
| The browser downloads a PHP file or displays PHP source | The selected vhost has no PHP handler, or the required PHP module/proxy module is not loaded. | Confirm the selected vhost, inspect loaded modules, then add either the PHP-FPM SetHandler or the mod_php mapping appropriate to the installation. |
| A PHP URL returns 502 or 503 | PHP-FPM is stopped or unreachable, the socket or port is wrong, or permissions prevent Apache from connecting. | Read the selected vhost’s error log, check the PHP-FPM service and pool endpoint, and correct the configured TCP address or Unix-socket path and permissions. |
| Only one virtual host executes PHP | The handler exists globally or only in another vhost. | Put the handler in the vhost proven to receive the request, then repeat the explicit-Host test and log check. |
| Front-controller routes produce unexpected 404 or 500 errors | A broad PHP handler catches nonexistent paths before FallbackResource or application routing can run. |
Guard the handler with -f and keep routing rules ordered so only real PHP files are sent to FPM. |
6. Verify the complete request path before reloading
A configuration can be syntactically valid yet point at the wrong vhost or an unavailable PHP endpoint. Validate in this order:
- Validate Apache syntax. Run your distribution’s Apache configuration-test command, commonly
apachectl configtest. Fix every reported error before attempting a reload. - Recheck the vhost map. Run
apachectl -Sagain and confirm the intended address, port,ServerName, aliases, default vhost, and absence of duplicate names. - Confirm the PHP endpoint. Compare the
SetHandlervalue with the active PHP-FPM pool’s TCP listener or socket. For mod_php, confirm the module is loaded and the MPM is compatible. - Reload gracefully. Use the service-management command provided by your operating system for a graceful Apache reload. The exact command differs by distribution; do not assume one service name or unit exists everywhere.
- Make a minimal test request. Through the intended hostname, request a small PHP test file and inspect the status, response body, access log, and error log. A successful response proves that this vhost selected a handler; it does not prove every application dependency is healthy.
- Remove diagnostic files. If you used a
phpinfo()script, delete it after testing. It exposes PHP, web-server, path, and environment details that should not be public.
Test a static file as well as PHP. If static content is served by the wrong document root, a successful PHP response may still be coming from an unintended host. Test a nonexistent PHP filename and a normal application route to verify that the real-file guard and fallback behavior both work.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.7. Avoid insecure or overly broad PHP matching
PHP execution should be limited to scripts you intend to run. A greedy ProxyPassMatch or similarly broad regular expression can interpret a path such as /uploads/file.jpg/something.php as PHP, depending on path-info handling. If an attacker can upload content and then append a PHP-looking suffix, that mismatch can become an upload-to-code-execution route.
- Prefer a
FilesMatchrule with an existence check for ordinary script execution. - Keep upload directories outside the document root when practical.
- Do not give upload directories a PHP handler.
- If path info is required, validate the real script path and the path-info portion rather than relying on a greedy proxy pattern.
- After changing rules, test both a legitimate PHP file and an uploaded or static-looking path that must remain non-executable.
Do not treat a 404 as proof that an upload directory is safe: verify that the response is not being forwarded to PHP and that the file cannot be interpreted through an added path segment. Keep the narrow rule in every vhost that exposes user-controlled files, not only in the primary site.
8. A compact decision path
- If the wrong HTML appears, solve vhost matching before touching PHP.
- If the right site appears but PHP is downloaded or exposed as text, install or enable the correct handler in that vhost.
- If the handler is PHP-FPM and the response is 502/503, verify the pool is running, the endpoint is exact, and Apache can access the socket or port.
- If the application uses front-controller routing, retain the real-file guard so nonexistent PHP-looking paths reach the application fallback instead of an unintended backend request.
- If the server is a new Apache 2.4 deployment, choose PHP-FPM with
mod_proxy_fcgiunless a documented legacy requirement calls for a compatible mod_php setup.
Frequently Asked Questions
Why does Apache show my PHP source code instead of executing it?
The selected virtual host is serving the file without a PHP content handler, or the required PHP module and proxy modules are not loaded. Confirm the host with apachectl -S and an explicit Host header, then add either a PHP-FPM SetHandler or the mod_php mapping that matches your installation.
Why does one virtual host run PHP while another downloads it?
Apache may be selecting the default or another duplicate-named vhost, or the PHP handler may exist only in the working host. Compare ServerName, ServerAlias, address and port entries, and per-vhost logs; then place the handler in the vhost that actually receives the request.
What does a 503 or 502 mean after adding PHP-FPM?
Apache reached a proxy handler but could not communicate with PHP-FPM. Check that the pool is running, that the configured TCP port or Unix socket exists, and that Apache can access it. The selected vhost’s error log usually identifies an incorrect endpoint or permission failure.
Should I use mod_php or PHP-FPM?
For modern Apache 2.4 deployments, Apache and PHP documentation prefer PHP-FPM through mod_proxy_fcgi. It supports event and worker MPMs, isolates PHP processes, and allows independent PHP restarts. Keep mod_php for a compatible legacy setup, normally with prefork MPM and a non-thread-safe PHP build.
Why do front-controller URLs return 404 after I configure PHP-FPM?
A broad handler may be forwarding nonexistent .php-looking paths before FallbackResource or rewrite routing can handle them. Wrap the handler in an existence test such as -f %{REQUEST_FILENAME} so only real PHP files are sent to FPM.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Is a PHP handler in the global Apache configuration enough?
Not necessarily. Another vhost may be selected, or a later rule may override the global setting. Prove the receiving vhost with logs and apachectl -S, then verify the effective handler in that vhost.
How can I test a name-based vhost without changing DNS?
Send the intended name in the request’s Host header while connecting to the server’s IP, for example curl -H "Host: example.test" -i http://127.0.0.1/. Use the corresponding TLS listener and hostname when testing HTTPS.
The Bottom Line
Start with routing, not PHP: apachectl -S, an explicit Host header, and distinct vhost logs prove which configuration handled the request. Once that is certain, choose one execution model. On current Apache 2.4 systems, use PHP-FPM with mod_proxy_fcgi, point it at the real pool socket or port, guard the rule with a file-existence check, validate the configuration, reload gracefully, and remove diagnostic scripts. Keep upload paths non-executable and treat every 502, source response, or unexpected 404 as evidence from a specific layer to verify.
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.
Free tools Windows power users keep installed
One-click scans. No signup required.




