Skip to content

Reload TLS certificate and key on change when -hotreload is set - #771

Open
chiliec wants to merge 1 commit into
adnanh:masterfrom
chiliec:tls-cert-hotreload
Open

chiliec wants to merge 1 commit into
adnanh:masterfrom
chiliec:tls-cert-hotreload

Conversation

@chiliec

@chiliec chiliec commented Sep 22, 2026

Copy link
Copy Markdown

Fixes #393

What

With -secure, webhook loads the certificate/key once via ServeTLS and keeps serving that in-memory copy after the files are renewed on disk (e.g. by certbot), so a renewed Let's Encrypt certificate only takes effect after a restart.

Fix

When -secure is combined with -hotreload, the certificate is now served through tls.Config.GetCertificate (certReloader in tls.go). On each handshake it compares the cert and key files' modification times with the ones it loaded; if either changed, it reloads the pair. If reloading fails (e.g. key temporarily missing mid-renewal), the previously loaded certificate keeps being served and the error is logged. Without -hotreload behaviour is unchanged.

The -hotreload help text and docs/Webhook-Parameters.md mention the new behaviour.

Tests

  • TestCertReloader (new, tls_test.go): generates a self-signed cert, checks the reloader returns it, rewrites cert+key with a new serial and checks the new one is served, then deletes the key and checks the last good certificate is still returned.
  • End-to-end against the built binary: started webhook -secure -hotreload, connected with a TLS client, regenerated the cert with openssl (serial 1 → 2), connected again.
$ go test ./...
ok      github.com/adnanh/webhook       13.871s
ok      github.com/adnanh/webhook/internal/hook
ok      github.com/adnanh/webhook/internal/pidfile

# before this change
before renewal: serial 1
after renewal:  serial 1

# with this change
before renewal: serial 1
after renewal:  serial 2
[webhook] certificate cert.pem reloaded

When webhook serves HTTPS, ServeTLS loads the certificate once at startup
and keeps serving it after the files on disk are renewed, so a renewed
Let's Encrypt certificate is only picked up after a restart.

With -secure -hotreload, the certificate and key are now loaded through
tls.Config.GetCertificate, which checks the files' modification times on
each handshake and reloads the pair when either changed. If reloading
fails the previously loaded certificate keeps being served.

Fixes adnanh#393
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSL Certificates aren't updated upon renewal

1 participant