- Go 96.2%
- Dockerfile 3.8%
| .gitignore | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE.md | ||
| main.go | ||
| README.md | ||
cert-manager-webhook
A cert-manager ACME DNS-01 solver webhook. Currently implements the DNS provider's REST API needed for this project's own zone; see the decision record in homelab-docs (ADR-022) for why DNS-01 and this provider were chosen, this README only covers how to build and run what's here.
Not part of the mymh.dev platform's deployment manifests, those live in homelab-gitops as usual. This repo is only the webhook's own source and image build.
Prerequisites
- Docker (the build runs entirely inside a container, no local Go install needed)
- A Kubernetes cluster with cert-manager already installed, to actually deploy and test against
Build
docker build -t cert-manager-webhook:local .
Multi-stage build: compiles with golang:1.26-bookworm, ships as a distroless/static-debian12 runtime image. go.sum is committed, so the build downloads pinned dependency versions only, no go mod tidy at build time.
Why go.mod looks big for such a small tool
Only a handful of packages are imported directly, but cmd.RunWebhookServer (cert-manager's own helper for building this kind of webhook) is built on k8s.io/apiserver, the same library Kubernetes itself uses for its API server. That's what provides the TLS-serving and auth-delegation machinery for free, correctly, without hand-rolling it, at the cost of a large transitive dependency tree (etcd client code, gRPC, OpenTelemetry, none of it actually used directly). Every comparable cert-manager DNS-01 webhook has this same shape, it's the cost of the tool, not this codebase. This isn't npm-style risk either: Go compiles to one static binary at build time, nothing loads or resolves dependencies at runtime, and go.sum is a security feature, not bloat, it cryptographically pins the exact hash of every module version so tampering fails the build immediately.
Configuration
The webhook needs two things at runtime:
GROUP_NAMEenvironment variable: the custom API group this webhook registers under (must match thegroupNameset in theIssuer/ClusterIssuer's webhook solver config).--tls-cert-file/--tls-private-key-fileflags: paths to a serving certificate for the webhook's own aggregated-API endpoint. Required explicitly, the underlying server framework does not fail or warn if these are omitted, it silently falls back to an ephemeral self-signedlocalhostcertificate instead (seelessons_learned.mdinhomelab-docsfor the full symptom trail).
It also needs a Kubernetes Secret holding the DNS provider's API token, referenced by name via the Issuer's own solver config (apiKeySecretRef), read from the namespace of the resource being processed.
Local test loop
An isolated kind cluster with cert-manager installed, the built image loaded via kind load docker-image, and a real Certificate requested against Let's Encrypt's staging endpoint is the fastest way to validate a change without touching any real infrastructure or burning a production rate limit. Full worked example (RBAC, the webhook's own serving cert via cert-manager itself, an Issuer, a test Certificate) is documented in homelab-docs's journal alongside this project's own validation of this exact webhook.
License
See LICENSE.md.