Remove Server header globally

1. Caddy version (caddy version):


2. How I run Caddy:

a. System environment:


b. Command:

caddy run -watch -config /etc/caddy/Caddyfile

c. Service/unit/compose file:

image: caddy:2.5.0
command: caddy run -resume -config /etc/caddy/Caddyfile
- backend
- 80:80
- 443:443
- caddy_data:/etc/caddy/caddy
- ~/certs:/etc/caddy/certs
XDG_CONFIG_HOME: /etc/caddy

d. My complete Caddyfile or JSON config:

(common) {

  header -Server

(error-common) {
  header -Server

:80 {
  import common

  root * /etc/caddy/static
  error * 404
  handle_errors {
    import error-common
    rewrite * /404.html

3. The problem I’m having:

It should delete Server header on every request to severs IP.
Works perfectly fine in localhost when request to
and give this response:

$ curl -I  
HTTP/1.1 404 Not Found
Accept-Ranges: bytes
Content-Length: 17
Content-Type: text/html; charset=utf-8
Etag: "rbi8jsh"
Last-Modified: Sat, 07 May 2022 08:50:16 GMT
Date: Sat, 07 May 2022 12:35:18 GMT

But when I use the same config in get this response with curl:

$ curl -I <IP_V4>
HTTP/1.1 404 Not Found
Server: Caddy
Date: Sat, 07 May 2022 11:56:11 GMT

I’m wondering how is this possible I get 404 response and Server header at the same time!

There’s absolutely no security or privacy advantage to removing the header. We have no plans to make it easier to do so.


Yeah nmap -A doesn’t care.

But that wasn’t the question :smiley:

Are you sure you’re hitting the exact same Caddy instance?

Yes, I am pretty sure.
I get 404 response and server header at the same time I don’t how!!!

Something doesn’t add up. Is what you’ve posted the 100% full picture without any alterations?

Your first curl command gets an Etag and content-length back as if it was serving a file from the file_server, which only appears in your error handler.

Your second curl command doesn’t get any of that, indicating it isn’t even getting into the error handler. But there’s no other file_server specified in your posted config.

I think some other shenanigans are up, and that Caddy is actually working fine.

1 Like

I managed to reproduce the problem partially when the /404.html does not exist in /etc/caddy/static.
So that the “fallback” file_server throws an error (and returns early, I assume), and the headers handler created by the header directive isn’t executed.

However, this does not explain why you get different results when reaching the same server over different interfaces/IPs.
Would you mind rerunning your curl commands? :thinking:
Just to double-check, it has nothing to do with caddy serving two different configs between the tests?

Also, are you running caddy run with the -watch or -resume flag? You mentioned both in your opening post:

Excerpt from caddy run -help:

    	Use saved config, if any (and prefer over --config file)

The saved config is not the Caddyfile, but the internal json config every Config Adapters — Caddy Documentation translates to.
You can print the internal json config by running curl localhost:2019/config/ from within your Docker container.

Would be nice if you could provide some logs and perhaps this json config, to nail this issue further down :upside_down_face:


Thanks that was the case.
I have to focus more on details and sorry for the spam.

1 Like

Thanks @IndeedNotJames – very thoughtful reasoning!

But why does it do that only over the public IP?

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