Deploy-hook error

certbot 5.6.0 Ubuntu 22.04

Following situation: I ran a certbot renew --force-renewal

Saving debug log to /var/log/letsencrypt/letsencrypt.log


Processing /etc/letsencrypt/renewal/mydomain.de.conf


Renewing an existing certificate for mydomain.de and 42 more
Hook 'deploy-hook' ran with output:
...
Hook 'deploy-hook' ran with error output:
writing RSA key
Reloading apache server after certificate renewal


Congratulations, all renewals succeeded:
/etc/letsencrypt/live/mydomain.de/fullchain.pem (success)


root@post:~#
`

letsencrypt.log contains the line:
2026-05-24 11:26:44,257:WARNING:certbot.display.ops:Hook 'deploy-hook' ran with error output: writing RSA key
The line "writing RSA key" comes from a line within my deploy-hook script:

openssl rsa -in $PRIVKEY -out key-pkcs1.pem -traditional

The return code of that command is 0
of the deploy-hook script is an

exit 0

I'm wondering why it says that deploy-hook ran with error output.

Probably a permissions problem. Did you try running certbot with sudo ?

Also, are you sure the source key is RSA ?

The source key is RSA or worded differently: the conversion works, the target key is in the appropriate format. The source key the privkey.pem from Letsencrypt. How else can I check the property of the source key?

I ran the certbot command being root.

NB: key_type = rsa is in the conf-file.

Please show the deploy-hook command.

certbot 5.6.0 Ubuntu 22.04

I just ran a

certbot renew --force-renewal .

How can I determine when certbot will be renewing automatically next time?

Do not use the --force-renewal flag.

It will renew the cert when Let's Encrypt says it's time to do so, which will ordinarily be when 2/3 of the cert's lifetime has expired.

certbot 5.6.0 ubuntu 22.04

Somehow I messed the certificate timeline a bit:

In the past I had certbot running and periodically it updated the cert files in /etc/letsencrypt/archive/mydomain.de. Besides the apache2 webserver, which received he files by the symbolic link mechanism between the live and the archive directories, I was running a mail server (CommuniGate). This server received its certs by loading them manually every three months through its GUI.

Recently I finally managed to feed the certs to the CG-Server by a CLI script.
The last cert was valid up to June, 10th, 2026. certbot doesn't know of that date, since it has proceeded meanwhile in its "one month before expiration"-schedule. Through my recently enforced renewal I caused the cert to expire on Aug, 22nd. That would mean, that cerbot would renew on around Jul, 24th.

Can I tweak certbot in such a way, that it generates a certificate valid up to a date of July 10th
and then starts the generation of the "one month before expiration"-schedule on June 10th? Yes, it may sound awkward, but I would not like to wait until July just to test whether my automated (deploy-hook) works.

Let's encrypt currently offer three certificate lifetimes depending on which profile you use:

  • 90 days (classic) the default
  • 45 days (tlsserver)
  • 160 hours (about 6 days) (shortlived)

These can be selected using the --preferred-profile option in certbot.

The shortlived profile would give frequent renewals which might help you.

Can't you run your hook directly to test whether it works or not? In fact, you should do that to debug why your openssl command fails (in your other thread).

You can also test using Certbot's renew like:
certbot renew --dry-run --run-deploy-hooks

That will not update your production certs so your hook will run using the most recently issued production cert. See: User Guide — Certbot 5.7.0.dev0 documentation

Thanks. I already knew about that --dry-run but lost that out of focus.
It works, despite of this little glitch:

Hook 'deploy-hook' ran with error output:
 writing RSA key

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: 

As said, this `writing RSA key` comes from the lines in the deploy-hook script:

` #!/bin/bash
CERTFILE=/etc/letsencrypt/live/mydomain.de/cert.pem
PRIVKEY=/etc/letsencrypt/live/mydomain.de/privkey.pem
CHCHAIN=/etc/letsencrypt/live/mydomain.de/fullchain.pem
umask 027
openssl rsa -in $PRIVKEY -out key-pkcs1.pem -traditional `

And what happens if you run that openssl command using the -in privkey for your latest cert?

root@post:~# echo $PRIVKEY
/etc/letsencrypt/live/mydomain.de/privkey.pem

openssl rsa -in $PRIVKEY -out key-pkcs1.pem -traditional
writing RSA key
root@post:~# echo $?
0

Then I'd double check the user and $PRIVKEY when running from Certbot

Add some debug lines to your script such as

date >>~/myhook.log
whoami >>~/myhook.log
echo PRIVKEY: $PRIVKEY >>~/myhook.log

Also check the permissions for the existing key-pkcs1.pem

It doesn't appear that there's an issue, openssl is just telling you that it's writing the key. The reason why stderr (error output) is used for this is in case a pipe is used e.g.

openssl rsa -in $PRIVKEY | openssl sha256

If standard output was used for writing RSA key then it would become part of the digest.

certbot will tell you if the hook was unsuccessful, otherwise the error output looks normal[1].


  1. If you are using a shell script, add set -x to the start so that it exits in case of an error â†Šī¸Ž

certbot 5.6.0 Ubuntu 22.04

Just a question: I saw the directories renewal and renewal-hooks.
In renewal there is a conf-file, mydomain.conf, with a section renewal-params and a line
renewal-hook=.

When I put there a file with full path, like renewal-hook=/root/myscript, I assume I can be safe that the absolute filename is being used.
And the other way around: when I write renewal-hook=myscript, is then the script taken when it is deposited in /etc/letsencrypt/renewal-hooks/deploy/myscript ?

See this docs section for --deploy-hook setup and usage: User Guide — Certbot 5.7.0.dev0 documentation

But, you should use an absolute path when specifying --deploy-hook.

The Certbot renewal config file should not be modified manually. It is easy to make small typos that cause problems. For example, it is not renewal-hook= in that config file.

Instead, use the reconfigure command :slight_smile:

certbot help reconfigure
certbot reconfigure --cert-name example.com --deploy-hook /path/to/hook.sh

If reconfigure is successful it will update the renewal config file

The various hooks directories are when you want the same hook to run for every cert you manage with Certbot. Personally I prefer setting a --deploy-hook for any cert that needs it. Otherwise, hooks under the renewal-hooks directory run for every cert and your hook should handle any future case getting a cert using Certbot

My question among others was "when will certbot renew next time?", but it had gone to rack somehow due to 2 questions have been merged into one. I can look at the certs expiration date and subtract 30 days from this. But is there a way to obtain this date (exact time) by asking a timer? I'm too lazy to calculate the date and I'd rather hear it from certbot saying it by itself.

sudo systemctl list-timers | grep certbot
Tue 2026-05-26 21:19:00 CEST 11h left Tue 2026-05-26 01:55:04 CEST 8h ago snap.certbot.renew.timer snap.certbot.renew.service

This tells me, when the new check will be run but it doesn't tell me when it will actually renew:

root@post:~# systemctl status snap.certbot.renew.timer
● snap.certbot.renew.timer - Timer renew for snap application certbot.renew
Loaded: loaded (/etc/systemd/system/snap.certbot.renew.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Sun 2026-05-24 11:06:51 CEST; 1 day 23h ago
Trigger: Tue 2026-05-26 21:19:00 CEST; 11h left
Triggers: ● snap.certbot.renew.service

May 24 11:06:51 post.mydomain.de systemd[1]: Started Timer renew for snap application certbot.renew.

What shows?:
certbot certificates

Well, it was answered by Dan in post #6

You cannot tell for certain when a cert will be renewed in advance. Your version of Certbot supports ARI (ACME Renewal Info). Certbot gets the renewal info from the Let's Encrypt server and renews when instructed to. This is normally when 2/3 of its life has elapsed. But, it may renew much sooner for LE revocation events or may vary based on LE's needs (planned outages, for example).

This is what Dan described just in more detail.

I think we covered techniques for testing your hook in your other recent threads. You should not architect solutions around specific renewal times as they may vary. The --deploy-hook will be run whenever a new cert is issued.

Perhaps add something in your deploy-hook to alert you using your preferred method?