I’m running Caddy 0.11 in a Docker container on an Amazon EC2 instance. Everything was working great until I made a few tweaks to my site, pushing and pulling the Docker image and restarting the container several times within a few minutes. At which point I hit the rate limit error below from Let’s Encrypt:
I’m running the Docker container with the Let’s Encrypt files mounted in a volume using this command: docker run -d -p 80:80 -p 443:443 -v /home/ec2-user/dotcaddy:/.caddy:rw --name caddy --ulimit nofile=8192:8192 --restart always myrepo/mywebsite.com
I don’t understand why Caddy is trying to register my site with Let’s Encrypt every time I restart the Docker container. How can I avoid this error in future?
What is actually contained within your rootfs? Obviously you must have the caddy binary in there because it’s not being added from anywhere else but what else is included?
If I were you I would check if caddy has stored the certs inside /var/www/html/.caddy. I checked the documentation and came to these conclusions:
You are not setting $CADDYPATH anywhere so caddy won’t use a path based on that.
In that case caddy will try to use $HOME/.caddy. The only way I see this generating the path /.caddy is if your rootfs contains a user (I guess it has to be root because you aren’t using USER) whose home directory is /. I’m gonna say this isn’t true because it should work if it were.
So I think the options are either that you are defining a home directory for the root user (other than /) or caddy will fallback to the final behaviour which is creating .caddy in the current working directory (which in your case will be /var/www/html due to the WORKDIR line).
In any case I would suggest you configure $CADDYPATH to explicitly tell caddy where you want the certs to be. That always feels the most clear to me anyway.
EDIT: To test a new config to fix your issue you could consider using the -ca option to use the staging endpoint:
You can also define this in the Caddyfile which might suit you better. This gets you non-trusted certs but worth using to test new changes & while you are rate-limited for production certs anyway.
Thanks I’ll take a look. I’ll have to temporarily change my Docker image to explore the filesystem because as I’m using the scratch base image it doesn’t have a shell!
OK, it looks like there are three things going on here. My Docker run command had a couple of errors. I was publishing the container port as port 80, but Caddy was listening on the default port 2015. I was also mounting my dotcaddy volume in /.caddy rather than root’s home directory, as Joel pointed out. So the corrected command looks like this:
The third issue is that I’m hitting the bug Matt mentioned, because I can see from the logs that Caddy is requesting certificates from Let’s Encrypt every time the Docker container is started, rather than using its local copies mounted in the container.
I’m not sure what behaviour you’re expecting, but I started my Docker container using my Caddy binary built from the sni-fixes branch as requested. Then I stopped the container and restarted it. Both times the logs indicate that the server validated the request and that the server responded with a certificate. I was expecting the locally stored certificate to be used the second time.
$ docker logs caddy
Activating privacy features...
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address: 2019/02/04 18:04:35 [INFO] [www.johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 18:04:36 [INFO] [www.johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/8iXlD_77ScOX94iQphcm3DVCxGHKvrKNs8fzAPZYFzw
2019/02/04 18:04:36 [INFO] [www.johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 18:04:36 [INFO] [www.johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 18:04:41 [INFO] [www.johntopley.com] The server validated our request
2019/02/04 18:04:41 [INFO] [www.johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 18:04:43 [INFO] [www.johntopley.com] Server responded with a certificate.
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address: 2019/02/04 18:04:44 [INFO] [mail.johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 18:04:45 [INFO] [mail.johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/_GM5PwhkmkrCqpfzgvViIu-QaC0WDchxnow7kVSJU1E
2019/02/04 18:04:45 [INFO] [mail.johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 18:04:45 [INFO] [mail.johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 18:04:51 [INFO] [mail.johntopley.com] The server validated our request
2019/02/04 18:04:51 [INFO] [mail.johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 18:04:52 [INFO] [mail.johntopley.com] Server responded with a certificate.
2019/02/04 18:04:52 [INFO] acme: Registering account for xxxx@johntopley.com
2019/02/04 18:04:53 [INFO] [johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 18:04:53 [INFO] [johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/PBlBGphCn_etxlvcdz8J2UYZb53OGFhHZeaLDoN3P-M
2019/02/04 18:04:53 [INFO] [johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 18:04:53 [INFO] [johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 18:04:59 [INFO] [johntopley.com] The server validated our request
2019/02/04 18:04:59 [INFO] [johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 18:05:01 [INFO] [johntopley.com] Server responded with a certificate.
done.
https://www.johntopley.com
https://mail.johntopley.com
https://johntopley.com
http://www.johntopley.com
http://mail.johntopley.com
http://johntopley.com
$ docker logs caddy
Activating privacy features...
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address: 2019/02/04 19:29:00 [INFO] [www.johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 19:29:00 [INFO] [www.johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/q026fAyGHnOYgx3Whmvbd3Do8WeSL27v_Yh0kYZQJLY
2019/02/04 19:29:00 [INFO] [www.johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 19:29:00 [INFO] [www.johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 19:29:07 [INFO] [www.johntopley.com] The server validated our request
2019/02/04 19:29:07 [INFO] [www.johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 19:29:08 [INFO] [www.johntopley.com] Server responded with a certificate.
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address: 2019/02/04 19:29:09 [INFO] [mail.johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 19:29:10 [INFO] [mail.johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/C-xBrH6cq_oMVLOfKTNNUAO2skPsoQlXBiyytY__XPo
2019/02/04 19:29:10 [INFO] [mail.johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 19:29:10 [INFO] [mail.johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 19:29:15 [INFO] [mail.johntopley.com] The server validated our request
2019/02/04 19:29:15 [INFO] [mail.johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 19:29:17 [INFO] [mail.johntopley.com] Server responded with a certificate.
2019/02/04 19:29:17 [INFO] acme: Registering account for xxxx@johntopley.com
2019/02/04 19:29:18 [INFO] [johntopley.com] acme: Obtaining bundled SAN certificate
2019/02/04 19:29:18 [INFO] [johntopley.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz/y7K7bVZmiDhJ49fuuOHzdWA72x7Af2ncMbneAThKtp0
2019/02/04 19:29:18 [INFO] [johntopley.com] acme: use tls-alpn-01 solver
2019/02/04 19:29:18 [INFO] [johntopley.com] acme: Trying to solve TLS-ALPN-01
2019/02/04 19:29:24 [INFO] [johntopley.com] The server validated our request
2019/02/04 19:29:24 [INFO] [johntopley.com] acme: Validations succeeded; requesting certificates
2019/02/04 19:29:26 [INFO] [johntopley.com] Server responded with a certificate.
done.
https://www.johntopley.com
https://mail.johntopley.com
https://johntopley.com
http://www.johntopley.com
http://mail.johntopley.com
http://johntopley.com
If you could verify that, after using docker rm and then when the new container starts up, the certificates still exist in $CADDYPATH ($HOME/.caddy by default), that would be good. Right now it looks like your certificates are getting destroyed when you delete the container.
I would also be sure to follow @joelnb’s advice above to use the staging endpoint before you rate limit yourself again.
It looks like they are bind mounting to /root/.caddy just fine.
That said, I’ve just gotten around to building this myself on Ubuntu v18.04 running Docker v18.09.1 with Compose v1.23.2.
I built Caddy v0.11.2 +73d3146 with the following Dockerfile:
Dockerfile
FROM golang:alpine
RUN apk add --no-cache git
RUN go get \
github.com/abiosoft/caddy-git \
github.com/caddyserver/builds \
github.com/mholt/caddy
WORKDIR /go/src/github.com/mholt/caddy
RUN git checkout sni-fixes
RUN sed '/This is where other plugins get plugged in (imported)/ a _ "github.com/abiosoft/caddy-git"' -i /go/src/github.com/mholt/caddy/caddy/caddymain/run.go
WORKDIR /go/src/github.com/mholt/caddy/caddy
RUN go run build.go
FROM alpine:3.8
RUN apk add --no-cache ca-certificates
COPY --from=0 /go/src/github.com/mholt/caddy/caddy/caddy /usr/bin/caddy
RUN /usr/bin/caddy -version
RUN /usr/bin/caddy -plugins
WORKDIR /srv
RUN echo "Caddy is running!" > index.txt
ENTRYPOINT ["/usr/bin/caddy"]
CMD ["-conf", "/etc/Caddyfile", "-log", "stdout", "-agree"]
Ran the container with the following Compose file:
I changed my Docker base image from scratch to golang-alpine, rebuilt the image and redeployed the container so I could get a shell for the purposes of inspecting the filesystem. I can confirm that my /home/ec2-user/dotcaddy volume is correctly mounted at /root/.caddy within the running container. The certificates under acme/acme-v02.api.letsencrypt.org/sites are dated 26th January, so nothing’s getting deleted.
Interestingly I got different log output when running this golang-alpine version:
Activating privacy features...
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address:
Your sites will be served over HTTPS automatically using Let's Encrypt.
By continuing, you agree to the Let's Encrypt Subscriber Agreement at:
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
Please enter your email address to signify agreement and to be notified
in case of issues. You can leave it blank, but we don't recommend it.
Email address: done.
https://www.johntopley.com
https://mail.johntopley.com
https://johntopley.com
http://www.johntopley.com
http://mail.johntopley.com
http://johntopley.com
My understanding of the above output is that it’s using the cached certificates rather than requesting new ones. I don’t understand why changing the Docker base image would affect this.
That’s the correct inference. I couldn’t tell you why scratch didn’t want to play nicely, though. Was Caddy running as root inside the scratch version?
P.S. You can use the -agree and -email youremail@example.com flags to avoid the interactive prompt for your email on a fresh startup.
I know this is an old thread now, but for the sake of completeness what I’ve discovered is that when using scratch as the base Docker image the bind mount wasn’t working and my certificates weren’t getting cached. At least not on Amazon Linux. Changing the base image to alpine fixed that.