Caddy with PHP-FPM - File not found

Hey all!

I’ve a little problem I can’t seem to fix.

I’m trying to set up caddy with PHP-FPM on a centOS 7 machine.

I’ve got both Caddy and PHP-FPM running as systemd services, and they work just fine separately, but whenever I navigate to the URL that is supposed to serve a php file, I get a “File not found.” message. In the caddy log, the following message appears:

+0100 [ERROR 0 /] Primary script unknown

I’ve scoured the internet for fixes, here’s what I tried:

  • There is an entry for something like this in the github README:

  • I have caddy 0.9.5

  • both services run under www-data

  • I’ve chown & chmod all files either service could need (by following the instructions on github, using the same services file, with a different path for caddy (/bin/caddy instead of /usr/local/bin/caddy), but I changed the chmod commands accordingly.

  • I made sure php-fpm and caddy are run as the same user (www-data)

  • The php-fpm master does still run under root (see HTOP screenshot)

  • All folders (/var/www ; /etc/caddy; …) and files contained within those are owned by this user and/or his group.

  • I tried starting both manually as root user, to no avail

  • I tried using a unix socket, instead of 127.0.0.1:9000

I’m not sure what else I should try, so any help would be appreciated!

Here’s my config files:

Caddyfile (/etc/caddy ; I did change the URL, but the structure is the exact same)

www.domain.com {
	root /var/www
	gzip
	minify
}

ivc.domain.com {
	root /var/www/ivc
	gzip
	minify
	fastcgi / 127.0.0.1:9000 php {
		root /var/www
	}
}

The php-fpm.conf (/etc)

[global]
pid = /var/run/php-fpm/php-fpm.pid
error_log = /var/log/php-fpm/error.log ;this doesn't contain anything useful
daemonize = yes
include=/etc/php-fpm.d/*.conf

And the pool config for php-fpm (/etc/php-fpm.d)

[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log

; I tried with and without these, didn't work
;chroot = /var/www
;chdir = /var/www

php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache

And a htop screenshot:

PS: I’m fairly new at this (I’ve only used an AMP stack before), so forgive me for any ommisions or wrong terminology.

Thanks in advance!

What happens if you remove the root /var/www from the fastcgi block?

It makes no difference, I forgot to mention that I tried a couple of different values (/var/www/ivc) as well as just deleting it there already.

The only two things that I can think of that would cause that particular issue is if Caddy is sending the wrong script filename or the files are inaccessible by php-fpm. All your config looks OK to me. Would you mind showing the output of ls -al in the /var/www/ivc directory?

Sure, here it is:

# ls -al
total 4
dr-xr-xr-x. 2 www-data www-data 22 Jan 26 16:52 .
drwxr-xr-x. 5 root     root     58 Jan 26 15:03 ..
-r-xr-xr-x. 1 www-data www-data 31 Jan 25 22:00 index.php

Is that index file chmod 555? Seems a little odd with no write permissions anywhere and world execute, but should have enough permissions to be readable by php-fpm.

I know you said you’ve already tried removing this, but having the root /var/www subdirective in the fastcgi block will definitely contribute or outright cause this issue. The Caddy fastcgi directive will concatenate the root and the request path to produce the SCRIPT_FILENAME CGI variable. That means that a request to / with an index .php specified (by the php preset) will concat /var/www and /index.php. You may or may not have a file at /var/www/index.php, but I’m sure it’s definitely not desired behaviour.

The last thing I can think of is to double check removing the root subdirective from the Caddyfile and running systemctl stop caddy, then systemctl start caddy to be 100% sure the correct SCRIPT_FILENAME is being set. I know nginx has a way to debug which CGI variables are being sent, but I can’t think of a way to get Caddy to do the same off the top of my head.

Yeah, I did remove the root directive after your last comment just do double check.

I also played around with the file’s permissions to no avail.

I did notice, however, that the default caddy.service starts uses this:

ExecStart=/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp

I tried changing the root parameter to /var/www (and daemon-reload, etc), as that’s apparently the default root, but I assume that gets overridden in the caddyfile anyway.

It’s still the same error though.

Either way, thanks for the help already, I appreciate it :smile:

You’re correct, that will get overridden on a per-site basis by your Caddyfile.

To attempt to get a better grasp on your issue, I spun up a Centos 7 server on Vultr. From stock install, I enacted the following general procedure:

  • Added a non-root user
  • Assigned hostname adrastos and made DNS-available at adrastos.whitestrake.net
  • Created /etc/caddy, /etc/ssl/caddy dirs and chown'd/chmod'd appropriately
  • Created /var/www/adrastos.whitestrake.net/index.php with contents:
    <?php phpinfo() ?>
  • Set the following webroot ownership and permissions:
    sudo chown -R $(whoami):www-data /var/www
    sudo find /var/www -type f -exec chmod 640 {} \;
    sudo find /var/www -type d -exec chmod 750 {} \;
  • Intalled php-fpm from yum (version 5.4.16 currently)
  • Edited /etc/php-fpm.d/www.conf to set user and group to www-data
  • Installed Caddy via https://getcaddy.com (version 0.9.5 currently)
  • Set Caddy binding capabilities
    sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy
  • curl'd https://raw.githubusercontent.com/mholt/caddy/master/dist/init/linux-systemd/caddy.service and installed as normal
  • Opened required ports for Caddy
    sudo firewall-cmd --permanent --zone=public --add-service={http,https}
    sudo firewall-cmd --reload
  • Ran the required software
    sudo systemctl start caddy
    sudo systemctl start php-fpm

The Caddyfile at /etc/caddy/Caddyfile:

adrastos.whitestrake.net {
    root /var/www/adrastos.whitestrake.net
    fastcgi / 127.0.0.1:9000 php
    log stdout
    errors stderr
}

The result is visible https://adrastos.whitestrake.net (edit: since removed). While it was fun to wander outside my own neat little Unbuntu+Docker “comfort zone”, unfortunately I wasn’t able to recreate your issue under the above circumstances. Let me know if you spot any specific differences between my method and yours that you think might be worth investigating as a possible cause.

P.S. I note that Centos 7 comes with systemd version 219, where the wiki seems quite adamant in its requirement for >= 229. For what reason, I’m unsure - as demonstrated my implementation seems to have been successful with no modification in this regard.

Edit: Added better way to deal with firewalld entries for HTTP/HTTPS

Edit 2: Took down the demonstration website

1 Like

Thanks a lot for your help, I’m just going to start over, this time following your directions.

I am going to get another php version though, as I need some of the language features of PHP 7.

Anyway, thanks again for all your help :slight_smile:

No worries - I’ve got a hunch that this is the place you’ll want to look to get php7.0 running on Centos 7, as I don’t believe it’s packaged natively.

Best of luck!

I know this is an old topic however just reading it my first mind goes to your systemd config file. This could be restricting the access to /var and thus the files are not found. If you want further details please reply with your systemd config file, or otherwise use the default one provided inside the Caddy repo.

I’ve always used the systemd file from the repo, but your explanation does make sense.

I’ve since then switched to Ubuntu 16.04 (for various other reasons, I did get php to work after more fiddling on centos, though I couldn’t tell you what ultimately did it.), and everything worked first time.

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