Troubleshooting

Fix 500 Internal Server Error for PHP sites on a VPS

Track down a PHP 500 Internal Server Error on your own Nginx or Apache server: read the right logs, then fix fatal errors, permissions, .htaccess, FPM and SELinux causes.

IntermediateLinux VPS3 min read

A 500 Internal Server Error is a generic "something broke" response. On your own server you have every log, so the real error is never far away. This guide is for VPS setups with Nginx or Apache and PHP-FPM; for shared hosting see the cPanel 500 error guide.

Before you start

  • Root access and the exact URL and time of the error.
  • Reproduce it once while watching the logs.

Watch the logs while you load the page

tail -f /var/log/nginx/error.log /var/log/php8.3-fpm.log

For Apache use /var/log/apache2/error.log (Debian/Ubuntu) or /var/log/httpd/error_log (RHEL). Also check the app's own log (Laravel storage/logs, WordPress debug.log). If PHP logs nothing, enable log_errors = On and catch_workers_output = yes in the FPM pool so worker errors reach the log.

Match the error to a fix

Log showsFix
PHP Fatal error: Uncaught Error ... / Parse errorCode bug or incompatible PHP version; fix or roll back the change
Allowed memory size ... exhaustedRaise memory_limit or fix the code
failed to open stream: Permission deniedPHP user cannot read or write a file; fix ownership
Invalid command 'php_value' (Apache)php_value in .htaccess only works with mod_php; move it to .user.ini
Request exceeded the limit of 10 internal redirectsA rewrite loop in .htaccess or Nginx rules
open_basedir restriction in effectThe script reads outside allowed paths; adjust open_basedir for the site
Primary script unknown (Nginx)Wrong root or SCRIPT_FILENAME; shows as 404 or 500

Fix file permissions

Code should be readable by the PHP-FPM user; only upload, cache and log folders writable:

find /var/www/site -type d -exec chmod 755 {} + && find /var/www/site -type f -exec chmod 644 {} +
chown -R deploy:www-data /var/www/site/storage && chmod -R ug+rwX /var/www/site/storage

Check .htaccess (Apache)

Rename .htaccess temporarily. If the 500 disappears, the problem is inside: an unsupported directive, a missing module (a2enmod rewrite headers), or a rewrite loop. Restore it and remove lines one by one.

Check PHP-FPM and extensions

  • Run php-fpm8.3 -t to validate the configuration.
  • Confirm the site uses the PHP version you expect (fastcgi_pass socket name).
  • Missing extensions show as Call to undefined function or Class not found; install them for that version and restart FPM.

SELinux on AlmaLinux and Rocky

If permissions look right but writes fail, check ausearch -m avc -ts recent. Label writable folders with semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/site/storage(/.*)?' and restorecon -Rv /var/www/site; allow outbound connections (APIs, remote database) with setsebool -P httpd_can_network_connect 1.

Check the fix

  • curl -I https://example.com/failing-page returns 200.
  • No new errors appear in the logs while you browse.

Troubleshooting

  • 500 only after a deploy: missing vendor (run composer install), cached config pointing to old paths, or a new required PHP extension.
  • 500 only for uploads: temp directory not writable or upload_tmp_dir outside open_basedir.
  • Intermittent 500s: often resource-related (memory, max_children) or a flaky external service; correlate with timestamps.

500 error FAQ

Why don't I see the error in the browser?

Production hides PHP errors from visitors on purpose. They are in the logs.

Is a 500 the same as a 502?

No. A 500 is produced by the application or web server; a 502 means the proxy could not get a valid response from PHP-FPM at all.

Can a plugin cause a 500?

Yes, very often. The log names the file, which usually reveals the plugin or module.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.