Help configuring PHP-FPM Status for Caddy2?

1. The problem I’m having:

Minor background:

We have a server where PHP is “falling over” from time to time. I’ve been able to see that something is causing PHP-FPM to spin up child processes until it hits the max_children, at which point PHP stops serving anything to any site until PHP is restarted.

The problem I’m trying to solve:

As all the sites share the same PHP-FPM pool (www), there’s no useful information for me to track down where the problem is stemming from. So I am trying to get the PHP-FPM Status page configured, which I am hoping will give me more information so I can at least see which site hosted on the server and possibly what script might be the root cause of the behaviour.

I can’t seem to work out how to configure that in Caddy2, and must admit that this may be as much “not having a clear understanding of the guts of how this works” as it is about “specifically Caddy’s configuration”. The only things I’ve found relating to this are seemingly for “old Caddy”.

For clarity, I can confirm I have edited /etc/php/8.1/fpm/pool.d/www.conf to enable the line pm.status_path = /status and have restarted PHP-FPM via systemctl restart php8.1-fpm. I have also restarted Caddy via sudo systemctl daemon-reload && systemctl reload caddy && systemctl start caddy

2. Error messages and/or full log output:

No ‘Caddy’ errors, I just get a 404 for https://staging.domain.ext/status?html&full

(URL anonymised, but “correct”)

3. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

  • Installed Ubuntu 22.04LTS
  • Set up UFW
  • Set up Fail2Ban
  • sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
  • curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
  • curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
  • sudo apt update && sudo apt install caddy git

a. System environment:

  • Ubuntu 22.04LTS

b. Command:

It runs itself on boot?

c. Service/unit/compose file:

Not relevant

d. My complete Caddy config:

# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.
#

# Snippets (see: https://caddyserver.com/docs/caddyfile/concepts)
(staticfilecache) {
        @static {
                file
                path *.ico *.css *.js *.gif *.jpg *.jpeg *.webp *.png *.svg *.woff2
        }
        header @static Cache-Control max-age=5184000
}

staging.domain.ext {
        root * /websites/staging
        encode gzip zstd

        log {
                output file /websites/_logs/staging.log
        }

        php_fastcgi /status unix//run/php/php8.1-fpm.sock {
                env SCRIPT_NAME /status
        }

        file_server
}

other.website.url {
        root * /websites/craft4-vca/web
        encode gzip zstd
        php_fastcgi unix//run/php/php8.1-fpm.sock

        file_server
        import staticfilecache

        log {
                output file /websites/_logs/craft4-vca.log
        }
}

Above, the domains are not “real” just for security - but in reality both sites work. The first, staging.domain.ext doesn’t have any PHP scripts but it the one I want to be able to access the FPM Status from. The second isn’t related to this problem but I can confirm that it hosts PHP pages and runs fine.

5. Links to relevant resources:

The problem is Caddy is looking for a file on disk that matches the script you’re trying to run, and it will also only pass requests to fastcgi if the rewritten file path ends with .php

To work around this, you could do this, i.e. manually setting up a proxy with the fastcgi transport to skip all the custom behaviour of the php_fastcgi directive for the /status path specifically:

staging.domain.ext {
	root * /websites/staging
	encode gzip zstd

	log {
		output file /websites/_logs/staging.log
	}

	reverse_proxy /status unix//run/php/php8.1-fpm.sock {
		transport fastcgi
	}

	php_fastcgi unix//run/php/php8.1-fpm.sock
	file_server
}

Thank you - that’s getting me somewhere! Though now I have a “Access denied.” response from it… I’ll see what I can find out about what’s causing that.

[edit]
Nope, I can’t work out why that’s resulting in a 403 error. Would seem to be permissions of some sort but I can not track down why the fastcgi / reverse_proxy is being returned a 403. I did try adding capture_stderr as a flag, but that broke the Caddyfile on that line and dropped the follwing in the jounalctl log Error: adapting config using caddyfile: parsing caddyfile tokens for 'reverse_proxy'.

You need to add it within transport, so like this:

	reverse_proxy /status unix//run/php/php8.1-fpm.sock {
		transport fastcgi {
			capture_stderr
		}
	}

Agh, I’d not put that in braces, thought it must go as a sibling. Ok, that’s validating now - thanks.

Was hoping that I’d see more in the /websites/_logs/staging.log by adding this, but apparently not. And nothing in journalctl -e -u caddy that seems to be of help either. Hmm.

Not sure why I’m getting Access Denied for /status requests.

Interestingly, with the configuration as follows:

staging.website.ext {
        root * /websites/staging
        encode gzip zstd

        log {
                output file /websites/_logs/staging.log
        }

        reverse_proxy /status unix//run/php/php8.1-fpm.sock {
                transport fastcgi {
                        capture_stderr
                }
        }

        php_fastcgi unix//run/php/php8.1-fpm.sock

        file_server
}

accessing https://staging.website.ext/index.html loads as expected, but not accessing https://staging.website.ext/phpinfo.php which is a test script that just contains:

<?php phpinfo(); ?>

That’s being prompted as a download instead of actually showing the page - which would seem to me as though it’s not hooking into PHP-FPM.

Regardless, requesting https://staging.website.ext/status in a browser is a 403 Access denied (which is my core problem atm).

PHP is definitely running and working as there are other declarations for sites in this Caddyfile that use the same php_fastcgi unix//run/php/php8.1-fpm.sock line, and those are running OK.

Turn on the debug global option, see what rewrites are happening, what’s being sent to php-fpm.

I finally have this working - here’s how to get the PHP: Status Page - Manual functionality working in Caddy2, so that you’re able to see more details about what the PHP-FPM processes are actually doing.

SOLUTION:

staging.website.ext {
        root * /websites/staging
        encode gzip zstd

        log {
                output file /websites/_logs/staging.log
        }

        # Handle the /status URL specifically, which has been configured following
        # https://www.php.net/manual/en/fpm.status.php
        reverse_proxy /status unix//run/php/php8.1-fpm.sock {
                transport fastcgi {
                        env SCRIPT_NAME /status
                }
        }

        # Handle normal PHP stuff by passing it to PHP-FMP
        php_fastcgi unix//run/php/php8.1-fpm.sock

        # Serve files that exist straight
        file_server
}
2 Likes

So, turns out capture_stderr was broken

:see_no_evil:

Sorry about that. It’s been fixed in this PR though:

2 Likes

Lol! I did wonder, as nothing seemed to happen, but I also couldn’t work out exactly where it was supposed to output anything from the docs either :slight_smile: (I assumed it’d be in the standard log, but nothing seemed to differ).

PS: Thanks for all the help! Much appreciated.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.