How does certbot's --nginx plug-in work in certonly mode?


I'm trying to understand how the --nginx plugin works, in my case. I'm using nginx, and haven't modified anything to its configuration myself. There's no mention of an acme_challenges directory anywhere. It is just my plain old configuration, nothing more.

I'm using the certonly mode, because I don't want certbot to modify my nginx blocks. Please don't tell me that the --nginx plugin finds my blocks and adds the correct lines to them, because I do not use this functionality.

Everything works perfectly fine, but I don't understand how and it bugs me out.

The --standalone plugin doesn't work, which is understandable since it appears it tries to run its own web server on port 80, which is already in use. The --nginx plugin works. How? Does it modify nginx's central configuration on the fly, to create and serve a challenge directory, and then erase its tracks, making sure to reload nginx at the right times? How can I find precisely how the configuration is being modified, then? I'm not comfortable having changes to my web server configuration happen in an opaque way.

Thanks in advance


Hi @Biganon

if you use --nginx, you use that functionality.

To debug - see

there is a --debug-challenges you can use to create a copy of your config files.

If you don't want that, switch to --webroot. That's a raw method that ignores the config files.


Thank you, I understand better now. Indeed, even though thanks to the "certonly" subcommand my nginx configuration files are not durably modified, they are still temporarily modified to answer to the challenge. I have looked at the modifications, don't really understand everything (especially not why the "rewrite [...] $1 break" line is created twice), but it's clearer now.

I'll try and use --webroot, like you suggest, because I don't want anything modifying files on the fly, I don't think it's a good idea.


Welcome to the Let's Encrypt Community, Simon :slightly_smiling_face:

Your concerns regarding the configuration modifications are certainly understood. Modified and/or more complex nginx configurations can conflict with what certbot tries to do.

The line itself is so that the http-01 challenge files can be found when requested by the Let's Encrypt server when you use the nginx authenticator (--nginx). I don't believe that there should be two of them though.

certbot certonly --nginx -d "," --keep-until-expiring

If you want to use the standalone authenticator, you need to stop nginx first, run certbot, then start nginx.

systemctl stop nginx

certbot certonly --standalone -d "," --keep-until-expiring

systemctl start nginx

If you use the webroot authenticator, be sure to reload nginx afterwards. This is better than standalone because it doesn't disrupt nginx operation.

certbot certonly --webroot -w /path/to/your/webroot -d "," --keep-until-expiring

systemctl reload nginx


Hello Jonathan, thank you for your answer!

To be clear, the reloading of nginx you allude to at the very end of your message is there to make sure nginx reloads and serves the fresh certificates, right?


It (gracefully) reloads your new certificate into memory, yes. I could probably reference 1000+ topics in this community of people struggling with "old certificates" being used when they have "new certificates" only to find out (after hours or even months of headache) that they just needed to reload/restart nginx. :wink:

By the by, the --keep-until-expiring, as its name implies, prevents you from accidentally acquiring duplicate certificates and hitting your head on the rate limits. If your certificate isn't close to expiry (within 30 days), certbot just won't acquire a new certificate.

Renewals are treated specially: they don’t count against your Certificates per Registered Domain limit, but they are subject to a Duplicate Certificate limit of 5 per week. Exceeding the Duplicate Certificate limit is reported with the error message too many certificates already issued for exact set of domains.


Thank you for your answers. I've been trying to move from the nginx verification to the webroot one.

I'm doing it with sudo certbot certonly --cert-name --force-renewal -a webroot -w /etc/letsencrypt/www

According to this answer, it's correct.

I have not yet modified my web server configuration to serve the webroot directory, so I expect it to not work. Yet... it works. And I don't understand why.

Adding --staging --dry-run leads to a 404 error output in the terminal, which is expected.

Is there a cache of some sort?


A few clarifications...

--force-renewal should be avoided anytime possible. It forces certbot to acquire a certificate even if you already have one that doesn't need renewal.

--staging --dry-run is actually redundant with --staging being somewhat dangerous.

If you don't specify the domain names with -d then whatever domain names are associated with the current certificate based on --cert-name will be used.

The webroot is simply the path to the directory containing the root of your website. This might be /var/www/html. You need to check your configuration to see where the document root points.

You want to include --keep-until-expiring to avoid hitting the rate limits like you have. It's a safety measure so that if you script the command or accidentally hit enter then you don't need to be concerned.


certbot certonly --webroot -w /etc/letsencrypt/www --dry-run

Testing can be done even if you've hit the rate limits on the production server because it uses the staging server.


certbot certonly --webroot -w /etc/letsencrypt/www --keep-until-expiring --deploy-hook "systemctl reload nginx"


certbot renew

Updated per @Osiris's excellent suggestion below.


You can put the systemctl reload nginx part in the --deploy-hook option so it will automatically reload nginx when certbot succesfully renewed a certificate. See official certbot documentation about renewing for more info. It'll only be stored for that current certificate. If you have multiple certs where you'd like to use the hook, you'd need to run certbot with that extra option for every cert you'd like to enable it. As far as I know, this can be done by certbot renew --cert-name <certificate name from certbot certificates> --deploy-hook "<your deploy hook>"


Thank you griffin. I did modify nginx's configuration so the web root for the challenge URL (http only) would be the directory I've mentioned.

Also, reading a bit made me learn about the verification cache that lasts 30 days. If an account key X has proven to be in control of domain Y, this will be remembered for 30 days.

Finally, I'm very sorry but it was by mistake that I included the domain name Do you think you could edit it out of your message? It will be in the history, but my client won't see that haha. It's OK if you refuse, it's my fault after all.

Cheers, and thanks Osiris too! Great community. Not always easy to understand all the parameters, but with help it's perfect.


Updated my post accordingly. :slightly_smiling_face:

That's correct in terms of the validated authorizations associating an account to identifiers (DNS names).

No problem. Done and done. :slightly_smiling_face:

That's what we like to hear.
We try to make things clear.
It helps to have a beer.
With your success we cheer.