If your browser starts downloading index.php files instead of rendering the page, the issue is almost always a failure in the integration between the Nginx web server and the PHP-FPM process manager. This behavior occurs because when Nginx fails to forward the script to the FastCGI interpreter, it treats the response as a generic static file and sends default MIME headers (such as application/octet-stream), instructing the browser to download the raw source code.
In this detailed guide, you will find a complete technical roadmap to diagnose and restore proper web server operation in aaPanel, covering preemptive backups, bind conflicts ("Address already in use"), orphan sockets, permission controls, SSL, SELinux, audit logs, and post-fix testing.
| Clinical Symptom | Probable Root Cause | Immediate Impact | Recommended Action |
|---|---|---|---|
| Browser downloads PHP code | PHP-FPM inactive or location ~ \.php block missing | Exposure of credentials and site failure | Validate Unix socket and check nginx -t |
Address already in use error | Orphaned Nginx processes holding ports 80/443 | Nginx fails to start (Downtime) | Identify PID with ss and terminate gracefully |
PHP-FPM status active (exited) | Lost tracking of the real PID by systemd | Critical FastCGI upstream failure | Recreate Unix socket and restart PHP-FPM pool |
| Modal or AJAX fails (Content) | Mixed HTTP calls in page loaded via HTTPS | Requests blocked by browser (Console) | Apply 301 redirect and CSP header |
1. Preemptive backups before changing configurations#
Before executing any corrective commands, killing processes, or editing configuration files on your production aaPanel server, it is mandatory to make backup copies of critical Nginx and PHP-FPM directories.
Run the commands below to generate structured backups with date tagging:
# Create a backup of the Nginx configuration directory
cp -r /www/server/nginx/conf/ /root/nginx-conf-backup-$(date +%Y%m%d)/
# Create a backup of the PHP-FPM 8.0 configuration directory
cp -r /www/server/php/80/etc/ /root/php80-etc-backup-$(date +%Y%m%d)/
Alternatively, you can consolidate and compress both folders into a single compressed security file:
# Generate a tarball of the Nginx and PHP-FPM configurations before changes
tar czf /root/webserver-config-backup-$(date +%Y%m%d).tar.gz /www/server/nginx/conf/ /www/server/php/80/etc/
2. The BIND error "address already in use" and safe process termination#
When you try to restart Nginx and encounter the following error in the logs:
[emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
This indicates that the operating system could not bind Nginx to port 80 or 443 because another process (or orphaned zombie workers from an old instance of Nginx itself) is retaining the network port socket.
The danger of killall -9 without auditing#
Forcing immediate termination with the SIGKILL signal (-9) blindly is a dangerous practice. It prevents Nginx from safely closing active client connections, finalizing ongoing file transfers, cleaning up temporary lock files, and writing pending audit logs to memory.
Follow the safe shutdown and port cleanup protocol:
- Audit active processes cleanly:
# List all processes associated with Nginx
ps aux | grep nginx | grep -v grep
- Send a graceful termination signal (SIGTERM):
# Request orderly termination of processes
killall nginx
# Wait for network buffer deallocation and log writes
sleep 3
- Check if ports 80/443 are still occupied:
# Query active ports and identify the associated PID
ss -lntp | grep -E ':80|:443'
- Apply SIGKILL only as a last resort on stubborn processes:
# Force close if orphaned processes remain stuck
killall -9 nginx 2>/dev/null || true
3. Orphaned unix sockets and "active (exited)" PHP-FPM status in aaPanel#
aaPanel manages the PHP-FPM lifecycle using traditional init scripts located at /etc/init.d/php-fpm-XX (where XX is the PHP version, e.g., 80). During periods of high load or disk failure, systemd or the init script can lose track of the master PHP process PID, showing the confusing active (exited) status in the service manager.
When this happens, the Unix socket file (usually /tmp/php-cgi-80.sock) becomes orphaned (inconsistent) or is deleted, preventing Nginx from forwarding PHP script calls via the FastCGI protocol.
Socket and service diagnosis#
Perform a physical triage of the service and the socket communication channel:
# Inspect the active execution status of PHP-FPM
systemctl status php-fpm-80
# Check if the socket file physically exists in the temporary directory
ls -la /tmp/php-cgi-80.sock
# Query advanced info about owner and write permissions of the socket
stat /tmp/php-cgi-80.sock
Validating process listening#
To ensure the PHP-FPM daemon is running and listening for requests on the correct Unix socket or TCP port, use the ss utility:
# List open ports and Unix sockets by PHP-FPM in the system
ss -lnxp | grep php-cgi
# If the pool is configured via TCP port (e.g. 9000)
ss -lntp | grep php-fpm
4. Nginx configuration and syntax validation#
Never restart Nginx directly after editing virtual host blocks. Typos, obsolete directives, or missing delimiters can take down the entire web server.
Testing syntax locally#
Run the built-in test command to validate the grammar of the configuration files:
# Validate the structural and syntax integrity of Nginx
nginx -t
Dump and search for warnings#
To inspect all active directives applied in the included (include) files for conflicts or warnings, run:
# Export compiled configurations and filter warnings and errors
nginx -T 2>&1 | grep -iE "error|warn"
Recommended PHP configuration block (aaPanel)#
Ensure that the location ~ \.php block in the application's virtual host file (/www/server/panel/vhost/nginx/mysite.com.conf) points correctly to the Unix socket corresponding to the active PHP version:
# FastCGI processing directive for PHP files
location ~ \.php$ {
fastcgi_pass unix:/tmp/php-cgi-80.sock; # Active physical socket
fastcgi_index index.php;
include fastcgi.conf;
# Mapping and buffer parameters
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# Timeout settings to prevent HTTP 504 Gateway Timeout
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
}
5. Detailed web file permission auditing#
Incorrect permissions in the site's root directory (/www/wwwroot/mysite.com/ or /home/usuario/public_html/) prevent the PHP-FPM interpreter from reading and executing files requested by Nginx, resulting in HTTP 403 Forbidden errors or processing failures that can trigger script downloads.
Checking owner and permissions#
Inspect the recursive ownership settings on the application files:
# List permissions and owners of files in the web directory
ls -la /www/wwwroot/mysite.com/
Applying structured fixes#
aaPanel uses the system user and group www to execute web services. Apply the recommended safe permissions in the environment:
# Recursively set the correct owner and group for the directory
chown -R www:www /www/wwwroot/mysite.com/
# Standardize folder read, write, and navigation permission to 755
find /www/wwwroot/mysite.com/ -type d -exec chmod 755 {} \;
# Standardize file read and write permission to 644
find /www/wwwroot/mysite.com/ -type f -exec chmod 644 {} \;
Removing the immutable attribute from .user.ini#
aaPanel creates the .user.ini security file to shield the directory against Directory Traversal attacks. This file is often marked as immutable in the Linux kernel, blocking the application of recursive chown or chmod commands on the directory.
If you receive an Operation not permitted error during the permission correction, temporarily remove the immutable attribute:
# Remove the immutable file protection from .user.ini
chattr -i /www/wwwroot/mysite.com/.user.ini
# Re-apply the previous permission commands and restore the attribute if desired:
# chattr +i /www/wwwroot/mysite.com/.user.ini
6. SSL certificate configuration and HTTPS redirects#
Conflicts from expired certificates, malformed SSL directives, or HTTPS ports not associated with the web server block prevent validation of security handshakes.
Auditing SSL configurations#
Query in which virtual host files port 443 and SSL directives are active:
# Search for active SSL directives in aaPanel virtual hosts
grep -i "ssl" /www/server/panel/vhost/nginx/*.conf
Validating physical certificate via openssl#
Before restarting the server, ensure that the certificate files (fullchain.pem or cert.pem) are not corrupted or expired:
# Check the temporal validity of the configured SSL certificate
openssl x509 -in /www/server/panel/vhost/cert/mysite.com/fullchain.pem -noout -dates
Testing HTTPS communication locally#
Validate the safety protocol response by bypassing external DNS resolutions (firing the command directly against the loopback IP):
# Inspect HTTPS response headers forcing local safety bypass
curl -kI https://localhost/
7. Silent blocks by SELinux#
On Red Hat-based systems (such as Rocky Linux, AlmaLinux, and CentOS), SELinux operates as a Mandatory Access Control (MAC) security mechanism. Even if file permissions (chmod) and owners (chown) are correct in traditional Linux, SELinux can block Nginx from communicating with system files and sockets in the /tmp directory.
Checking SELinux state#
Query the active kernel policing status:
# Check if SELinux is Enforcing, Permissive, or Disabled
getenforce
Tracking policy denials (AVC)#
If SELinux is in Enforcing mode, audit the system log for access denials associated with web services:
# Search for recent AVC denial records associated with Nginx or PHP
sudo ausearch -m avc -ts recent | grep -iE "nginx|php"
Validating security contexts#
Inspect context labels associated with the socket and the application's web directory:
# Verify the security label of the PHP Unix socket
ls -laZ /tmp/php-cgi-80.sock
# Verify context labels of site files
ls -laZ /www/wwwroot/mysite.com/
8. Disk space and inode exhaustion check#
If the server's disk space usage hits 100% or exhausts the inode table (the maximum number of allocatable files in the filesystem), PHP-FPM will fail to write user sessions or store temporary data. Nginx will also fail to generate local request buffers, breaking communication and forcing file downloads or 502/504 errors.
Diagnostics of storage resources#
Perform an inventory of space and inode usage on system partitions:
# Check free disk space on critical partitions
df -h /var/log /tmp /www
# Check free inodes on the aaPanel data partition
df -i /www
Locating inflated logs in aaPanel#
Poorly configured log files or those without active rotation can consume hundreds of gigabytes quickly. Locate giant files in the aaPanel log folder:
# Identify files larger than 100MB in the webserver log tree
find /www/wwwlogs -type f -size +100M -exec ls -lh {} \;
9. Reading Nginx and PHP-FPM logs#
Triage of a systemic incident requires active monitoring of the error log files of both software components.
aaPanel log paths#
- Nginx Logs (Virtualhost):
/www/wwwlogs/mysite.com.error.log(or global log at/var/log/nginx/error.log). - PHP-FPM 8.0 Logs:
/www/server/php/80/var/log/php-fpm.log(or global log at/var/log/php-fpm.log).
Monitoring logs in real time#
Start continuous reading of event logs for service crash warnings:
# Monitor Nginx error logs
tail -n 100 /www/wwwlogs/mysite.com.error.log
# Monitor PHP-FPM execution and worker logs
tail -n 100 /www/server/php/80/var/log/php-fpm.log
Tracking BIND and connection refused errors#
Use grep to map recurring errors in consolidated files:
# Search for port or address already in use failures in Nginx
grep -i "bind" /www/wwwlogs/*.log /var/log/nginx/*.log | tail -20
# Search for Upstream failures and refused socket connections
grep -iE "upstream|connect|permission" /www/wwwlogs/*.log | tail -20
10. Post-fix validation and operation testing#
After applying the fixes and restarting the system daemons, ensure that the services returned to operational stability and that PHP code is being interpreted and not exposed insecurely.
Operational validation steps#
- Confirm active execution status of daemons:
# Active status of Nginx
systemctl status nginx
# Active status of PHP-FPM 8.0
systemctl status php-fpm-80
- Inspect local server HTTP response headers:
# Request headers from local host validating if it returns HTTP 200 OK
curl -I http://localhost/
- Ensure proper interpretation of PHP code:
Insert a basic test file (e.g. index.php containing <?php echo "Webserver OK"; ?>) and execute the call via curl. The response should contain the printed text, and never raw programming syntax:
# Validate that the output is HTML/plain text and does not contain raw PHP tags
curl -s http://localhost/index.php | head -5
Checklist: Nginx downloading PHP (not executing)#
1. Initial diagnosis#
- [ ] Verify if Nginx is running:
systemctl status nginx - [ ] Verify if PHP-FPM is running:
systemctl status php-fpm-80 - [ ] Verify physical socket presence:
ls -la /tmp/php-cgi-80.sock - [ ] Monitor Nginx error logs in real time:
tail -50 /www/wwwlogs/mysite.com.error.log - [ ] Monitor PHP-FPM error logs:
tail -50 /www/server/php/80/var/log/php-fpm.log
2. Address already in use handling#
- [ ] Map active Nginx processes in memory:
ps aux | grep nginx - [ ] Send graceful shutdown signal:
killall nginx(wait 3 seconds) - [ ] Verify if ports 80/443 were deallocated:
ss -lntp | grep -E ":80|:443" - [ ] Force terminate orphans only upon failure:
killall -9 nginx - [ ] Start service cleanly:
systemctl start nginx
3. PHP-FPM recovery and sockets#
- [ ] Check integrity and presence of the Unix socket:
ls -la /tmp/php-cgi-80.sock - [ ] Confirm socket ownership for the correct user:
stat /tmp/php-cgi-80.sock(expected:www:www) - [ ] Restart PHP-FPM process pool:
systemctl restart php-fpm-80 - [ ] Audit active listening sockets in the system:
ss -lnxp | grep php-cgi
4. Syntax and config file validation#
- [ ] Run syntax test of Nginx configurations:
nginx -t - [ ] Dump all upstream and include rules:
nginx -T 2>&1 | grep -iE "error|warn" - [ ] Validate presence of the correct FastCGI PHP block in virtual host directives.
5. SSL and security settings#
- [ ] Audit SSL directives in the site's virtual host block.
- [ ] Verify certificate temporal validity:
openssl x509 -in fullchain.pem -noout -dates - [ ] Add CSP for automatic media request upgrades:
add_header Content-Security-Policy "upgrade-insecure-requests"; - [ ] Replace hardcoded HTTP URLs with relative ones in JavaScript code.
6. Permissions, SELinux, and resource controls#
- [ ] Remove immutable attribute from security files if needed:
chattr -i .user.ini - [ ] Correct root folder ownership recursively:
chown -R www:www /www/wwwroot/mysite.com/ - [ ] Adjust recursive folder (755) and file (644) permissions.
- [ ] Check active SELinux status:
getenforce - [ ] Search for recent SELinux AVC denials in the audit log:
ausearch -m avc -ts recent - [ ] Validate inodes (
df -i) and free disk space (df -h) on the system. - [ ] Monitor inflated log files consuming storage:
find /www/wwwlogs -type f -size +100M
7. Post-fix verification#
- [ ] Make local HTTP requests and verify it returns HTTP 200 OK:
curl -I http://localhost/ - [ ] Test requests against PHP files and validate that the output renders as structured HTML/text.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments