Tell Caddy to use local TLS for a wildcard domain

I think this is a really stupid question, but I can’t quite figure it out from the docs - I really hope the answer to this is a RTFM pointing me to the right bit of the docs.

1. Caddy version (caddy version):

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

a. System environment:

mac os

b. Command:

caddy run

c. Service/unit/compose file:

Don’t think this is relevant but maybe I’m wrong

d. My complete Caddyfile or JSON config:

{
  local_certs
}

ghost.eris

reverse_proxy localhost:2368

3. The problem I’m having:

I’m using Caddy just for local development and I would like to tell Caddy to always use local TLS for a particular TLD. Traditionally peopled used .local or .dev but those are both bad ideas now as bonjour on mac uses .local and chrome uses .dev, so I am trying to setup my own .eris purely for local dev.

I have the above Caddyfile that works for one domain, but I have to manually set local_certs otherwise it errors. I either want Caddy to know .eris is local, or just to use local by default always as I’m running on my local box.

4. Error messages and/or full log output:

Here’s the logs if I don’t set local_certs, which obviously doesn’t work :slight_smile:

2021/04/07 14:17:24.735	INFO	using adjacent Caddyfile
2021/04/07 14:17:24.737	INFO	admin	admin endpoint started	{"address": "tcp/localhost:2019", "enforce_origin": false, "origins": ["localhost:2019", "[::1]:2019", "127.0.0.1:2019"]}
2021/04/07 14:17:24.737	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc0003a4000"}
2021/04/07 14:17:24.738	INFO	http	server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS	{"server_name": "srv0", "https_port": 443}
2021/04/07 14:17:24.738	INFO	http	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
2021/04/07 14:17:24.738	INFO	http	enabling automatic TLS certificate management	{"domains": ["ghost.eris"]}
2021/04/07 14:17:24.738	INFO	autosaved config	{"file": "/Users/hannah/Library/Application Support/Caddy/autosave.json"}
2021/04/07 14:17:24.738	INFO	serving initial configuration
2021/04/07 14:17:24.738	INFO	tls	cleaned up storage units
2021/04/07 14:17:24.739	INFO	tls.obtain	acquiring lock	{"identifier": "ghost.eris"}
2021/04/07 14:17:24.739	INFO	tls.obtain	lock acquired	{"identifier": "ghost.eris"}
2021/04/07 14:17:24.750	INFO	tls.issuance.acme	waiting on internal rate limiter	{"identifiers": ["ghost.eris"]}
2021/04/07 14:17:24.750	INFO	tls.issuance.acme	done waiting on internal rate limiter	{"identifiers": ["ghost.eris"]}
2021/04/07 14:17:25.744	INFO	tls.issuance.acme	waiting on internal rate limiter	{"identifiers": ["ghost.eris"]}
2021/04/07 14:17:25.744	INFO	tls.issuance.acme	done waiting on internal rate limiter	{"identifiers": ["ghost.eris"]}
2021/04/07 14:17:27.355	ERROR	tls.obtain	will retry	{"error": "[ghost.eris] Obtain: [ghost.eris] creating new order: request to https://acme.zerossl.com/v2/DV90/newOrder failed after 1 attempts: HTTP 400 urn:ietf:params:acme:error:rejectedIdentifier - Invalid DNS identifier [ghost.eris] (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 1, "retrying_in": 60, "elapsed": 2.616209947, "max_duration": 2592000}
2021/04/07 14:18:29.162	ERROR	tls.obtain	will retry	{"error": "[ghost.eris] Obtain: [ghost.eris] creating new order: request to https://acme.zerossl.com/v2/DV90/newOrder failed after 1 attempts: HTTP 400 urn:ietf:params:acme:error:rejectedIdentifier - Invalid DNS identifier [ghost.eris] (ca=https://acme.zerossl.com/v2/DV90)", "attempt": 2, "retrying_in": 120, "elapsed": 64.42429126, "max_duration": 2592000}
^C2021/04/07 14:18:42.567	INFO	shutting down	{"signal": "SIGINT"}
2021/04/07 14:18:43.572	INFO	tls.cache.maintenance	stopped background certificate maintenance	{"cache": "0xc0003a4000"}
2021/04/07 14:18:43.572	INFO	tls.obtain	releasing lock	{"identifier": "ghost.eris"}
2021/04/07 14:18:43.572	ERROR	tls	job failed	{"error": "ghost.eris: obtaining certificate: context canceled"}
2021/04/07 14:18:44.074	INFO	admin	stopped previous server
2021/04/07 14:18:44.074	INFO	shutdown done	{"signal": "SIGINT"}

5. What I already tried:

I have read the docs about local TLS and Caddy JSON but I’m struggling to understand how I can set this at a system level.

6. Links to relevant resources:

Hopefully you can link me to what I’m missing :grimacing:

You can use .localhost instead, that should always work. See here:

Using local_certs is exactly the way to go here. There’s no such thing as “system level” config for Caddy. Caddy is configured via a JSON document (or other formats, via config adapters which map to JSON, like the Caddyfile – run caddy adapt to see what your Caddyfile to JSON looks like)

Ok - so .localhost and .local are hardcoded things inside of Caddy, not a configurable thing I have control over :thinking:

It’s pretty picky I guess but as .local is advised against and .localhost is a lot of typing neither are a setup I’m sure about committing to as I’m trying to design a process for developing locally with a lightweight toolset that will work across multiple environments for multiple people from different backgrounds :grimacing:

Well *.localhost isn’t Caddy specific, it’s reserved by RFC 2606:

And *.local is typically used for multicast DNS:

So if you want to follow “standard practice”, then .localhost is probably the way to go.

Might there be scope for adding more options?

.lan is also reserved, short and I’m seeing it recommended as an alternative to .dev in lots of places.

The reserved list:

  • .local
  • .localdomain
  • .domain
  • .lan
  • .home
  • .host
  • .corp

https://tools.ietf.org/id/draft-chapin-rfc2606bis-00.html#rfc.section.2

That’ll be for @matt to decide, but I’ll say it’s “probably unlikely”.

Anyways, like I said:

Right now we’re being conserative and applying self-signed certificates only to standards-reserved TLDs.

Ok cool, totally understand your position

It seems .lan was only ever a draft based on it being an invalid TLD but ICANN reporting it as widely requested, suggesting it’s a commonly used thing.

But going back to the official RFC 2606 the reserved TLDs are:
.test
.example
.invalid
.localhost

Would .test therefore be a viable candidate so that there is one option which has no conflicts and is short?

1 Like

Oh - just to keep all the info in one place, as well as several blog posts I’ve read, the main place I’ve seen .lan is in dnsmasq’s default config. Again, I understand completely wanting to stick to official RFCs.

Note: I can’t get .local to play nicely on a mac with dnsmasq

For development:
on linux you would edit /etc/hosts and set the FQDN you want to use, including a .local naming convention if you wanted.

Mac instructions are second page of this article - How to edit your Mac's Hosts file and why you would want to | iMore

Windows is C:\Windows\system32\drivers\etc\hosts (edit with notepad as administrative user)

If you have a registered domain with a normal TLD (internal business scenarios) then create a “internal” domain based on your registered domain (e.g. int.example.com) that you resolve internally.

Most firewall routers will let you define and serve an internal domain of dhcp registered hosts, and if you configure to use the router as your primary DNS, that will work as well. Full feature open source firewall router software such as LEDE/OpenWRT will let you set up and manage internal DNS for a network.

1 Like

None of that applies to my use case I’m afraid.

I want a process multiple developers (e.g. in an OSS environment) can follow to be able to configure their machine with a wildcard domain.

Caddy is ideal because then each project in which an https domain is needed all that’s required is a small Caddyfile. I’m hoping to get rid of the need to add

{
  local_certs
}

to all Caddyfiles by getting a TLD like .test accepted by Caddy.

I have looked to make a PR but I wasn’t able to find the right bit of code.

@ErisDS the code that makes that check is in Certmagic: