1. The problem I’m having:
I’m hosting a couple dozen static sites at *.classes.example.com
(like course1.classes.example.com
, course2.classes.example.com
, and so on).
(For the sake of illustration and reproducibility, I’ll use classes.localhost
instead here).
My Caddyfile looks like this:
course1.classes.localhost {
root * /var/www/html/classes/course1
file_server
}
course2.classes.localhost {
root * /var/www/html/classes/course2
file_server
}
# A bunch more...
That works fine, and I could probably use a snippet or something to automate it more, but this is okay.
If I run this locally, and look in my data directory, I can see that it generates individual certificates for each of the sites:
certificates
└── local
├── course1.classes.localhost
│ ├── course1.classes.localhost.crt
│ ├── course1.classes.localhost.json
│ └── course1.classes.localhost.key
└── course2.classes.localhost
├── course2.classes.localhost.crt
├── course2.classes.localhost.json
└── course2.classes.localhost.key
My concern is that in production, I’ll run into Let’s Encrypt rate limits, given how many there are. I’d like to create just one wildcard domain and have all the sites use that.
To test this locally, I added a wildcard domain:
*.classes.localhost {
tls internal
# For production
# tls {
# dns digitalocean {env.DO_API_TOKEN}
# }
}
course1.classes.localhost {
root * /var/www/html/classes/course1
file_server
}
course2.classes.localhost {
root * /var/www/html/classes/course2
file_server
}
# A bunch more...
I was hoping that course1.classes.localhost
and course2.classes.localhost
would not use site-specific certificates and instead use the wildcard one, but that’s not the case. Caddy generates a wildcard certificate, but it also generates site-specific ones too:
certificates
└── local
├── course1.classes.localhost
│ ├── course1.classes.localhost.crt
│ ├── course1.classes.localhost.json
│ └── course1.classes.localhost.key
├── course2.classes.localhost
│ ├── course2.classes.localhost.crt
│ ├── course2.classes.localhost.json
│ └── course2.classes.localhost.key
└── wildcard_.classes.localhost
├── wildcard_.classes.localhost.crt
├── wildcard_.classes.localhost.json
└── wildcard_.classes.localhost.key
2. Error messages and/or full log output:
There are no error messages or log issues—Caddy just creates a bunch of certificates instead of just one wildcard one. This is what’s in the data folder:
certificates
└── local
├── course1.classes.localhost
│ ├── course1.classes.localhost.crt
│ ├── course1.classes.localhost.json
│ └── course1.classes.localhost.key
├── course2.classes.localhost
│ ├── course2.classes.localhost.crt
│ ├── course2.classes.localhost.json
│ └── course2.classes.localhost.key
└── wildcard_.classes.localhost
├── wildcard_.classes.localhost.crt
├── wildcard_.classes.localhost.json
└── wildcard_.classes.localhost.key
3. Caddy version:
I’m using Caddy v2.7.6 .
4. How I installed and ran Caddy:
a. System environment:
I’m using Caddy through Docker Desktop 4.26.1 and Docker Compose v2.23.3 on macOS Sonoma 14.2.1
c. Service/unit/compose file:
version: "3.8"
services:
caddy:
image: caddy:2-alpine
ports:
- 80:80
- 443:443
volumes:
- "./sites/:/var/www/html/:ro"
- "./caddyfile-dev/Caddyfile:/etc/caddy/Caddyfile"
# Caddy needs to mount /data and /config for persisted data
- "./caddy_data/:/data/"
- "./caddy_config/:/config/"
d. My complete Caddy config:
Here’s the full Caddyfile:
# Wildcard domain
*.classes.localhost {
tls internal
}
course1.classes.localhost {
root * /var/www/html/classes/course1
file_server
}
course2.classes.localhost {
root * /var/www/html/classes/course2
file_server
}
5. Links to relevant resources:
In the Common Patterns section of the documentation, it discusses wildcard domains, and I think I’d need to include each of the site-specific blocks inside the wildcard block with some combination of handle
and host
, but I’m not entirely sure how that would look, since the documentation shows basic respond
commands and not server names and roots and file server details