Disabling server header not working

1. Output of caddy version:


2. How I run Caddy:

Inside docker.

a. System environment:

Distributor ID:	Debian
Description:	Debian GNU/Linux 10 (buster)
Release:	10
Codename:	buster

b. Command:

caddy run -config /config/Caddyfile

c. Service/unit/compose file:


d. My complete Caddy config:

  dev.some.com {
    route {
      header              cache-control "no-cache"
      header /favicon.ico cache-control "public, max-age=604800"
      header /js/*        cache-control "public, max-age=604800"
      header /css/*       cache-control "public, max-age=604800"
      header /fonts/*     cache-control "public, max-age=604800"
      header /api*        cache-control "no-cache"
    reverse_proxy /api* {
      to srv+http://.....
      header_down -server
      header_down -cache-control
    reverse_proxy {
      to srv+http://.....
      header_down -server
      header_down -cache-control
      header_down x-frame-options "DENY"

3. The problem I’m having:

I would like to prevent shipping the server header at all.

4. Error messages and/or full log output:

curl -I https://dev.some.com
HTTP/2 200 
accept-ranges: bytes
cache-control: no-cache
content-type: text/html
date: Tue, 23 Aug 2022 19:44:03 GMT
etag: "63035ed5-1bff"
last-modified: Mon, 22 Aug 2022 10:47:49 GMT
server: Caddy
x-frame-options: DENY
content-length: 7167

5. What I already tried:

header -server
header_down -server

I thought just setting header -server inside route should be enough - seems it isn’t.
But neither is setting header_down on the reverse_proxy.
Now I am a little lost what else to try.

6. Links to relevant resources:

That seems to be working actually.

But first, I strongly recommend upgrading to 2.5.2, because srv+http:// has been deprecated. You want dynamic upstreams from here: reverseproxy: Dynamic upstreams (with support for SRV and A/AAAA lookups) by mholt · Pull Request #4470 · caddyserver/caddy · GitHub (Caddyfile docs: reverse_proxy (Caddyfile directive) — Caddy Documentation

header_down has to be used inside reverse_proxy. This is because it specifically manipulates headers going “down” to the client from the backend. So it will remove any Server header set by the backend.

However, Caddy still sets its own Server header too, which is what you’re seeing in your curl command.

Put header -server in your config outside of reverse_proxy and it should remove the header completely, including the one Caddy sets. It probably doesn’t in the route because routes affect the handler ordering. (I’m not sure why you have them all in a route in the first place?)

1 Like

Nice. I will look into the migrating. What’s the major difference?
I couldn’t find that yet.

Gotcha. I guess that the missing header outside is the culprit then.

:+1: will try that.

I don’t have to?
I don’t remember whether there was a particular reason.

Thanks for the quick help!

The old way only looks at the first SRV record, and it acts like a single upstream for health checking, even though there are multiple. It’s basically a hacky way to get it working, but it held us over until we had a better way. It also wasn’t extensible. But now we have native support for truly dynamic upstreams!

I dunno, depends on what your goals are. But it’s not obvious to me from looking at it. I usually only add things to the config once I determine they’re needed, rather than assuming they will be.

Good luck!

1 Like

Please make sure to use -- double dashes for CLI arguments, we’re planning a change in a future version which will mean single dashes will no longer be supported.

Also FYI, the default container’s command will run Caddy with your Caddyfile as long as you mount the Caddyfile at /etc/caddy/Caddyfile. I suggest you do that instead.

There’s no reason at all to remove this header. It doesn’t reveal any information that clients couldn’t otherwise glean from your server (e.g. looking at TLS handshake patterns, etc). It doesn’t protect you in any way.


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