Is certbot certonly --renew-with-new-domains executing the hook-deploy scripts if the cert is renew


I am not sure if this is the category to post it, but I can’t find information in the Documentation or over the internet.

We have the following command which is executed with each app deployment:

certbot certonly --non-interactive --dns-route53 --cert-name --domain --domain --keep-until-expiring --renew-with-new-domains --rsa-key-size 2048 --email --agree-tos

If the certificate is renew because there are new domains on the list, or because just it is near the expiration day and the deploy happen before the cron job certbot renew is executed, are the scripts in /etc/letsencrypt/renewal-hooks/deploy executed? or they are only executed when the certificate is renew with the certbot renew option?

In case that script is not executed with certbot certonly anyway the certificate is renew, how we can deal with it? Adding the following option maybe?

--deploy-hook /etc/letsencrypt/renewal-hooks/deploy/

Thanks in advance,

1 Like

Deploy hooks are indeed executed during both issuance (e.g. certbot certonly) and renewal (i.e. certbot renew).

I did following your instruction but it not work, can you send me other ways ? Many thanks

So I happened to have a terminal still open in which I issued a new certificate a few days ago, and it ran my deploy hook in /etc/letsencrypt/renewal-hooks/deploy, so I thought you’d be good, but I now see it was treated like a renewal because it was an expansion of an existing certificate.

So certbot certonly will run your deploy hook if you are adding names to an existing certificate, but will not if you are creating a new certificate entirely. Sorry for the incorrect information.

You can use /etc/letsencrypt/hooks/post instead, but IIRC your hook will run every time certbot runs, even if it doesn’t actually renew the certificate because it isn’t due for expiry yet. You could also just run your hook once in the script that calls certbot.

I wonder if this is a bug? As a deploy hook specified on the command line with --deploy-hook does run when requesting an entirely new certificate…


Thanks for the reply, I just had time to run some tests as well.

So, to be clear at what @Patches is saying, it only will run when new domains (names) are added and --expand is specify?

I just test to add new domains to a existing certificate using the main post command:

certbot certonly --non-interactive --dns-route53 --cert-name --domain --domain --keep-until-expiring --renew-with-new-domains --rsa-key-size 2048 --email --agree-tos

and it doesn’t executed the --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/ scripts.

I will try soon to do a new test using --expand and post the results.

I didn’t explicitly pass --expand in the terminal session I happened to have open previously, I just accepted certbot’s offer to expand the existing certificate when it asked me to. Perhaps that makes a difference?

@schoen @bmw @joohoi instead of us guessing from our past logs perhaps you can confirm whether deploy hooks are supposed to run during initial issuance, expanding an existing certificate, or just renewal? And maybe why, because generally I always run my deploy hook manually after issuance anyway? Thanks!

Yes, deploy hooks in contrary to the old, deprecated renewal hooks (a legacy system not to be confused with renewal-hooks directory) are supposed to run on every certificate issuance. That excludes --dry-run too by the way.

Some pointers I noticed from the discussion:

Did you define this on your command line? All executable files under /etc/letsencrypt/renewal-hooks/deploy/ directory are supposed to run automatically by Certbot upon certificate issuance. You shouldn't have to define the --deploy-hook for scripts in this directory explicitly.

That said, please make sure that the deploy script you wish to get run on issuance is in fact executable in addition to being readable by the Certbot user (typically root).

This is what I get:

john@dynamite:/etc/letsencrypt/renewal-hooks$ sudo certbot certonly --manual --manual-auth-hook="/home/john/Documents/Projects/Software/ACME/duckdns/" --manual-cleanup-hook="/home/john/Documents/Projects/Software/ACME/duckdns/" --preferred-challenges=dns-01 -d
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for

NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
(Y)es/(N)o: y
Waiting for verification...
Cleaning up challenges

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   Your cert will expire on 2018-12-04. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:
   Donating to EFF:          

john@dynamite:/etc/letsencrypt/renewal-hooks$ certbot --version
certbot 0.23.0
john@dynamite:/etc/letsencrypt/renewal-hooks$ cat deploy/ 
echo "deploy hook"
logger -t certbot-hooks "deploy hook"
john@dynamite:/etc/letsencrypt/renewal-hooks$ ls -l deploy/
total 4
-rwxr-xr-x 1 root root 69 Sep  5 12:04

The output of does not appear in the certbot output nor in syslog. It does appear in both when I subsequently run certbot renew --force-renewal --cert-name, and it also appears if I pass the hook script explicitly via the --deploy-hook command line option.

Oh, you are absolutely correct here. I checked out the relevant part of the code and it looks like the deploy hook only gets called if there’s no pre-existing lineage (defined by --cert-name) present. I’ll bring this issue up with the rest of the team, and we’ll decide if we should update our documentation or file an issue regarding this.

