Porting Drupal apache config to Caddyfile

1. The problem I’m having:

I was with @dunglas today and we were trying to port Drupal apache config to Caddyfile. I’m having a problem with a regex used to deny access to certain files, while allowing certain paths.

What we have in the apache config:

<FilesMatch "\.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config|yarn\.lock|package\.json)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$">

Paths that matches the regex:

core/modules/system.module
core/modules/system.yml
.toto
.haccess
.plop
Entries
composer.json
package.json

Path that do not match the regex:

.well-known/change-password

As expected the problem here is the (?!well-known) part for porting that to Caddyfile.

What I tried to do in Caddyfile is:

	@protectedFilesRegexp {
		not path /.well-known*
		path_regexp \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^\/(\..*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config|yarn\.lock|package\.json)$|^\/#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$
	}
	error @protectedFilesRegexp 403

All the paths that are supposed to match, match, but it also matches https://localhost/.well-known/change-password, I’m getting a 403 when accessing that url.

3. Caddy version:

I’m using caddy through frankenphp and it’s frankenphp

root@044e65faae38:/opt/drupal# frankenphp --version
FrankenPHP v1.1.2 PHP 8.3.4 Caddy v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=

4. How I installed and ran Caddy:

I used the docker stack from Caddyfile by theodoreb · Pull Request #25 · dunglas/frankenphp-drupal · GitHub

d. My complete Caddy config:

# Adapted from https://caddy.community/t/caddyfile-for-drupal-10/21607/5
{
	{$CADDY_GLOBAL_OPTIONS}

	frankenphp {
		{$FRANKENPHP_CONFIG}
	}

	# https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
	order php_server before file_server
	order php before file_server
}

{$CADDY_EXTRA_CONFIG}

{$SERVER_NAME:localhost} {
	root * web/
	encode zstd br gzip

	@hiddenFilesRegexp path_regexp (^|/)\.
	error @hiddenFilesRegexp 403

	@hiddenPhpFilesRegexp path_regexp \..*/.*\.php$
	error @hiddenPhpFilesRegexp 403

	@notFoundPhpFiles path_regexp /vendor/.*\.php$
	error @notFoundPhpFiles 404

	@notFoundPhpFilesRegexp path_regexp ^/sites/[^/]+/files/.*\.php$
	error @notFoundPhpFilesRegexp 404

	@privateDirRegexp path_regexp ^/sites/.*/private/
	error @privateDirRegexp 403

	@protectedFilesRegexp {
		not path /.well-known*
		path_regexp \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^\/(\..*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config|yarn\.lock|package\.json)$|^\/#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$
	}
	error @protectedFilesRegexp 403

	@static {
		file
		path *.avif *.css *.eot *.gif *.gz *.ico *.jpg *.jpeg *.js *.otf *.pdf *.png *.svg *.ttf *.webp *.woff *.woff2
	}
	header @static Cache-Control "max-age=31536000,public,immutable"

	{$CADDY_SERVER_EXTRA_DIRECTIVES}

	php_server
}```

Earlier in my config there is a rule to disallow all the .* matches. After removing that it works as expected

1 Like