coredns/Makefile

118 lines
4.5 KiB
Makefile
Raw Normal View History

.DEFAULT_GOAL := help
SHELL := /usr/bin/env bash
COMPOSE := docker compose
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
# Source .env so $(CADDY_HOSTNAME) etc. are available in recipes.
include .env
export
.PHONY: help certs up down restart logs logs-caddy ps test test-tls \
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
test-public reload clean tls-up cert-watch caddy-rebuild
help: ## Show this help
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
# ---------------------------------------------------------------------------
# Zone-file edits are now direct: edit zones/*.zone, bump SOA serial,
# commit. CoreDNS's auto plugin reloads within 30s. HE pulls on its
# SOA-refresh cycle (300s by zone SOA setting).
#
# For manual edits, scripts/bump-serials.sh helps bump CalVer-style
# serials for zones changed since HEAD. RFC 2136 UPDATEs (via the
# coredns-rfc2136 plugin) bump serials themselves and auto-commit.
#
# The legacy prepare-zones.sh / make prep / notify-he.py pipeline is
# retired — kept in scripts/archive/ for reference. See CLAUDE.md.
# ---------------------------------------------------------------------------
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
certs: ## Generate self-signed dev cert (only useful if not using Caddy ACME)
@./scripts/generate-certs.sh
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
caddy-rebuild: ## Rebuild the Caddy image (after editing caddy/Dockerfile)
$(COMPOSE) build --no-cache caddy
# ---------------------------------------------------------------------------
# Production / Let's Encrypt flow
# ---------------------------------------------------------------------------
tls-up: ## Bring up Caddy → wait for cert → start CoreDNS (one command)
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
@if [ -z "$$VULTR_API_KEY" ]; then \
echo "ERROR: VULTR_API_KEY is not exported. Set it in your shell:"; \
echo " export VULTR_API_KEY=..."; \
exit 1; \
fi
@mkdir -p caddy-data caddy-config
$(COMPOSE) up -d caddy
@echo ""
@echo "Waiting for Caddy to provision cert for $(CADDY_HOSTNAME)..."
@echo "(DNS-01 via Vultr typically takes 30-90s; press Ctrl-C to abort)"
@for i in $$(seq 1 90); do \
if [ -e caddy-data/caddy/cert.pem ]; then \
echo ""; echo " ✓ cert ready after $${i}0s"; break; \
fi; \
printf '.'; sleep 10; \
done
@test -e caddy-data/caddy/cert.pem || \
(echo ""; echo "FAILED — see logs: make logs-caddy"; exit 1)
$(COMPOSE) up -d coredns
@sleep 3 && $(COMPOSE) logs --tail=15 coredns
cert-watch: ## Tail Caddy logs while it provisions the cert
$(COMPOSE) logs -f caddy
logs-caddy: ## Tail Caddy logs
$(COMPOSE) logs -f caddy
# ---------------------------------------------------------------------------
# Day-to-day operations
# ---------------------------------------------------------------------------
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
down: ## Stop & remove all containers
$(COMPOSE) down
restart: ## Restart CoreDNS (does not re-issue cert)
$(COMPOSE) restart coredns
reload: ## Touch zone files so CoreDNS auto plugin picks them up promptly
@echo "CoreDNS auto plugin polls zones/ every 30s — no action needed."
@echo "If you just edited a zone, ensure the SOA serial was bumped."
logs: ## Tail CoreDNS logs
$(COMPOSE) logs -f coredns
ps: ## Show container status
$(COMPOSE) ps
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
# ---------------------------------------------------------------------------
# Smoke tests
# ---------------------------------------------------------------------------
test: ## Smoke-test plain DNS
@echo "Querying acrazy.org @ 127.0.0.1:$(DNS_PORT) (plain DNS)"
@dig @127.0.0.1 -p $(DNS_PORT) acrazy.org SOA +short
@dig @127.0.0.1 -p $(DNS_PORT) acrazy.org NS +short
@dig @127.0.0.1 -p $(DNS_PORT) or.acrazy.org A +short
test-tls: ## Smoke-test DoT + DoH against LOCAL endpoints (trusts cert via system CAs)
@echo "=== DoT @ 127.0.0.1:$(DOT_PORT), expecting cert for $(CADDY_HOSTNAME) ==="
@dig @127.0.0.1 -p $(DOT_PORT) +tls +tls-hostname=$(CADDY_HOSTNAME) \
acrazy.org SOA +short
@echo ""
@echo "=== DoH @ https://$(CADDY_HOSTNAME):$(DOH_PORT)/dns-query ==="
@dig @$(CADDY_HOSTNAME) -p $(DOH_PORT) +https acrazy.org A +short
test-public: ## Smoke-test using the public hostname (DoT/DoH ports must be open + DNS A record set)
@echo "=== DoT on public hostname @ port 853 ==="
@dig @$(CADDY_HOSTNAME) +tls cloudflare.com A +short
@echo "=== DoH on public hostname @ port 443 ==="
@dig @$(CADDY_HOSTNAME) +https cloudflare.com A +short
clean: down ## Remove containers + dev self-signed certs
rm -f certs/*.pem
coredns: production Let's Encrypt cert via Caddy sidecar (DNS-01 + Vultr) Replaces the self-signed dev cert flow with a real LE prod cert for dns.l.supported.systems, issued and auto-renewed by a Caddy sidecar using DNS-01 challenge against the Vultr API. Components: - caddy/Dockerfile builds Caddy 2.10.0 with caddy-dns/vultr plugin via xcaddy. GOTOOLCHAIN=auto so xcaddy can fetch newer Go on demand when plugin versions advance their minimum Go. - caddy/Caddyfile uses DNS-01 with explicit public resolvers (1.1.1.1, 9.9.9.9) for the propagation check. Without that, Docker's embedded DNS leaks the container into the host's split-horizon LAN DNS, which returns LAN IPs for ns1.vultr.com and the propagation check fails. - docker-compose: caddy service shares ./caddy-data with coredns via a read-only subpath mount that excludes /acme (account private key). - Healthcheck doubles as a symlinker: maintains stable cert.pem / key.pem names at /data/caddy/ and chmods cert files + their dirs to be readable by CoreDNS's nonroot user. Flips to "healthy" only once the symlinks dereference (i.e. cert exists), gating CoreDNS start via depends_on: service_healthy. - Corefile unchanged — same /etc/coredns/certs/cert.pem path; only the bind-mount source switches from ./certs to ./caddy-data/caddy. - New Makefile target: tls-up orchestrates the bring-up sequence. Cert is valid until Aug 12 2026. Verified end-to-end: dig @127.0.0.1 -p 8853 +tls +tls-hostname=dns.l.supported.systems ... dig @127.0.0.1 -p 8443 +https +tls-hostname=dns.l.supported.systems ...
2026-05-14 01:34:57 -06:00
clean-caddy: down ## Also wipe Caddy's data dir (forces re-issuance from scratch!)
@echo "About to delete caddy-data/ — this will force re-issuance from LE."
@echo "Hit Ctrl-C in 5s to abort..."
@sleep 5
rm -rf caddy-data caddy-config