This episode covers manual TLS configuration: the tls directive, protocol and cipher options, disabling automatic HTTPS for development, certificate sources beyond Let's Encrypt, and enforcing HTTPS with HSTS.

Automatic HTTPS handles 90 percent of the needs, but sometimes you need to control TLS manually: use an existing certificate, run development on localhost, choose a minimum protocol, or use a different CA. Episode 8 covers all of those options.
If you have a certificate and key from a particular vendor, install them with the tls directive:
example.com {
tls /etc/ssl/example.com.crt /etc/ssl/example.com.key
root * /var/www
file_server
}The file format is PEM — a certificate and private key pair. If the certificate is a chain, combine everything into a single file.
When tls is given a file, Caddy won't request an ACME certificate for that site — it uses the file provided. This is useful for certificates from commercial or organizational CAs.
For local development, Caddy has its own internal CA:
localhost {
tls internal
root * ./site
file_server
}tls internal makes Caddy its own CA and issues a local certificate for localhost. Browsers will show a trust warning, but the connection is still encrypted. This pattern is also used for internal sites in episode 10.
You can restrict protocol versions and ciphers:
example.com {
tls {
protocols tls1.2 tls1.3
curves x25519
}
}protocols tls1.2 tls1.3 limits to only the secure versions — disabling the obsolete TLS 1.0 and 1.1. curves x25519 selects the elliptic curve for key exchange. By default Caddy already picks secure options; this configuration is for compliance or specific needs.
h2 for HTTP/2.Both are enabled automatically by Caddy — they rarely need manual changes.
Automatic HTTPS only activates for public domain names. For localhost, .local, IP addresses, or other internal names, Caddy doesn't request public certificates:
localhost:8080 {
root * ./site
file_server
}This site will run plain HTTP on port 8080. For local HTTPS, add tls internal as shown earlier.
If you create your own self-signed certificate:
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout key.pem -out cert.pem -days 365 \
-subj "/CN=internal.example.com"Then install the result:
internal.example.com {
tls /etc/ssl/cert.pem /etc/ssl/key.pem
root * /var/www
file_server
}openssl req -x509 ... creates a certificate suitable for internal networks. Remember: clients must trust this certificate or they'll see a warning.
Caddy uses Let's Encrypt by default. For a different CA, use the global options:
{
acme_ca https://acme.zerossl.com/v2/DV90
}
example.com {
root * /var/www
file_server
}acme_ca points all issuance at the new CA. You can use ZeroSSL, or an internal ACME server like Step CA — covered in episode 10.
Combine per-site CAs and manual files:
a.example.com {
tls {
issuer acme {
ca https://acme.zero-ssl.com/v2/DV90
}
}
}
b.example.com {
tls /etc/ssl/b.crt /etc/ssl/b.key
}Site A uses a custom CA, site B uses a manual file. Per-site control like this is useful in multi-tenant environments.
HSTS tells browsers to always use HTTPS for that domain:
example.com {
header Strict-Transport-Security "max-age=31536000; includeSubDomains"
root * /var/www
file_server
}header Strict-Transport-Security ... tells browsers to access the site only via HTTPS for one year, including subdomains. HSTS prevents downgrade attacks to HTTP.
To get into the browser preload list, add preload to the HSTS value and register the domain at hstspreload.org. Once preloaded, browsers will reject HTTP forever — make sure your HTTPS is flawless before registering.
Episode 8 gave you full control over TLS: the tls directive for manual certificates, protocol and cipher options, disabling automatic HTTPS in development with tls internal or self-signed certs, choosing certificate sources from Let's Encrypt to custom ACME, and enforcing HTTPS with HSTS.
Key takeaways:
tls file.crt file.key installs a manual PEM-format certificate.tls internal uses Caddy's built-in CA for development.acme_ca points issuance at another CA like ZeroSSL.includeSubDomains strengthens HTTPS enforcement.In the next episode, episode 9, we'll cover wildcard certificates and DNS challenges — a star certificate for all subdomains, DNS provider credentials like Cloudflare and Route53, DNS-01 configuration, and custom builds with xcaddy to add DNS provider modules.