.DEFAULT_GOAL := help SHELL := /usr/bin/env bash COMPOSE := docker compose # Source .env so $(CADDY_HOSTNAME) etc. are available in recipes. include .env export .PHONY: help prep certs up down restart logs logs-caddy ps test test-tls \ test-public reload clean tls-up cert-watch caddy-rebuild help: ## Show this help @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) prep: ## Re-inject SOA + bump serial, then NOTIFY HE (auto-fires AXFR) @./scripts/prepare-zones.sh @./scripts/notify-he.py --quiet || echo " (NOTIFY had failures; HE will still re-poll on SOA refresh)" certs: ## Generate self-signed dev cert (only useful if not using Caddy ACME) @./scripts/generate-certs.sh caddy-rebuild: ## Rebuild the Caddy image (after editing caddy/Dockerfile) $(COMPOSE) build --no-cache caddy # --------------------------------------------------------------------------- # Production / Let's Encrypt flow # --------------------------------------------------------------------------- tls-up: prep ## Bring up Caddy → wait for cert → start CoreDNS (one command) @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 # --------------------------------------------------------------------------- down: ## Stop & remove all containers $(COMPOSE) down restart: ## Restart CoreDNS (does not re-prep zones / re-issue cert) $(COMPOSE) restart coredns reload: prep ## Re-prep zones; CoreDNS auto-plugin picks changes up @echo "Zones re-prepared. CoreDNS reloads files every 30s (auto plugin)." logs: ## Tail CoreDNS logs $(COMPOSE) logs -f coredns ps: ## Show container status $(COMPOSE) ps # --------------------------------------------------------------------------- # 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 + prepared zones + dev self-signed certs rm -rf zones-prepared/*.zone certs/*.pem 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