Example docker compose file
version: "3"
services:
caddy:
build:
context: .
dockerfile: service/caddy/dockerfile
image: mojzu/dev-caddy:latest
hostname: caddy
ports:
- "80:80"
- "443:443"
volumes:
- caddy_config:/config
- caddy_data:/data
restart: "unless-stopped"
step-ca:
image: smallstep/step-ca:latest
hostname: step-ca
ports:
- "444:443"
volumes:
- step_ca:/home/step
- ./private/pki:/pki
restart: "unless-stopped"
... other services
volumes:
caddy_config:
caddy_data:
step_ca:
Creating a CA
docker-compose run --rm step-ca bash
step ca init
# Follow instructions, DNS name is DOMAIN, bind address is :443
step ca provisioner add acme --type ACME
# Change ca-url in config/defaults.json to "https://DOMAIN:444" (the public port from docker-compose service)
# Change maxTLSCertDuration in config/ca.json to "8400h" (for client certificates)
# Copy certs/root_ca.crt and certs/intermediate_ca.crt for installing on client devices
Creating client certificates
step ca certificate --offline --not-after 8400h EMAIL --san EMAIL certs/NAME.crt secrets/NAME.key
step certificate p12 secrets/NAME.p12 certs/NAME.crt secrets/NAME.key --ca certs/root_ca.crt --ca certs/intermediate_ca.crt
step certificate inspect secrets/NAME.p12
# Copy certs/NAME.crt, secrets/NAME.key, secrets/NAME.p12 for installing on client devices
Install root and client certificates on devices/in browsers (depends on device/browser)
Caddy configuration file built into mojzu/dev-caddy image, root_ca.crt file copied to /pki/root_ca.crt
(acme_mtls) {
tls EMAIL {
ca https://DOMAIN:444/acme/acme/directory
ca_root /pki/root_ca.crt
client_auth {
mode require_and_verify
trusted_ca_cert_file /pki/root_ca.crt
}
}
}
SUBDOMAIN.DOMAIN {
import acme_mtls
reverse_proxy http://INTERNAL_SERVICE
}
... other subdomains
Discussion: https://news.ycombinator.com/item?id=29810148