Caddy Let’s Encrypt Certificate Issue Support Request
1. The Problem I’m Having
Caddy will not issue a Let’s Encrypt certificate for any domain, full stop. Resulting in an error that isn’t described anywhere on this forum, nor can I find any resources on how to solve this issue.
2. Error Messages and/or Full Log Output
{
"level": "error",
"ts": 1756340527.875998,
"logger": "tls.obtain",
"msg": "will retry",
"error": "[map.redacted.io] Obtain: registering account [mailto:default.json] with server: attempt 1: acme-staging-v02.api.letsencrypt.org/acme/new-acct: HTTP 400 urn:ietf:params:acme:error:invalidContact - Error validating contact(s) :: unable to parse email address",
"attempt": 2,
"retrying_in": 120,
"elapsed": 60.663868785,
"max_duration": 2592000
}
3. Caddy Version
caddy:2.9.1-builder-alpine
4. How I Installed and Run Caddy
a. System Environment
Docker, AMD
b. Dockerfile
# syntax=docker/dockerfile:1.4
# Build Go
FROM golang:1.21-alpine AS go-builder
# Install build dependencies
RUN apk add --no-cache gcc musl-dev vips-dev build-base && rm -rf /var/cache/apk/*
# Initialize Go module and build with better error handling
RUN set -ex && \
go mod init && \
go get github.com/gofiber/fiber/v2@latest && \
go get github.com/h2non/bimg@latest && \
go get github.com/valyala/fasthttp@latest && \
go mod tidy && \
CGO_ENABLED=1 GOOS=linux go build -v -o
# Final stage with Caddy
FROM caddy:2.9.1-builder-alpine AS builder
RUN xcaddy build --with --with
FROM caddy:2.9.1-builder-alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
# Install runtime dependencies and supervisord
RUN apk add --no-cache vips supervisord nss-tools curl && rm -rf /var/cache/apk/*
# Copy config files
COPY supervisord.conf /etc/supervisor/supervisord.conf
# Copy mysql.json configuration to the exact location
COPY mysql.json /usr/bin/mysql.json
# Ensure correct permissions
RUN chmod 644 /usr/bin/mysql.json
# Create directories
RUN mkdir -p /etc/caddy
# Use EXPOSE for documentation
EXPOSE 80 443 3001
# Set GOGC to off for runtime
ENV GOGC=off
ENV GOMAXPROCS=0
# Use supervisor as entrypoint
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
c. Command (supervisord.conf)
[supervisord]
nodaemon=true
user=root
logfile=/dev/stdout
logfile_maxbytes=0
pidfile=/var/run/supervisord.pid
[program:caddy]
command=caddy run --adapter mysql --config /usr/bin/mysql.json
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
d. Service/Unit/Compose File
services:
cadx:
build: .
network_mode: "host"
restart: unless-stopped
5. My Complete Caddy Configuration
Admin Configuration
{
"disabled": false,
"email": "redacted",
"config": {
"persist": false
}
}
Apps Configuration
HTTP Configuration
{
"https_port": 443,
"email": "redacted",
"servers": {
"srv0": {
"listen": [":443"],
"protocols": ["h1", "h2", "h3"],
"routes": [
{
"handle": [
{
"handler": "headers",
"response": {
"delete": ["Server", "Etag"],
"deferred": true
}
}
]
}
]
}
}
}
Cache Configuration
{
"allowed_http_verbs": ["GET", "HEAD"],
"cache_name": "Redis-Proxy",
"default_cache_control": "public, max-age=7200",
"distributed": true,
"mode": "bypass",
"redis": {
"found": true,
"configuration": {
"AlwaysPipelining": true,
"DisableCache": false,
"DisableRetry": false,
"ShuffleInit": true,
"ClientName": "redacted",
"InitAddress": ["localhost:6379"]
}
},
"timeout": {
"backend": "0s",
"cache": "0s"
},
"ttl": "10s"
}
TLS Configuration
{
"email": "redacted",
"automation": {
"policies": [
{
"on_demand": true
}
],
"on_demand": {
"permission": {
"module": "http",
"endpoint": "redacted"
}
}
}
}
Storage Configuration
{
"module": "mysql",
"query_timeout": 0,
"lock_timeout": 0,
"dsn": "redacted"
}
Server Routes Configuration
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "encode",
"encodings": {
"zstd": {
"level": "fastest"
},
"gzip": {
"level": 1
}
},
"prefer": ["zstd"]
},
{
"handler": "cache",
"cache_name": "Redis-Proxy"
},
{
"handler": "reverse_proxy",
"transport": {
"protocol": "http",
"read_buffer_size": 15360,
"write_buffer_size": 15360,
"keep_alive": {
"max_idle_conns_per_host": 128
}
},
"headers": {
"request": {
"set": {
"Host": ["redacted"]
}
}
},
"upstreams": [
{
"dial": "redacted"
}
]
}
]
}
]
}
],
"match": [
{
"host": ["redacted"]
}
]
}