@@ -122,13 +122,15 @@ type TLS struct {
122
122
DNSRaw json.RawMessage `json:"dns,omitempty" caddy:"namespace=dns.providers inline_key=name"`
123
123
dns any // technically, it should be any/all of the libdns interfaces (RecordSetter, RecordAppender, etc.)
124
124
125
- certificateLoaders []CertificateLoader
126
- automateNames []string
127
- ctx caddy.Context
128
- storageCleanTicker * time.Ticker
129
- storageCleanStop chan struct {}
130
- logger * zap.Logger
131
- events * caddyevents.App
125
+ magic * certmagic.Config
126
+ certificateLoaders []CertificateLoader
127
+ unmanagedCertsTicker * time.Ticker
128
+ automateNames []string
129
+ ctx caddy.Context
130
+ storageCleanTicker * time.Ticker
131
+ storageCleanStop chan struct {}
132
+ logger * zap.Logger
133
+ events * caddyevents.App
132
134
133
135
serverNames map [string ]struct {}
134
136
serverNamesMu * sync.Mutex
@@ -238,7 +240,7 @@ func (t *TLS) Provision(ctx caddy.Context) error {
238
240
// certificates have been manually loaded, and also so that
239
241
// commands like validate can be a better test
240
242
certCacheMu .RLock ()
241
- magic : = certmagic .New (certCache , certmagic.Config {
243
+ t . magic = certmagic .New (certCache , certmagic.Config {
242
244
Storage : ctx .Storage (),
243
245
Logger : t .logger ,
244
246
OnEvent : t .onEvent ,
@@ -248,18 +250,14 @@ func (t *TLS) Provision(ctx caddy.Context) error {
248
250
DisableStorageCheck : t .DisableStorageCheck ,
249
251
})
250
252
certCacheMu .RUnlock ()
251
- for _ , loader := range t .certificateLoaders {
252
- certs , err := loader .LoadCertificates ()
253
- if err != nil {
254
- return fmt .Errorf ("loading certificates: %v" , err )
255
- }
256
- for _ , cert := range certs {
257
- hash , err := magic .CacheUnmanagedTLSCertificate (ctx , cert .Certificate , cert .Tags )
258
- if err != nil {
259
- return fmt .Errorf ("caching unmanaged certificate: %v" , err )
260
- }
261
- t .loaded [hash ] = ""
262
- }
253
+
254
+ unmanaged , err := t .loadUnmanagedCertificates (ctx )
255
+ if err != nil {
256
+ return err
257
+ }
258
+
259
+ if unmanaged > 0 {
260
+ t .regularlyReloadUnmanagedCertificates ()
263
261
}
264
262
265
263
// on-demand permission module
@@ -720,6 +718,61 @@ func (t *TLS) HasCertificateForSubject(subject string) bool {
720
718
return false
721
719
}
722
720
721
+ func (t * TLS ) loadUnmanagedCertificates (ctx caddy.Context ) (int , error ) {
722
+ cached := 0
723
+ for _ , loader := range t .certificateLoaders {
724
+ certs , err := loader .LoadCertificates ()
725
+ if err != nil {
726
+ return 0 , fmt .Errorf ("loading certificates: %v" , err )
727
+ }
728
+ for _ , cert := range certs {
729
+ hash , err := t .magic .CacheUnmanagedTLSCertificate (ctx , cert .Certificate , cert .Tags )
730
+ if err != nil {
731
+ return 0 , fmt .Errorf ("caching unmanaged certificate: %v" , err )
732
+ }
733
+ t .loaded [hash ] = ""
734
+ }
735
+ }
736
+ return cached , nil
737
+ }
738
+
739
+ func (t * TLS ) regularlyReloadUnmanagedCertificates () {
740
+ t .unmanagedCertsTicker = time .NewTicker (2 * time .Hour )
741
+ go func () {
742
+ defer func () {
743
+ if err := recover (); err != nil {
744
+ log .Printf ("[PANIC] unmanaged certificates reloader: %v\n %s" , err , debug .Stack ())
745
+ }
746
+ }()
747
+ t .reloadUnmanagedCertificates ()
748
+ for {
749
+ select {
750
+ case <- t .storageCleanStop :
751
+ return
752
+ case <- t .storageCleanTicker .C :
753
+ t .cleanStorageUnits ()
754
+ }
755
+ }
756
+ }()
757
+ }
758
+
759
+ func (t * TLS ) reloadUnmanagedCertificates () error {
760
+ for _ , loader := range t .certificateLoaders {
761
+ certs , err := loader .LoadCertificates ()
762
+ if err != nil {
763
+ return fmt .Errorf ("loading certificates: %v" , err )
764
+ }
765
+ for _ , cert := range certs {
766
+ hash , err := t .magic .CacheUnmanagedTLSCertificate (t .ctx , cert .Certificate , cert .Tags )
767
+ if err != nil {
768
+ return fmt .Errorf ("caching unmanaged certificate: %v" , err )
769
+ }
770
+ t .loaded [hash ] = ""
771
+ }
772
+ }
773
+ return nil
774
+ }
775
+
723
776
// keepStorageClean starts a goroutine that immediately cleans up all
724
777
// known storage units if it was not recently done, and then runs the
725
778
// operation at every tick from t.storageCleanTicker.
0 commit comments