1. Caddy version (caddy version
):
v2.4.0-beta.1.0.20210227022758-ec309c6d52fd h1:Fvxh1kW7soG+k+0oG17Tn1+LYsYowXMHwtTIGUuDDc8=
2. How I run Caddy:
Built using Dockerfile
FROM caddy:builder AS builder
RUN xcaddy build ec309c6d52fdfce0431a1303a49f28c3f546176a \
--with github.com/mholt/caddy-dynamicdns \
--with github.com/caddy-dns/cloudflare
FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
a. System environment:
Running in Docker, built from Dockerfile
b. Command:
... Docker-compose.yml
command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
c. Service/unit/compose file:
paste full file contents here
d. My complete Caddyfile or JSON config:
{
dynamic_dns {
provider cloudflare APIKEY
domains {
site.com www @
}
check_interval 5m
}
acme_dns cloudflare APIKEY
cert_issuer zerossl
cert_issuer acme
email webmaster@site.com
}
# Add gzip compression to requests
(encoding) {
encode gzip zstd
}
# Add Security headers
(SecurityHeaders) {
header {
# Server name removing
-Server
## Server site.com
X-Content-Type-Options "nosniff"
# Disallow the site to be rendered within a frame (clickjacking protection)
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "no-referrer-when-downgrade"
# Enable HTTP Strict Transport Security (HSTS)
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-Xss-Protection "1; mode=block"
# Prevent search engines from indexing (optional)
X-Robots-Tag "none, noimageindex, noarchive, nocache, nosnippet"
Cache-Control "public, max-age=15, must-revalidate"
Feature-Policy "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"
Content-Security-Policy "upgrade-insecure-requests"
X-Permitted-Cross-Domain-Policies "none"
X-Download-Options "noopen"
}
}
(logging) {
log {
output file /var/log/caddy-{args.0}-access.log {
roll true
roll_size 1Mib
roll_local_time true
roll_keep_for 7d
}
}
}
(errors) {
handle_errors {
rewrite * /{http.error.status_code}
reverse_proxy https://httpstatusdogs.com {
header_up Host httpstatusdogs.com
}
}
}
(common) {
import SecurityHeaders
import encoding
import errors
}
(tls) {
import common
tls {
resolvers 8.8.8.8:53
curves secp521r1 secp384r1
}
}
:2018 {
metrics
}
ssl.site.com {
import tls
import logging ssl
respond "Site to check SSL"
}
proxy.site.com {
import tls
import logging proxy
respond "Caddy Proxy Up!"
}
sabnzbd.site.com {
import tls
import logging sabnzbd
reverse_proxy 192.168.XX.XXX:8680
}
# This site uses it's on internal cert, I would to ensure that I've configured this correctly
pf.site.com {
import tls
import logging pf
reverse_proxy https://192.168.X.X:8443 {
transport http {
tls_insecure_skip_verify
}
}
}
etc....
3. The problem I’m having:
I have an issue and a few questions…
I assembled the above config from examples I’ve found on the Caddy Server forums, and for the most part it works without issue. I’m able to get my Certs, Update DNS (changed to CloudFlare this weekend), serve my websites…
Though, I noticed that even if I have ZeroSSL first, if I force the reissuance of a cert by deleting the directory proxy.site.com in caddy/certificates/acme.zerossl…, it requests a new cert from LE. When I stop/up -d the container, it checks for a cert for proxy.site.com and gets a cert from LE.
If I run the validate command, it completes successfully.
docker-compose exec caddy2 caddy validate --config /etc/caddy/Caddyfile
Also, I want to make sure that it is using the DNS-01 challenge, I seem to have the correct command acme_dns, but I’m not sure if that is the correct usage. I’m unable to tell from the caddy2 container logs whether it is performing a DNS-01 challenge.
I also would need your guidance to optimize my config.
I have a site that has it’s own/self-signed cert and I would like to keep the communication secure between the site and Caddy config/reverse proxy… The only way I was able to make it work was to tls_insecure_skip_verify…Is there a better way to achieve this?
I’ve also configured my sites to request individual certs to make it more secure. Yes, I could do this with a Wildcard, but it was my choice to go with individual certs. But, I would like that if a site is not valid, that it display a custom error site. (errors).
For example…
q.site.com would display… 404 not found error from the custom site, but still display https://q.site.com
4. Error messages and/or full log output:
caddy2 | {"level":"info","ts":1615246479.8447576,"logger":"tls.obtain","msg":"acquiring lock","identifier":"proxy.site.com"}
caddy2 | {"level":"info","ts":1615246479.851522,"logger":"tls.obtain","msg":"lock acquired","identifier":"proxy.site.com"}
caddy2 | {"level":"info","ts":1615246479.852667,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["proxy.site.com"]}
caddy2 | {"level":"info","ts":1615246479.852694,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["proxy.site.com"]}
caddy2 | {"level":"debug","ts":1615246480.059418,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"GET","url":"https://acme-v02.api.letsencrypt.org/directory","headers":{"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["658"],"Content-Type":["application/json"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"debug","ts":1615246480.1085842,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"HEAD","url":"https://acme-v02.api.letsencrypt.org/acme/new-nonce","headers":{"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["0103_idO1wQzX0xoFvD1i5d6QoF-CL-yvcV-OJUE2mYPLv4"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"debug","ts":1615246480.357558,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/new-order","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":201,"response_headers":{"Boulder-Requester":["xxxxxx"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["334"],"Content-Type":["application/json"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Location":["https://acme-v02.api.letsencrypt.org/acme/order/xxxxxx/xxxxxx"],"Replay-Nonce":["0103inwG7Vomfh-v5xtV8y_xtmodN6tSUZ6FkSvTGCLYXvg"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"debug","ts":1615246480.4378402,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/authz-v3/11129044150","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Boulder-Requester":["xxxxxx"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["605"],"Content-Type":["application/json"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Replay-Nonce":["010414EufhRANNUaOu3bUwvbpKMJ5rnvbmHhp8wg6kEUUi0"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"info","ts":1615246480.4384246,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-v02.api.letsencrypt.org/acme/order/xxxxxx/xxxxxx"}
caddy2 | {"level":"debug","ts":1615246480.921991,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/finalize/xxxxxx/xxxxxx","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Boulder-Requester":["xxxxxx"],"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["438"],"Content-Type":["application/json"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\""],"Location":["https://acme-v02.api.letsencrypt.org/acme/order/xxxxxx/xxxxxx"],"Replay-Nonce":["0104lpmKjIqiiLOi_kQmuM4oVzaLnM9-rJeypmp0jSadt3o"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"debug","ts":1615246480.9997852,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["3157"],"Content-Type":["application/pem-certificate-chain"],"Date":["Mon, 08 Mar 2021 23:34:40 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\"","<https://acme-v02.api.letsencrypt.org/acme/cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/1>;rel=\"alternate\""],"Replay-Nonce":["0103-M2Q63fvdag3YZnB9JDybJSL2u5GYmbDPCPu927BIIA"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"debug","ts":1615246481.0776393,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme-v02.api.letsencrypt.org/acme/cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/1","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/2.4.0-beta.1.0.20210227022758-ec309c6d52fd CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Cache-Control":["public, max-age=0, no-cache"],"Content-Length":["3397"],"Content-Type":["application/pem-certificate-chain"],"Date":["Mon, 08 Mar 2021 23:34:41 GMT"],"Link":["<https://acme-v02.api.letsencrypt.org/directory>;rel=\"index\"","<https://acme-v02.api.letsencrypt.org/acme/cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/0>;rel=\"alternate\""],"Replay-Nonce":["0103jPvKSFsMLCKpC2BHPO56yrvfHlEH0afOeozT6yQpwes"],"Server":["nginx"],"Strict-Transport-Security":["max-age=604800"],"X-Frame-Options":["DENY"]}}
caddy2 | {"level":"info","ts":1615246481.0778122,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-v02.api.letsencrypt.org/acme/cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
caddy2 | {"level":"info","ts":1615246481.0785155,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"proxy.site.com"}
caddy2 | {"level":"info","ts":1615246481.0785413,"logger":"tls.obtain","msg":"releasing lock","identifier":"proxy.site.com"}
caddy2 | {"level":"debug","ts":1615246481.0796878,"logger":"tls","msg":"loading managed certificate","domain":"proxy.site.com","expiration":1623018880,"issuer_key":"acme-v02.api.letsencrypt.org-directory","storage":"FileStorage:/data/caddy"}
5. What I already tried:
I’ve tried various configs from different forum posts…