#!/usr/bin/env bash # Generate a self-signed RSA cert for CoreDNS DoT/DoH (local dev only). # Production deployments should mount real Let's Encrypt certs (e.g. from # Caddy's shared volume) into certs/ instead. # # SANs cover the names a local resolver client is likely to use: # - localhost (loopback by name) # - 127.0.0.1 / ::1 (loopback by IP) # - coredns (docker container DNS name) # - dns.local (convenient pinning hostname) set -euo pipefail CERT_DIR="${CERT_DIR:-certs}" DAYS="${DAYS:-825}" # 825 is the historical macOS/Apple cap; safe ceiling mkdir -p "$CERT_DIR" if [[ -f "$CERT_DIR/cert.pem" && -f "$CERT_DIR/key.pem" ]]; then # Skip regeneration if not expired and re-prep was not forced. if [[ "${FORCE:-0}" != "1" ]]; then # openssl returns 0 if cert is valid beyond the given window (24h here). if openssl x509 -checkend 86400 -noout -in "$CERT_DIR/cert.pem" >/dev/null 2>&1; then echo "Cert at $CERT_DIR/cert.pem still valid (>24h). Set FORCE=1 to regenerate." exit 0 fi fi fi # Single-shot self-signed cert with SANs. -addext requires openssl >= 1.1.1. openssl req -x509 -newkey rsa:2048 -nodes -days "$DAYS" \ -keyout "$CERT_DIR/key.pem" \ -out "$CERT_DIR/cert.pem" \ -subj "/CN=coredns-local" \ -addext "subjectAltName=DNS:localhost,DNS:coredns,DNS:dns.local,IP:127.0.0.1,IP:::1" \ >/dev/null 2>&1 # 0644 (not 0600) on the key so the CoreDNS container's `nonroot` user # can read it via the bind mount. Acceptable for a local-dev self-signed # cert whose private key never leaves this directory. For production # certs, mount with explicit UID/GID via :ro,uid=65532 or use a tmpfs/ # secret instead. chmod 644 "$CERT_DIR/key.pem" chmod 644 "$CERT_DIR/cert.pem" echo "Generated $CERT_DIR/{cert,key}.pem (valid ${DAYS} days)" openssl x509 -in "$CERT_DIR/cert.pem" -noout -subject -issuer -dates \ -ext subjectAltName 2>&1 | sed 's/^/ /'