From 0bfeade2fe354e2432936a2917f04fdb039e32f6 Mon Sep 17 00:00:00 2001 From: fuomag9 <1580624+fuomag9@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:30:07 +0100 Subject: [PATCH] Add HTTP-01 challenge fallback for managed certificates without Cloudflare Previously, managed certificates required Cloudflare DNS to be configured, otherwise no TLS automation was configured and HTTPS would fail with TLS handshake errors. Changes: - When Cloudflare is configured: use DNS-01 challenge via Cloudflare - When Cloudflare is NOT configured: use HTTP-01 challenge (default) - Enable automatic HTTPS when TLS automation policies exist - This allows Let's Encrypt certificates via HTTP-01 challenge Fixes TLS handshake errors when using managed certificates without Cloudflare configuration. Port 80 must be accessible for HTTP-01. --- src/lib/caddy.ts | 49 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/lib/caddy.ts b/src/lib/caddy.ts index 3a504ef5..d749ae9d 100644 --- a/src/lib/caddy.ts +++ b/src/lib/caddy.ts @@ -502,20 +502,7 @@ async function buildTlsAutomation( } const cloudflare = await getCloudflareSettings(); - if (!cloudflare || !cloudflare.apiToken) { - return { - managedCertificateIds: new Set() - }; - } - - // The caddy-dns/cloudflare module only accepts api_token - // See: https://github.com/caddy-dns/cloudflare - const providerBase: Record = { - name: "cloudflare", - api_token: cloudflare.apiToken - }; - // Note: zone_id and account_id are not supported by caddy-dns/cloudflare module - // The provider automatically handles all zones for the given API token + const hasCloudflare = cloudflare && cloudflare.apiToken; const managedCertificateIds = new Set(); const policies: Record[] = []; @@ -527,20 +514,34 @@ async function buildTlsAutomation( } managedCertificateIds.add(entry.certificate.id); - const providerConfig = { ...providerBase }; + + // Build issuer configuration const issuer: Record = { - module: "acme", - challenges: { - dns: { - provider: providerConfig - } - } + module: "acme" }; if (options.acmeEmail) { issuer.email = options.acmeEmail; } + // Use DNS-01 challenge if Cloudflare is configured, otherwise use HTTP-01 + if (hasCloudflare) { + // The caddy-dns/cloudflare module only accepts api_token + // See: https://github.com/caddy-dns/cloudflare + const providerConfig: Record = { + name: "cloudflare", + api_token: cloudflare.apiToken + }; + // Note: zone_id and account_id are not supported by caddy-dns/cloudflare module + + issuer.challenges = { + dns: { + provider: providerConfig + } + }; + } + // If no Cloudflare, Caddy will use HTTP-01 challenge by default + policies.push({ subjects, issuers: [issuer] @@ -714,9 +715,9 @@ async function buildCaddyDocument() { cpm: { listen: hasTls ? [":80", ":443"] : [":80"], routes: httpRoutes, - automatic_https: { - disable: true - }, + // Only disable automatic HTTPS if we have TLS automation policies + // This allows Caddy to handle HTTP-01 challenges for managed certificates + ...(tlsApp ? {} : { automatic_https: { disable: true } }), ...(hasTls ? { tls_connection_policies: tlsConnectionPolicies } : {}) } }