From 500 to 200: A 30-Minute Caddy + PHP-FPM Debug Diary

A single broken wp-config.php file and wrong file ownership turned a fresh Caddy + PHP-FPM 8.2 server into a never-ending 500-error loop. This post shows every diagnostic command we ran, the red-herrings we chased, and the two-line fix that finally brought the site back to life.   Hindi Summary एक टूटा हुआ wp-config.php और गलत फ़ाइल अनुमति ने Caddy + PHP-FPM 8.2 सर्भर को 500 एरर की अनंत लूप में धकेल दिया। इस पोस्ट में हमने जितने भी कमांड चलाए, उनकी पूरी लिस्ट दी है और बताया है कि आख़िरकार 2 कमांड से साइट कैसे ठीक हुई।

The Symptom – 500 on Every Request
Browser showed “Internal Server Error”; Caddy access log only recorded status 500. PHP-FPM service was restarting every 60 seconds, so we suspected a crash-loop.

Step 1 – Check PHP-FPM Status

$ sudo systemctl status php8.2-fpm

Result: active (running) – but only for 60 s, then restart. Take-away: Service restarts hide the real error; we need the last error before shutdown.

Step 2 – Read PHP-FPM Journal

$ sudo journalctl -u php8.2-fpm -b0 --no-pager | tail -50

Result: Clean exits only (NOTICE: exiting, bye-bye!). No crash → error is inside PHP script, not the engine itself.

Step 3 – Enable ClassicPress Debug Log Added to wp-config.php:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

Result: File wp-content/debug.log never created – permission problem suspected.

Step 4 – Run PHP CLI as Web User

$ sudo -u www-data php8.2 -f /var/www/cpress/index.php

Result (GOLD):

PHP Warning:  require_once(/var/www/cpress/wp-config.php):
Failed to open stream: Permission denied ...

Root cause identified: PHP cannot read its own config file.

Step 5 – Inspect File Permissions

$ ls -l /var/www/cpress/wp-config.php

Result: -rw------- 1 root root ......
Issues list: 
1. Owner = root → PHP-FPM (www-data) cannot read. 2. Syntax = half-lines missing quotes/semicolons → would 500 even if readable.

Step 6 – Validate Syntax Offline

$ php -l /var/www/cpress/wp-config.php

Result: PHP Parse error: unexpected end of file ... Confirmed both permissions and syntax are broken.

Step 7 – Fix in One Go

# correct syntax first (nano / vim)
$ sudo nano /var/www/cpress/wp-config.php

# fix ownership & mode
$ sudo chown www-data:www-data /var/www/cpress/wp-config.php
$ sudo chmod 640 /var/www/cpress/wp-config.php

Step 8 – Retest

$ sudo -u www-data php8.2 -f /var/www/cpress/index.php
# no output = success
$ curl -I https://nl.amar.link
# HTTP/2 200

Conclusion The 500 was never Caddy, PHP-FPM, or database credentials—it was a double fault:
1. Corrupt PHP syntax.
2. File unreadable by the web-server user.

Key Takeaways: 
– Always run php -l wp-config.php after manual edits.
– Use sudo -u www-data php index.php to simulate the request environment.
– Set files 640 & directories 755 owned by www-data for hassle-free operation.


IV. Additional Sections FAQ Section
1. Why was PHP-FPM restarting every minute?
Systemd unit had Restart=on-failure. Each 500 was treated as a failure, so systemd killed and respawned the pool.

  1. Could I have seen the error in Caddy’s log?
    Only the 500 status; Caddy does not capture PHP stderr. You need PHP’s own log or CLI test.
  2. Is chmod 777 a quick fix?
    Never. 640 for files and 755 for directories, both owned by www-data, is secure and sufficient.

Call-to-Action Found this checklist useful? Add it to your run-book and never chase ghost 500s again!


V. SEO Requirements Primary Keyword: Caddy 500 error Secondary Keyword: PHP-FPM permission denied
LSI Keywords: Caddyfile php_fastcgi, WordPress 500 internal server error, ClassicPress debug log
Meta Description (160 chars): Diagnose Caddy 500 errors fast: trace PHP-FPM restarts, check file permissions, and fix broken wp-config.php syntax in minutes.