Struggling with php_fastcgi and browsing a subdirectory

1. Caddy version (caddy version):

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

a. System environment:

ubuntu lts lxd container

b. Command:

n/a

c. Service/unit/compose file:

standard systemd file

d. My complete Caddyfile or JSON config:

example.com {
        root * /srv/www/public_html
        php_fastcgi unix//run/php/php-fpm.sock
        file_server
        file_server /stuff/* browse
}

3. The problem I’m having:

Basically I want the subdirectory “stuff/” to be browsable. Otherwise either serve the file directly, or process it with PHP, if it’s a php file.

Instead going do //example.com/stuff/ shows me //example.com/index.php

4. Error messages and/or full log output:

n/a

5. What I already tried:

tried using handler blocks, but that got confusing fast.

6. Links to relevant resources:

You’ll need to either use a route or handle block to solve this.

Basically, the problem is that the php_fastcgi directive is sorted above file_server, according to this pre-determined order.

You could either do this:

route {
    file_server /stuff/* browse
    php_fastcgi unix//run/php/php-fpm.sock
    file_server
}

Or this:

handle /stuff/* {
    file_server browse
}

handle {
    php_fastcgi unix//run/php/php-fpm.sock
    file_server
}

The route directive overrides the sorting, so you’re telling Caddy to always handle /stuff/* first. The handle directive instead makes each block mutually exclusive from eachother.

Both solutions are valid, but I would personally lean towards using handle because it’s more flexible if you need to make additional changes.

1 Like

I’ve tried the handle directive before and could not get it to work. Direct files were served and php files were processed, but going to //example.com/stuff/ still showed //example.com/index.php. This is the config I tried:

{
        root * /srv/www/public_html

        handle /stuff/* {
                file_server browse
                php_fastcgi unix//run/php/php-fpm.sock
        }

        handle {
                php_fastcgi unix//run/php/php-fpm.sock
                file_server
        }
}

route seems to work well though, thank you. Since you think that handle would be the better way, any thoughts on why the above config didn’t work?

Just for posterity, this is the route config that works:

{
        root * /srv/www/public_html

        route {
                file_server /stuff/ browse
                php_fastcgi unix//run/php/php-fpm.sock
                file_server
        }
}

The handle you tried doesn’t work because it doesn’t override the directive order (and route does), so you still end up with this (effectively):

        handle /stuff/* {
                php_fastcgi unix//run/php/php-fpm.sock
                file_server browse
        }

You can run caddy adapt --pretty to see the underlying config that the Caddyfile generates.

So maybe I misunderstood, but do you mean that you also have PHP files you want to execute in /files/*? Because if not, just remove the php_fastcgi line from that handle block and it should work fine.

Gotcha. Is it a rule that caddy processes directives bottom up?

Yes, basically, if there is a php file anywhere in that tree, I want it processed. I guess part of the problem is that php_fastcgi wraps up a lot of different functionality, including a bunch of redirect stuff. I just want the file processed without all the extras.

No, Caddy executes the HTTP handlers top to bottom, in the order they appear in the JSON config.

The Caddyfile is just a config adapter which generates a JSON config. It’s basically a UX layer, to make Caddy easier to use. And part of that, is having a default sort order so that the Caddyfile doesn’t need to be as strict about the order the user writes things in their config.

Fair enough, then route is what makes the most sense for you.

And yes, php_fastcgi is basically a shortcut for all this:

1 Like

No, the default directive order is described by the link Francis posted above. Caddyfile Directives — Caddy Documentation

Thank you both. A lot to unpack in that php_fastcgi expanded form.

It’s simple if you break it down by the 3 comments explaining it:

  1. Trailing slashes
  2. Index files
  3. Proxy to FastCGI responder

So just take what you need from that.

Thanks.

The split, split_path parts gave me pause, since you don’t have to do that stuff in Apache.

The split_path stuff is this:

Say you get a request like /index.php/foo/bar. By default, the server doesn’t have a way to know that index.php is actually a file, and not a directory.

So split_path .php basically means "in the path, find where there might be a .php in it, then split that in two parts (i.e. /index.php and /foo/bar), where the left side is the script to run, and the right side is the bit that goes in the PATH_INFO fastcgi variable. Modern PHP apps will look at PATH_INFO to do routing.

In Apache, that’s typically handled by a rewrite rule in an .htaccess in the root of your project. In Nginx and Caddy, those types of rules are done directly in the server config.

1 Like

Yeah. Reading the nginx docs actually helped me figure this out. Thank you.

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