Php_fastcgi + file_server browse

1. Caddy version (caddy version):


2. How I run Caddy:

systemctl start caddy

a. System environment:

Arch Linux - up-to-date, systemd

b. Command:


c. Service/unit/compose file:

The default Arch Linux caddy.service file, not edited at all.

Description=Caddy web server
Documentation= systemd-networkd-wait-online.service

ExecStartPre=/usr/bin/caddy validate --config /etc/caddy/Caddyfile
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
ExecStopPost=/usr/bin/rm -f /run/caddy/admin.socket

# Do not allow the process to be restarted in a tight loop. If the
# process fails to start, something critical needs to be fixed.

# Use graceful shutdown with a reasonable timeout


# Hardening options
ReadWritePaths=/var/lib/caddy /var/log/caddy /run/caddy


d. My complete Caddyfile or JSON config:

	admin "unix//run/caddy/admin.socket"

http://hoefnix.sys1 {
	root * /srv/http
	file_server browse
	php_fastcgi unix//run/php-fpm/php-fpm.sock
	log {
		output file /var/log/caddy/access-hoefnix.log

3. The problem I’m having:

I’m running caddy2 on a development machine called hoefnix.sys1 in an internal network.

The document root has some sub directories. If a sub directory doesn’t contain an index file (.php of .html), then I want to get a directory listing. But when a subdirectory does have and index file, that index file should be returned.

My problem is very similar to this topic:
Struggling with php_fastcgi and browsing a subdirectory

Except in my case there isn’t a specific sub directory for directory listing. The solution in that topic (with “route”) works well when there is a specific directory for listing. But I want to get a directory listing in every directory, except if that directory contains an index (index.php or index.html).

The following Caddyfile does what I want, except that php files aren’t parsed.

http://hoefnix.sys1 {
	root * /srv/http
	file_server browse
	log {
		output file /var/log/caddy/access-hoefnix.log

So how do I combine “file_server browse” and “php_fastcgi”.

4. Error messages and/or full log output:


5. What I already tried:

When i tried this:

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

Then, logically, php files aren’t parsed anymore.

6. Links to relevant resources:

Please use ``` on the lines before and after your config and logs to use code formatting, to preserve whitespace. It’s quite hard to read your post without it.

In your case, the php_fastcgi directive will not do what you want, because it has built-in try_files logic which is incompatible with what you’re trying to do. That directive is optimized for modern PHP apps which use a single index.php as an entrypoint for routing. See the expanded form to get an understanding of what it does:

To do what you need, you’ll likely want to use a modified version of the expanded form. I’m a bit unclear on your exact requirements (would need to see a tree view of your site root and some example requests and the expected result for each) so I can’t really suggest an exact config without more details.

My apologies for leaving out the backticks. I’ve added them right now.

The tree of my site root look like:

Request with expected results:
/ → /index.php
/static → /static/index.html
/somedata → directory listing of /somedata
/someapp/something.php → /someapp/something.php

These names are just some examples, in reality there are many more.

Thanks for your answer, I will try to understand what’s going on in the expanded form and adapt it to my situation.

I think you might do something like this:

route {
	# Add trailing slash for directory requests
	@canonicalPath {
		file {path}/index.php {path}/index.html
		not path */
	redir @canonicalPath {path}/ 308

	# If the requested file does not exist, try index files
	@indexFiles file {
		try_files {path} {path}/index.php {path}/index.html
		split_path .php
	rewrite @indexFiles {http.matchers.file.relative}

	# Proxy PHP files to the FastCGI responder
	@phpFiles path *.php
	reverse_proxy @phpFiles unix//run/php-fpm/php-fpm.sock {
		transport fastcgi {
			split .php

The key difference is that {path}/index.html is added to the try_files matcher, and index.php is removed as the fallback (which would prevent browsing from working).

Now that I wrote that out, I wonder if this might work the same (haven’t tested it):

php_fastcgi unix//run/php-fpm/php-fpm.sock {
	index {path}/index.html

By default, the “index” is index.php, but I think replacing that {path}/index.html might work :thinking:

Give both of those a shot!

Edit: Actually I don’t think the index override will work because that’ll also affect the redir and the existing {path}/index.php in the try_files.

I think this might do the trick though:

@indexFiles file {
	try_files {path} {path}/index.php {path}/index.html
	split_path .php
rewrite @indexFiles {http.matchers.file.relative}

php_fastcgi unix//run/php-fpm/php-fpm.sock {
	index off

Setting index to off basically gets rid of the built-in redir and rewrite, so you can do your own instead. (I sorta forgot I implemented that :joy:)

1 Like

Rewiring the route does exactly what I want. Thumbs up!

Like you already though, the second solution didn’t work; overriding the index affects the redir to index.php .

The last solution where the index got rebuild, works perfect as well.

For now I will stick to the first solution, because it is the most educational and the flexibility allows me to reorganise some other things.

I really appreciate you fast and extensive help!


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