php-fpm monitoring for single domain

Ran into this one recently and the solution came out of left field, so I thought I'd throw it out to the internet at large. I've got a server which is running php-fpm and nginx. However it has several websites running on it, each of which has its own php-fpm/pool.d/ profile. We were having a problem with one of the websites, which got a lot more traffic than the others, so we needed a way to monitor its php-fpm performance.

Setting up php monitoring is not hard. There are many guides around the internet. You put the line

pm.status_path = /status

in your fpm pool file, then add a block to your nginx config so that it can only be accessed by certain IP addresses.

        location ~ ^/status {
         access_log off;
         allow 127.0.0.1;    # localhost
         allow 12.23.34.45;   # my remote IP
         deny all;  
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         fastcgi_index index.php;
         include fastcgi_params;
         fastcgi_pass unix:/run/php/php-fpm-mysite.sock;
        }

You access the URL mysite.com/status and all is good.

Things get more complicated when you have a server where each domain has its own fpm pool file. The /status line in this case is just referring to that domain. If you access the mydomain.com/status URL from an external browser, the domain name resolves and nginx picks the correct php-fpm pool file, and you see the stats.

Now consider using curl from localhost.

 # On a server where there's only one pool file, this works. But when there are multiple pool files it doesn't know which one to use
curl http://127.0.0.1/status
# Can we resolve it with a Host header? No
 curl -H "Host: mysite.com" http://127.0.0.1/status
# Resolve looks hopeful, but actually it doesn't work with SSL
 curl --resolve 'mysite.com:443:127.0.0.1' https://127.0.0.1/status
# Maybe --insecure will help? No
 curl --resolve 'mysite.com:443:127.0.0.1' https://127.0.0.1/status --insecure
# Wait, maybe we can connect directly to the socket, and target the website that way! Nope.
curl --unix-socket /var/run/php/php-fpm-mysite.sock http://status/

After exhausting the Internet's wisdom on this, there didn't seem to be a way to get curl to fetch the information. It was needed locally so that it could be incorporated into a monitoring script, so allowing a remote IP to gather the info was not a desirable solution, although rapidly looking like the only option.

Salvation came in the form of a program called cgi-fcgi which talks pure cgi-ese to the fpm socket. Or something like that. (apt install libfcgi-bin or yum install fcgi). Once installed, we can ask it for the information like this:

SCRIPT_NAME=/status SCRIPT_FILENAME=/status REQUEST_METHOD=GET cgi-fcgi -bind -connect /var/run/php/php-fpm-mysite.sock

So, incorporating that into a script we can monitor our website's fpm usage. I guess this could also be used in telegraf, zabbix and other monitoring solutions. And you can have a different status URL for each site/pool on the server.

Leave a Comment