Log_skip directive has no effect?

1. The problem I’m having:

I am trying to use log_skip to suppress logging of requests originating from specific public IP addresses, but the directive seems to have no effect (i.e., requets from those IPs are still logged). I know I could filter the logs after the fact, but I really want to not log these in the first place.

2. Error messages and/or full log output:

No error messages per se, but request handling logs are still emitted even though log_skip should have stopped them. An example of such a log (where all addresses and FQDNs have been anonymized):

{"level":"info","ts":1775811061.6357963,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"198.18.0.1","remote_port":"40986","client_ip":"192.18.0.1","proto":"HTTP/1.1","method":"GET","host":"example.com","uri":"/ping.php","headers":{"User-Agent":["curl/7.88.1"],"Accept":["*/*"]}},"bytes_read":0,"user_id":"","duration":0.000325783,"size":0,"status":308,"resp_headers":{"Server":["Caddy"],"Connection":["close"],"Location":["https://example.com/ping.php"],"Content-Type":[]}}

3. Caddy version:

v2.11.2 h1:iOlpsSiSKqEW+SIXrcZsZ/NO74SzB/ycqqvAIEfIm64=

4. How I installed and ran Caddy:

Installed from the Debian package then replaced /usr/bin/caddy with a custom one built with xcaddy (as the online build server was non-functional at that time) including modules caddy-l4 and caddy-events-exec (neither of which is used in this specific case).
Run through systemd, reconfigured through commande “caddy --config /etc/caddy/Caddyfile reload.”

a. System environment:

Debian Trixie 13.4 on an ARM64 machine

b. Command:

N/A (caddy is run by Debian through systemd)

c. Service/unit/compose file:

N/A (service file is the one provided by the Debian package)

d. My complete Caddy config:

NOTE: despite the request to not redact addresses and domains, I cannot disclose those, and have replaced them with values suitable for documentation.

{
	default_bind 198.18.1.0:443 [2001:0002::1:0]:443
	log {
		output file /var/log/caddy/access.log {
			mode 0666
			roll_interval 24h
			roll_at 00:00
		}
		format json {
		}
		include http.log.access
	}
	# auto_https disable_redirects
	email x@example.com
	cert_issuer acme
}

example.com {
	log
	@our_own_ips remote_ip 198.18.0.1/32 2001:0002::1/128
	log_skip @our_own_ips
	reverse_proxy 198.18.2.0:443 {
		transport http {
			tls
			tls_server_name example.com
			proxy_protocol v2
			keepalive off
		}
	}
}

subdomain2.example.com {
	log
	redir https://example.com/subdomain2{uri} 308
}

subdomain1.example.com subdomain3.example.com {
	respond "OK" 200
}

5. Links to relevant resources:

Weird, that should work. I don’t see any obvious problem with your config. Try removing the matcher from log_skip or matching on some paths, does that work? If so then for some reason the remote_ip matcher is not matching the IPs you think it should. Otherwise, there’s maybe a bug that will need to be tracked down.

I’ve tried with path_regexp instead of remote_ip, with the same (lack of) effect.

I also checked that the remote_ip in the config matched the remote_ip (and client_ip) field in the log line which I wanted skipped but was not:

# grep -F 198.18.0.1 -m 1 /etc/caddy/Caddyfile <(tac /var/log/caddy/access.log | grep -F 198.18.0.1 -m 1)
/etc/caddy/Caddyfile:	@our_own_ip_addresses remote_ip 198.18.0.1/32 2001:0002::1/128
/dev/fd/63:{"level":"info","ts":1775896741.6245382,"logger":"http.log.access","msg":"handled request","request":{"remote_ip":"198.18.0.1","remote_port":"33312","client_ip":"198.18.0.1","proto":"HTTP/1.1","method":"GET","host":"example.com","uri":"/ping.php","headers":{"Accept":["*/*"],"User-Agent":["curl/7.88.1"]}},"bytes_read":0,"user_id":"","duration":0.000155455,"size":0,"status":308,"resp_headers":{"Connection":["close"],"Location":["https://example.com/ping.php"],"Content-Type":[],"Server":["Caddy"]}}
# _

Time for debugging, then, I guess.

Added level debug and commented out the include line in the log block (thus logging everything) then reloaded the config. I could see the debug log was enabled (there are “debug” level lines), but the “ping” requests do not cause any debug logs.

What can I do next?

Oh sorry, I wasn’t looking carefully enough. The logs you’re seeing are HTTP->HTTPS redirects, so they’re not going through your handlers and it’s not hitting log_skip because the handlers are only for the HTTPS server.

I think the problem is this line:

This is causing all access logs to be grabbed, ignoring whether log is enabled in a site or not. Remove that line and it should only log the stuff you want.