Caddy: fastcgi.index works only with http.root

Created on 25 Jul 2017  路  8Comments  路  Source: caddyserver/caddy

1. What version of Caddy are you using (caddy -version)?

Caddy 0.10.4

2. What are you trying to do?

Running caddy with php-fpm. I'm going to isolate some services, so there is no shared caddy root.

3. What is your entire Caddyfile?

https://sub.example.com {
    fastcgi / /srv/sub/php-fpm.sock php {
        root /srv/sub/php-fpm-root
    }
    tls [email protected]
}

4. How did you run Caddy (give the full command and describe the execution environment)?

Via systemd. I'm going to put it into a jail, so don't worry about the root user and group (and don't try this at home). Here is my caddy.service:

[Unit]
Description=Caddy
After=network.target

[Service]
User=root
Group=root
Environment=CADDYPATH=/srv/caddy/.caddy
ExecStart=/usr/bin/caddy -log stdout -agree -conf /srv/caddy/caddyfile -ca https://acme-staging.api.letsencrypt.org/directory
ExecReload=/usr/bin/kill -USR1 $MAINPID
LimitNOFILE=1048576
LimitNPROC=64

[Install]
WantedBy=multi-user.target

5. Please paste any relevant HTTP request(s) here.

curl -k "https://sub.example.com/index.php"
curl -k "https://sub.example.com"

6. What did you expect to see?

Hello PHP world!
Hello PHP world!

7. What did you see instead (give full error messages and/or log)?

Hello PHP world!
404 Not Found

8. How can someone who is starting from scratch reproduce the bug as minimally as possible?

  • set up php-fpm with socket
  • set up caddy with the above caddyfile
  • make sure that listen.owner and listen.group in php-fpm.conf match

Apparently caddy doesn't find the index.php file.

I can solve the problem by moving the root directive to the server block:

https://sub.example.com {
    root /srv/sub/php-fpm-root
    fastcgi / /srv/sub/php-fpm.sock php
    tls [email protected]
}
$ curl -k "https://sub.example.com/index.php"
Hello PHP world!
$ curl -k "https://sub.example.com"
Hello PHP world!

It seems that caddy uses http.root instead of fastcgi.root to look for the fastcgi.index file. I'm not sure if this behaviour is intended. If it is, I suggest mentioning it in the docs.

feature request

Most helpful comment

Hi @casipw Thanks for the detailed issue. I can recreate this issue.

The code seems to be correctly assigning the root but it is not matching the index file as you have stated, however I'm not sure if we want this to happen as the docs suggest that in some instances the fastcgi server will be running on another server.

Perhaps @mholt could provide some clarity on what should happen in this situation, so either the code can be fixed or the documentation updated.

In the meantime I think you can do what you want by structuring your caddyfile in a differnt way.

If you explain what it is specifically you are trying to isolate we can make suggestions.

All 8 comments

Hi @casipw Thanks for the detailed issue. I can recreate this issue.

The code seems to be correctly assigning the root but it is not matching the index file as you have stated, however I'm not sure if we want this to happen as the docs suggest that in some instances the fastcgi server will be running on another server.

Perhaps @mholt could provide some clarity on what should happen in this situation, so either the code can be fixed or the documentation updated.

In the meantime I think you can do what you want by structuring your caddyfile in a differnt way.

If you explain what it is specifically you are trying to isolate we can make suggestions.

I'm heading out the door but I'll ping @abiosoft for his thoughts on it too!

@tobya I'm putting caddy and some services (one of it being a php-fpm instance) into Firejails. Caddy and each service have their own chroot-jail (like /srv/caddy, /srv/sub). I saw no need for a http.root directive, because that directory would conceptually belong to caddy and not to php-fpm. Some custom fastcgi services might not even need a root directory.

If I understand the code correctly, caddy tries to match an index file using http.root and fails because http.root is not defined. This matching is essential if there are multiple possible index filenames. However I wonder how it should work if Caddy and FastCGI were on different servers, as the docs suggest. (Also with my current http.root solution, caddy needs read access to /srv/sub.)

After sleeping a night to think about it, things seem clearer to me.

  • My PHP application does not need any static assets. (Otherwise I had seen the need for a http.root to put them there.)

  • If the URL ends with .php, caddy doesn't check for the existence of that file and thus doesn't need read access to any php files.

  • If the URL doesn't end with .php, caddy looks for an index file ("matching"). Therefor it needs read access to the directory with the php files.

  • Using http.root instead of fastcgi.root for the matching is the right choice. If caddy and php-fpm run on different servers (or jails, containers), one should mount the php directory (fastcgi.root on the php-fpm server) to the caddy server (mountpoint http.root on the caddy server).

I see three possible solutions here:

  • Docs: Mention in the docs that caddy needs access to the fastcgi root (via http.root) in order to match an index file.

  • Caddy code: Omit matching (and the need for read access to the fastcgi root) if there is exactly one fastcgi.index filename.

  • Admin: Use a rewrite rule to rewrite https://sub.example.com to https://sub.example.com/index.php. Now caddy doesn't need access to the php files any more.

https://sub.example.com {
    rewrite {
        r ^/$
        to /index.php
    }
    fastcgi / /srv/sub/php-fpm.sock php {
        root /srv/sub/php-fpm-root
    }
    tls [email protected]
}

This is a bit tricky, the root fileserver needs to be aware there are other places to look for files.
And I do not think it is limited to index files, any file that is not in http.root will give a 404, even if it is present in fastcgi.root.

Is it possible to define what fastcgi.root is really for then?

So it isn't possible to have different fastcgi root?

I tried to "proxy" from https://github.com/lucaslorentz/caddy-docker-proxy via fastcgi to php backend. So there is no http.root, just fastcgi.root

Caddy v2's redesigned middleware architecture solves this problem; URL rewriting including matching index files can be done outside of the reverse proxy (which is the module which serves fastcgi now). Since it's solved in v2 I'm going to close this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mschneider82 picture mschneider82  路  3Comments

wayneashleyberry picture wayneashleyberry  路  3Comments

SteffenDE picture SteffenDE  路  3Comments

lorddaedra picture lorddaedra  路  3Comments

mikolysz picture mikolysz  路  3Comments