Handle_errors not working

1. Caddy version (caddy version):

v2.4.3

2. How I run Caddy:

via systemd

a. System environment:

Vanilla Caddy on Arch Linux

b. Command:

Paste command here.

c. Service/unit/compose file:

[Unit]
Description=Caddy
After=network.target

[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddyfile or JSON config:

{
	admin off
	email redacted@redacted.com
	key_type rsa4096
}

(standards) {
	php_fastcgi unix//run/php-fpm/php-fpm.sock
	encode zstd gzip
	file_server
	header {
		Referrer-Policy "same-origin"
		Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; style-src 'self'; media-src 'self'; font-src 'self'; img-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';"
		Permissions-Policy "interest-cohort=(), geolocation=(), microphone=(), camera=()"
		Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
		Cache-Control "max-age=31536000"
		X-XSS-Protection "1; mode=block"
		X-Content-Type-Options "nosniff"
		X-Frame-Options "deny"
		-Last-Modified
		-Server
	}
	tls {
		protocols tls1.2 tls1.3
	}
}

domain.com, www.domain.com {
	root * /var/www/domain
	import standards
	handle_errors {
		redir https://google.com
	}
}

3. The problem I’m having:

I’m using google.com because nothing I set under handle_errors seems to work; I wanted something very definitive and radical for proof.

Expected Behavior: (domain)/thisdoesnotexist should redirect to Google.
Observed Behavior: (domain)/thisdoesnotexist remains in the URL bar.

4. Error messages and/or full log output:

There are no errors output.

5. What I already tried:

I’ve tried everything I can think of, including:

handle_errors {
		@404 expression {http.error.status_code} == 404
		redir @404 https://google.com
		root * /var/www/domain
		file_server
}

The ultimate desired behavior I seek, is any 404 should redirect to (domain)/ and not stay at (domain)/someurlthatdoesnotexist

I always “systemctl daemon-reload” and “systemctl restart caddy” when making edits to the Caddyfile.

6. Links to relevant resources:

The php_fastcgi directive has built-in try_files logic that rewrites all requests to files that don’t exist on disk to index.php. Modern PHP apps work by using index.php as the entrypoint for doing their own routing. If your PHP app doesn’t work this way, then you’ll need to configure php_fastcgi to turn off the index.php rewrite. See the docs:

2 Likes

Thank you! So it looks like I need to set up my own internal rewrite, then use redir to handle errors:

(standards) {
    php_fastcgi unix//run/php-fpm/php-fpm.sock {
	index off
    }
}

domain.com, www.domain.com {
    root * /var/www/domain
    import standards
    handle / {
        rewrite * /index.php
    }
    handle_errors {
        redir https://domain.com
    }
}
1 Like

@francislavoie My solution is very close, but still not right, can you help?

(standards) {
    php_fastcgi unix//run/php-fpm/php-fpm.sock {
        index off
    }
    handle / {
        rewrite / /index.php
    }
}

The rewrite works for https://domain.com/index.php (and the benefit of the rewrite is that it keeps /index.php hidden from visitors.

But not for subfolders, e.g. https://domain.com/hello/ doesn’t see https://domain.com/hello/index.php and is treated as a 404 error. I don’t want to have to write rules for every subfolder I might have on a website. What am I missing?

EDIT: Got it!

Okay, so the whole thing needs to look like this:

(standards) {
    php_fastcgi unix//run/php-fpm/php-fpm.sock {
        index off
    }
    handle / {
        rewrite / /index.php
    }
    try_files {path} {path}/index.php
}

domain.com, www.domain.com {
    root * /var/www/domain
    import standards
    handle_errors {
        redir https://domain.com
    }
}
2 Likes

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