1. The problem I’m having:
I’m setting up Caddy as a containerized static web server/reverse-proxy in a set of containers for local development and eventually deployment to a production server. I’ve got it all working pretty well — except for certificate generation. Despite Caddy’s vaunted “It all just works” philosophy, it doesn’t just work, I assume because the containerized Caddy instance can’t communicate with my local machine to register any autogenerated certs.
I’m running on Linux, but I can’t assume the people who will be doing development on this will be on any particular OS, so I need a solution which will work for everybody with minimal configuration.
I was hoping I could get this running on localhost
. When that failed I registered a local.webdev.com
address in my /etc/hosts
file. Finally I fell back to registering a local.larp.buzz
address in my publicly available DNS provider. I couldn’t get anything to work. Here are my thoughts:
I assumed by registering an A
record (as 127.0.0.1
) and an AAAA
record (as ::1
) that the ACME client would automatically provision a cert. But it consistently gets
{"level":"error","ts":1729860457.8742154,"logger":"tls.acme_client","msg":"challenge failed","identifier":"local.larp.buzz","challenge_type":"tls-alpn-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for local.larp.buzz; no valid AAAA records found for local.larp.buzz","instance":"","subproblems":[]}}
despite nslookup
working fine for those records. I’m also worried about hitting that endpoint repeatedly as I bring services up and down; I could switch to the development endpoint for development but ACME requests you not to do that and instead run a local CA yourself, and at that point my development compose
stack is starting to divert significantly from the production stack in ways I’m not happy about.
I assume I could just manually generate my own certificate and register it. Is that the recommended practice for this? Should I run off of localhost
or is registering a development domain (either locally or in DNS) the better choice? Or is there some clever way of integrating the container with the local machine that avoids this problem?
2. Error messages and/or full log output:
{"level":"error","ts":1729860457.8742154,"logger":"tls.acme_client","msg":"challenge failed","identifier":"local.larp.buzz","challenge_type":"tls-alpn-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for local.larp.buzz; no valid AAAA records found for local.larp.buzz","instance":"","subproblems":[]}}
3. Caddy version:
caddy:2.8-alpine
4. How I installed and ran Caddy:
FROM caddy:2.8-alpine
WORKDIR /proxy
COPY Caddyfile ./
COPY --from=build-stage /app/dist ./webroot
EXPOSE 80
EXPOSE 443
CMD ["caddy", "run", "--config", "/proxy/Caddyfile"]
a. System environment:
Docker
b. Command:
docker compose up
c. Service/unit/compose file:
web:
build: ./web
ports:
- "80:80"
- "443:443"
d. My complete Caddy config:
localhost, local.larp.buzz {
encode zstd gzip
handle_path /api/* {
reverse_proxy http://api:80
}
handle {
root * /proxy/webroot
try_files {path}.html {path} /index.html
file_server
}
}