So the current behavior regardless of documentation is: If --cert-name is defined on the command line, and a certificate lineage with that name exists, deploy hooks do not get called. This is definitely unintended, and we’ll figure out the best way to fix the issue. Thanks everyone for digging in to this!


The rules around when Certbot hooks are run are overly complicated unfortunately. I'm hoping we can change this in the next 6 months or so, but I can answer questions about how things work now.

Executables in /etc/letsencrypt/renewal-hooks/post are only run with the renew subcommand when renewal is attempted. If you run certbot renew and none of your certificates need to be renewed, no hooks are run.

Deploy hooks defined in a global configuration file or the command line with --deploy-hook are run any time a new certificate is successfully obtained (and you're not using --dry-run). This is true whether it is the first time obtaining the certificate, you're expanding a certificate lineage to contain new domains, or you're just renewing an existing certificate with no other changes. Whether you're using the certonly, run, or renew subcommands also does not matter.

If you obtain a certificate with --deploy-hook set, the path to the hook is saved in the renewal configuration file in /etc/letsencrypt/renewal. You can then run certbot renew without setting --deploy-hook and the saved deploy hook will be run when the certificate is renewed.

Executables in /etc/letsencrypt/renewal-hooks/deploy are a little different. All hooks in /etc/letsencrypt/renewal-hooks are supposed to only run during renewal with the renew subcommand. This behavior is documented, but a bit hard to find. It's under User Guide — Certbot 2.7.0.dev0 documentation in the paragraph starting with "You can also specify hooks by placing files in subdirectories of Certbot’s configuration directory." Clarify and expand renewal-hook documentation · Issue #5935 · certbot/certbot · GitHub aims to improve this documentation.

While that was the intended behavior, you all found a bug! Executables in /etc/letsencrypt/renewal-hooks/deploy are also being run when an existing certificate lineage is renewed with other subcommands. I created Hooks in /etc/letsencrypt/renewal-hooks/deploy are running without using the renew subcommand · Issue #6346 · certbot/certbot · GitHub to address this. While I'm open to other options, we'll probably go back to the intended behavior of only running hooks in the renewal-hooks directory with the renew subcommand.


Hi all,
We here quite busy with a migration and now I can back to this research:

Yes, now I can confirm it, If I have a certificate for the following domains names and is added as a new domain for the actual certificate renewal-hooks are executed with the following command (which add

certbot certonly --non-interactive --dns-route53 --cert-name --domain --domain --domain --keep-until-expiring --renew-with-new-domains --rsa-key-size 2048 --email --agree-tos

It is as expected, and this is the returning output from certbot

// [...]
Running deploy-hook command: /etc/letsencrypt/renewal-hooks/deploy/
Running deploy-hook command: /etc/letsencrypt/renewal-hooks/deploy/

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
// [...]

But, beside the output the command is not in real executed, I am not sure why, still debugging it:

# ls -l /etc/letsencrypt/renewal-hooks/deploy
total 8
-rwxr-xr-x 1 root root 38 Aug 28 10:45
-rwxr-xr-x 1 root root 35 Sep  4 14:45
# cat /etc/letsencrypt/renewal-hooks/deploy/ 

systemctl reload apache2
# cat /etc/letsencrypt/renewal-hooks/deploy/ 
echo "I run" > /tmp/le

If I execute it directly from the console like:

# /etc/letsencrypt/renewal-hooks/deploy/

But, unless this quote:

the renewal-hooks/deploy against the output log of the command, supposedly are executed in a cert renewal because a new domain was added to an existing certificate but without call the renew subcommand.

Maybe it is in the output of the command but not in real executed? Then could be a bug.

I will update the post when I had more information.

Okay, now I just see it more in detail.. the /renewal-hooks/deploy are supposedly to don't be executed on a cert renewal if it is now under the renew subcommand.

I would recommend actually change the intended behavior and run the hook for any cert renewal behind the subcommand, because it is 1) more logic 2) more useful.

I will mention our use case:
We use LE but also AWS with Cloudfront (CF) and Elastic Load Balancer (ELB) which need to have the SSL certificate to works, CF and ELB take the certificate from AWS Certificate Manager (ACM), then when we deploy our app, we want if the certificate is renew executed a script which use AWS CLI to upload the new certificate.

But we are not running the renew subcomand on each deployment, we run certbot certonly --non-interactive --keep-until-expiring --renew-with-new-domains .. (full command in previous comment).. so if a new certificate is expired because a new domain is added to the actual cert (or removed) we expect that the renewal-hooks/deploy because the cert was renew with a new domain.

If renewal-hooks/deploy scripts are executed only over renew subcomand, how is possible that certbot execute a script also when the cert is renew because not expiration but another cause like a new domain? (but only in that case, we don't want to upload the certificate to AWS ACM if it was not changed).


This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.