Reverse_proxy all URLs to always same php file

I have a single index.php file run by php-fpm. I want all requests to /api/* paths to be handed by that single file only - at all times.

This does not work, what am I doing wrong?

@api {
    path /api/*
}
reverse_proxy @api php:9000 {
    rewrite /app/public/php/index.php?{query}&p={path}
    transport fastcgi
}

So, basically, I don’t need to allow for any other php files, at any other directory levels.

php is a docker container configured in Docker Compose.
php and caddy are two separate containers.

I’m trying to open .../api/ in my browser, and it says “access denied”. Here’s the Caddy log for that request (DEBUG level):

For some reason unknown to me, logs from php-fpm say something about /srv:

Access to the script '/srv' has been denied

Is this information enough to identify the problem?

Solved. All I had to do is manually set three environment variables: DOCUMENT_ROOT, SCRIPT_NAME, and SCRIPT_FILENAME.

{$WEBSITE_HOST:bot.127.0.0.1.nip.io} {
	@api {
		path /api/*
	}

	reverse_proxy @api php:9000 {
	    transport fastcgi {
	        # An example of env values for FastCGI:
	        # https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
	        # Also see: https://github.com/nginx/nginx/blob/master/conf/fastcgi_params
	        env DOCUMENT_ROOT /app/public/php
	        env SCRIPT_NAME /index.php
	        env SCRIPT_FILENAME /app/public/php/index.php
	    }
	}
}
1 Like

FYI, you can shorten your config to:

reverse_proxy /api/* php:9000 {
    rewrite /app/public/php/index.php?{query}&p={path}
    transport fastcgi
}

i.e. use the inline path matcher

Thanks for sharing your solution!!

Thanks @matt .

Btw, in the env REQUEST_URI {http.request.uri} instruction, is there a way to manipulate the {http.request.uri} piece? For instance, I’d like to strip the /api prefix before setting it to the environment variable.

Yeah, you want the uri directive (specifically, uri strip_prefix)

I think you actually do want to use php_fastcgi here.

root * /app/public
php_fastcgi php:9000
file_server

That’s what it does by default, i.e. send requests to index.php if the request isn’t to a file that exists on disk.

Your php app should read from REQUEST_URI to get the original request path. That’s how all major PHP frameworks work.

1 Like