Caddy tls cert for domain certs

I am trying to use caddy to proxy an app that has an internal domain name (foo.internal) that isn’t reachable by the internet. Then it also has an external domain name (foo.external) that is reachable from the internet.

I have the tls cert/key for the foo.internal provided by internal pki. I would like to use that. But the caddy docs state if tls is provided, then automatic https is disabled. So can I expect caddy to get the cert for public facing foo.external or no?

And secondly, I am trying to use a template for this. The testing site is only reachable internally. So the external fqdn is set to foo.internal. Caddy fails to start with an error stating duplicate site key. Is it possible to disable this check? I do not have the option for logic checks in my templates to avoid outputting it twice

Hi @gordon, welcome to the Caddy community.

You will have to configure them separately. The below example also shows how to handle the things Automatic HTTPS usually handles for you (HTTP->S upgrade and specifying scheme so it doesn’t serve over the default port 2015).

external.example.com {
  # regular Automatic HTTPS
}

http://internal.example.com,
https://internal.example.com {
  tls cert key
  redir 301 {
    if {scheme} is HTTP
    / https://internal.example.com{uri}
  }
}

Strictly speaking, yes you could disable this startup check in the source code and build your own version of Caddy. You’d only be asking for trouble, though - how is Caddy meant to know which of the two versions of the site to use when a client connects and asks for it?

Thanks.

My template was currently looking like:

http://internal.example.com,
http://external.example.com,
https://internal.example.com,
https://external.example.com  {
  tls cert key
  redir 301 {
    if {scheme} is HTTP
    / https://internal.example.com{uri}
  }
}

Where I had hoped I could make it use the provided internal cert and fetch the external cert. If that were the case, then it would have been nice to silence the duplicated name error since it isn’t actually ambiguous in the case where they are both on the same block

i.e.

http://internal.example.com,
http://internal.example.com,
https://internal.example.com,
https://internal.example.com {
  tls cert key
  redir 301 {
    if {scheme} is HTTP
    / https://internal.example.com{uri}
  }
}
 

There’s a few issues with programming Caddy to behave in that manner.

First and foremost is the fact that for Caddy to have that behaviour would clash with the apparent configuration of the Caddyfile. Based on what you’ve written, it pretty naturally follows that you’re applying the tls cert key to all hostnames above (including the external hostnames).

To single out some of the hostnames you’ve (fairly explicitly) told Caddy to use your own cert/key for, and use Automatic HTTPS on them instead, would seem perhaps fairly arbitrary, and make it impossible or at least take a pretty arcane configuration to actually tell Caddy to use your cert/key on all the hosts.

Also, there’s the question of just how Caddy would figure out which hostnames to apply Automatic HTTPS to as opposed to using the TLS configuration you provided. Caddy doesn’t have incredibly sophisticated public domain name detection; if it’s got more than one element, and it’s not an IP address, Caddy assumes it’s a real, publicly accessible domain name, I believe.

All of this make it just a no-brainer to stick with the current method - you tell Caddy which hostnames should be configured which way. You do that by making one site for internal, configure its TLS, and then make one site for external.


As for the duplicated names - I suppose it isn’t really ambiguous in that case, practically speaking, but it is still a duplicate logically speaking.

It might be possible to introduce some logic into the Caddyfile parsing to deduplicate the hosts in this scenario. I can’t promise it’ll be a high priority for development though, I’m afraid. You could open an issue on the Caddy repo to ask for this as a feature request.

Can you help me with modify my template so that caddy can understand what I want? It is going to be too problematic to swap to a template language that allows logic for this.

%(PUBLIC_FQDN)s {
    log stdout

    proxy / http://proxy {
        transparent
    }

  # regular Automatic HTTPS
}

http://*:%(RESPONDER_HTTP_PORT)s, https://%(APPLICATION_FQDN)s:%(RESPONDER_HTTPS_PORT)s {
    log stdout
    
    proxy / http://proxy {
        transparent
    }
    
    redir 302 {
        if {scheme} is http
        if {hostonly} is %(APPLICATION_FQDN)s
        if {hostonly} not localhost
        /  https://%(APPLICATION_FQDN)s:%(RESPONDER_HTTPS_PORT)s{uri}
    }
    
    tls /etc/pki/tls/certs/server.chained.crt /etc/pki/tls/private/server.key
}

The issue is that for templating sometimes (i.e. dev/staging) APPLICATION_FQDN == PUBLIC_FQDN

– edit –

Thought: Is it possible to use an if statement for conditional declaration?

The Caddyfile definitely doesn’t have any capability to predicate a site definition on a conditional. This would be down to your templating engine.

I’m not sure what you’re using, but if it’s got the ability to compare APPLICATION_FQDN with PUBLIC_FQDN and echo the first block only when they’re different, you’ve solved the problem.

One other thought - presumably, your ops process launches Caddy after the templating is finished? Perhaps you could modify your Caddy launch command to remove-duplicates-from-caddyfile.sh && caddy (or as appropriate) and make a bash file to delete the offending block if the two variables are the same.

That would make this simple but unfortunately isn’t possible

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.