# Written by ihasmail-oneshot {{.Version}} for {{.Plan.Domain}}. # # Caddy holds ports 80 and 443 for two things that both want certificates for # some of the same names: Caddy itself, to serve HTTPS, and Stalwart, whose # IMAP and SMTP listeners need a certificate of their own. They are kept apart # by challenge type rather than by name: # # Caddy TLS-ALPN-01 on 443 -- for Stalwart's names it never uses port 80. # Stalwart HTTP-01 on 80, which Caddy forwards to it untouched. # # So neither answers the other's challenge, and neither needs the other's key. { email {{.Plan.Email}} {{- if .Plan.ACMEDirectory}} acme_ca {{.Plan.ACMEDirectory}} {{- end}} {{- if .Plan.ACMECARoot}} acme_ca_root /etc/caddy/acme-ca-root.pem {{- end}} } # The webmail. Push arrives as Server-Sent Events, so responses are flushed as # they are written rather than buffered. {{.Plan.WebmailHost}} { encode zstd gzip reverse_proxy ihasmail:8080 { flush_interval -1 } } # Stalwart's web side: its admin UI, JMAP for other clients, CalDAV, CardDAV, # autoconfig and MTA-STS. Stalwart is told to believe the X-Forwarded-For Caddy # sets here, so a scanner is banned by its own address and not by Caddy's. {{join .Plan.StalwartNames ", "}} { tls { issuer acme { {{- if .Plan.ACMEDirectory}} dir {{.Plan.ACMEDirectory}} {{- end}} {{- if .Plan.ACMECARoot}} trusted_roots /etc/caddy/acme-ca-root.pem {{- end}} email {{.Plan.Email}} disable_http_challenge } } reverse_proxy stalwart:8080 } # Port 80 for Stalwart's names is Stalwart's challenge path and a redirect. {{range $i, $n := .Plan.StalwartNames}}{{if $i}}, {{end}}http://{{$n}}{{end}} { handle /.well-known/acme-challenge/* { reverse_proxy stalwart:8080 } handle { redir https://{host}{uri} 308 } }