Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modules/caddytls/ondemand.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func (p PermissionByHTTP) CertificateAllowed(ctx context.Context, name string) e

resp, err := onDemandAskClient.Get(askURLString)
if err != nil {
onDemandAskTotal.WithLabelValues("error").Inc()
return fmt.Errorf("checking %v to determine if certificate for hostname '%s' should be allowed: %v",
askEndpoint, name, err)
}
Expand All @@ -162,8 +163,10 @@ func (p PermissionByHTTP) CertificateAllowed(ctx context.Context, name string) e
}

if resp.StatusCode < 200 || resp.StatusCode > 299 {
onDemandAskTotal.WithLabelValues("denied").Inc()
return fmt.Errorf("%s: %w %s - non-2xx status code %d", name, ErrPermissionDenied, askEndpoint, resp.StatusCode)
}
onDemandAskTotal.WithLabelValues("allowed").Inc()

return nil
}
Expand Down
41 changes: 41 additions & 0 deletions modules/caddytls/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/caddyserver/certmagic"
"github.com/libdns/libdns"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

Expand All @@ -40,11 +41,32 @@ import (
func init() {
caddy.RegisterModule(TLS{})
caddy.RegisterModule(AutomateLoader{})

// Initialize metrics definitions.
// Note: We do not register them here. They are registered in Provision()
// to ensure they are attached to the correct Caddy metrics registry.
certificatesObtained = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "caddy",
Subsystem: "tls",
Name: "obtain_total",
Help: "Total number of certificates obtained or renewed",
}, []string{"issuer", "result"})

onDemandAskTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Namespace: "caddy",
Subsystem: "tls",
Name: "on_demand_ask_total",
Help: "Total number of on-demand TLS ask requests",
}, []string{"result"})
}

var (
certCache *certmagic.Cache
certCacheMu sync.RWMutex

// Metrics for TLS certificate management.
certificatesObtained *prometheus.CounterVec
onDemandAskTotal *prometheus.CounterVec
)

// TLS provides TLS facilities including certificate
Expand Down Expand Up @@ -152,6 +174,21 @@ func (TLS) CaddyModule() caddy.ModuleInfo {

// Provision sets up the configuration for the TLS app.
func (t *TLS) Provision(ctx caddy.Context) error {
// Register metrics with Caddy's internal registry.
// We handle AlreadyRegisteredError to support graceful reloads without panics.
if registry := ctx.GetMetricsRegistry(); registry != nil {
if err := registry.Register(certificatesObtained); err != nil {
if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
certificatesObtained = are.ExistingCollector.(*prometheus.CounterVec)
}
}
if err := registry.Register(onDemandAskTotal); err != nil {
if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
onDemandAskTotal = are.ExistingCollector.(*prometheus.CounterVec)
}
}
}

eventsAppIface, err := ctx.App("events")
if err != nil {
return fmt.Errorf("getting events app: %v", err)
Expand Down Expand Up @@ -904,6 +941,10 @@ func (t *TLS) storageCleanInterval() time.Duration {

// onEvent translates CertMagic events into Caddy events then dispatches them.
func (t *TLS) onEvent(ctx context.Context, eventName string, data map[string]any) error {
if eventName == "cert_obtained" {
certificatesObtained.WithLabelValues("local", "success").Inc()
}

evt := t.events.Emit(t.ctx, eventName, data)
return evt.Aborted
}
Expand Down
Loading