Caddyfile: having individual sites differ from global options

Let’s say I have a test server and a production server. On the test server, I want all but one site to use local TLS (the special site fetches certs from Let’s Encrypt / ZeroSSL as usual). On the production server, I want all but one site to fetch certs (the special site uses local TLS). How do I do this with Caddy v2.3.0?

Let’s say my test server has the following global options block:

{
	local_certs
}

And my production server has this global options block:

{
	email 	email@example.com
}

How would you have the following site differ from the global options w/r/t TLS?

www.maximumethics.dev {
	root * /srv/maximumethics.dev/www/public
	encode gzip zstd
	file_server browse
}

I used to use tls email@example.com to make an individual site fetch certs instead of using local TLS when that is specified globally, but that seems to have stopped working in Caddy v2.3.0, unless I’m doing something else wrong. I haven’t been able to figure out how to have only one site use local TLS.

Ok, after further experimentation, a simple tls internal does enable local tls for a site on the production server. I’m not sure what I was doing wrong there before. A working configuration looks like this:

# global options
{
	email 	email@example.com
}

# local test page
america.maximumethics.dev {
        root * /srv/maximumethics.dev/test/public/
        import boilerplate
        # https://caddyserver.com/docs/caddyfile/directives/templates
        # can't use default double curly braces b/c Ansible uses them
        templates {
                between (( ))
        }
        tls internal
}

I’m still unable to get a public site working on my test server, however. I’ll make a separate post to dig further into that.

Specifying local_certs globally does just override all sites with the local issuer. The right way to enable it per site is to use tls internal.

So there is now no way to have everything globally default to local certs and have only one site use public cert authorities? This used to work in older versions of Caddy.

I guess I can write it out for every site except one, it just seems to defeat the purpose of global defaults. What is the purpose of the tls email@example.com directive, then? Is it only so that you can have different email addresses for different sites?

It’s the other way around. The default is to use ACME, and if you set local_certs it overrides everything to use the local CA. It’s meant for development. The docs say this:

If it “worked” before then it was a bug, because that was always the intent.

Yep. The email address is entirely optional, but recommended.

1 Like

Here’s a previous thread where @matt suggested the tls email solution, so I find it difficult to believe he considered it a bug then: V2: How to test Caddyfile etc. before deploying to production?

Okay, yeah it might be a bug in v2.3.0

This Caddyfile

{
        local_certs
}

a.example.com {
        tls internal
}

b.example.com {
        tls abc@example.com
}

c.example.com {

}

Adapts to :point_down:

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "a.example.com"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "match": [
                {
                  "host": [
                    "b.example.com"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "match": [
                {
                  "host": [
                    "c.example.com"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "subjects": [
              "a.example.com"
            ],
            "issuers": [
              {
                "module": "internal"
              },
              {
                "module": "internal"
              }
            ]
          },
          {
            "subjects": [
              "b.example.com"
            ],
            "issuers": [
              {
                "module": "internal"
              },
              {
                "email": "abc@example.com",
                "module": "acme"
              }
            ]
          },
          {
            "issuers": [
              {
                "module": "internal"
              }
            ]
          }
        ]
      }
    }
  }
}

You can see that local_certs is prepending an internal issuer on all the policies, even causing a duplicate in the first case. That probably isn’t correct behaviour.

FYI @matt (on the latest on master, this is still a problem, but it now also correctly has the zerossl issuer on the 2nd site)

2 Likes

Thanks, definitely a bug – will be looking into this today.

1 Like

Should be fixed in:

https://github.com/caddyserver/caddy/commit/653a0d3f6bd7b66197abd1e00e366164876a9f2b

2 Likes

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