Skip to content

Last updated: 2026-02-11

Caddy TLS/SSL Configuration Guide

This guide covers TLS/SSL settings for Caddy, a modern web server that provides automatic HTTPS out of the box. Caddy automatically obtains and renews certificates from Let's Encrypt, configures strong TLS defaults, and enables HSTS -- making it one of the most secure web servers by default.

Prerequisites

Automatic HTTPS (Default Behavior)

Caddy's defining feature is automatic HTTPS. With a minimal Caddyfile, Caddy will:

A basic Caddyfile with automatic TLS:

example.com {
    root * /var/www/html
    file_server
}

That's it. No TLS configuration is needed for most deployments. Caddy's defaults are already strong and secure.

Default TLS Settings

Out of the box, Caddy configures:

Custom TLS Configuration

If you need to customize TLS settings (for compliance, auditing, or specific client requirements), use the tls directive in your Caddyfile.

Protocol Versions

Restrict to specific TLS versions:

example.com {
    tls {
        protocols tls1.2 tls1.3
    }
    root * /var/www/html
    file_server
}

Cipher Suites

Caddy uses Go's crypto/tls cipher names (IANA format). To explicitly set cipher suites:

example.com {
    tls {
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    }
}

TLS 1.3 cipher suites cannot be customized in Go's TLS stack. All three TLS 1.3 ciphers are always enabled, which is fine since they are all strong.

ECDH Curves

Specify the elliptic curves for key exchange:

example.com {
    tls {
        curves x25519 secp256r1 secp384r1
    }
}

Using Your Own Certificates

To use externally obtained certificates instead of automatic issuance:

example.com {
    tls /etc/caddy/ssl/fullchain.pem /etc/caddy/ssl/privkey.pem
}

Internal (Self-Signed) Certificates

For internal services that don't need publicly trusted certificates:

internal.example.com {
    tls internal
}

Caddy will generate a locally-trusted certificate using its built-in CA.

HSTS

Caddy enables HSTS automatically for public-facing sites. To customize the HSTS header:

example.com {
    header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
}

On-Demand TLS

For environments with many domains, Caddy supports on-demand TLS -- certificates are obtained at the time of the first TLS handshake:

{
    on_demand_tls {
        ask http://localhost:5555/check
    }
}

https:// {
    tls {
        on_demand
    }
}

The ask endpoint should verify that the requested domain is authorized before Caddy obtains a certificate for it.

Complete Custom Configuration Example

{
    # Global options
    email admin@example.com
}

example.com {
    tls {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
        curves x25519 secp256r1 secp384r1
    }

    header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

    root * /var/www/html
    file_server
}

Verification

Validate and reload the Caddy configuration:

caddy validate --config /etc/caddy/Caddyfile
caddy reload --config /etc/caddy/Caddyfile

Test the TLS connection:

openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3

Check Caddy's certificate management status:

caddy trust

Test your configuration externally using Qualys SSL Labs at https://www.ssllabs.com/ssltest/.