The nginx plugin is not working

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g., so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is:

I ran this command: certbot renew --dry-run --nginx

It produced this output:

Could not choose appropriate plugin: The nginx plugin is not working; there may be problems with your existing configuration.
The error was: NoInstallationError("Could not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly.")

My web server is (include version): nginx:1.18.0-alpine

The operating system my web server runs on is (include version): centOS 8 (host), alpine 3.7 for the containers

My hosting provider, if applicable, is: IONOS

I can login to a root shell on my machine (yes or no, or I don’t know): yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel): no, SSL

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot): certbot 1.7.0

For what I did so far see

1 Like

certbot runs in a docker-compose setting with nginx which is a proxy to a swarm stack. Creating the certificates (3) were ok with this setup. Now the first is due to renewal and the automatic renewal failed.

I wonder why renewal should be any different from creation. Trying to understand the problem, I found some issues, but they don’t solve the problem.

As this may be related to docker-certbot, I opened an issue there, but nobody seems to listen.

1 Like

Can you try to use certbot renew --dry-run?

1 Like

This is what I did numerous times. I cited the last result. The whole story at

1 Like

First, I’m sorry that nobody has responded to your issue on that repo. I suspect that repo gets a lot less attention than the main Certbot repo.

The Docker image certbot/certbot does not appear to ship with either the Apache or the nginx plugin. That surprises me. I suspect this might be the cause because it is difficult/possibly impossible to interact with a server process which is running in a completely different container/namespace.

Anyway, it looks like the repository was written to use the webroot plugin. So it does not rely on the presence of the Certbot nginx plugin in the first place.

As such, when you renew, you should use only the --webroot plugin, not --nginx. Just calling certbot renew should use the webroot plugin automatically (as it remembers what was initially used), unless you changed it at some point.

I skimmed over your story in your Github issue (sorry), and it appears that you may have tried to install the server plugins or something manually. All I can suggest is that, for the reason I suggested earlier, this could never work in an environment where the webserver and Certbot run in different containers. But webroot, as was implemented originally by, should certainly work.


It shouldn’t, because it doesn’t ship with the apache or nginx daemons either. :wink:

When certbot runs in a container by itself, it only makes sense with webroot or standalone modes (usually proxied by the main http server on the machine).

1 Like

Thank you very much. This makes sense to me. I will have a look and guess that I mixed 2 procedures here which led to the trouble.

1 Like

Thank you. I guess I mixed up 2 procedures. I remember having troubles with both ways – most probably because I didn’t understand fully what was going on.

1 Like


As such, when you renew, you should use only the --webroot plugin, not --nginx . Just calling certbot renew should use the webroot plugin automatically (as it remembers what was initially used), unless you changed it at some point.

This looks promising. It does not use --webroot automatically for some reason, but # certbot renew --dry-run --webroot produces

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator webroot, Installer None
Attempting to renew cert ( from /etc/letsencrypt/renewal/ produced an unexpected error: Missing command line flag or config entry for this setting:
Please choose an account
Choices: ['cbd87596afc3@2020-05-24T15:49:41Z (20a9)', '63e0cd57369e@2020-06-18T16:54:15Z (cee2)', '44db9f584532@2020-06-18T19:17:29Z (db3e)']. Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/ (failure)
  /etc/letsencrypt/live/ (failure)

- - - - - - - - - - - - - - - - - - - - - - - -

What is the syntax for this account approach? An attempt like certbot renew --dry-run --webroot --account cbd87596afc3@2020-05-24T15:49:41Z looks good but leads to

Account at /etc/letsencrypt/accounts/ does not exist. 

Inspecting the logs, I reconstruct as follows:

  • I first worked with the official tutorial involving Apache
  • to this end I had to fire up httpd standalone
  • this would not work because my proxy runs on port 80
  • so I had to shut down my proxy
  • I obtained a certificate

Now this cannot work in production, so I looked for a docker solution and found Nginx and Let’s Encrypt with Docker in Less Than 5 Minutes, i.e. wmnnd. This is the boilerplate for my proxy.


Just calling certbot renew should use the webroot plugin automatically (as it remembers what was initially used), unless you changed it at some point.

This explains why it remembers Apache. How can I change the initial setting?

1 Like

Same with --account '44db9f584532@2020-06-18T19:17:29Z (db3e)' (db3e) does not exist

/opt/certbot # ls -latr /etc/letsencrypt/accounts
total 0
drwx------    3 root     root            23 May 13 22:53
drwxr-xr-x    3 root     root            23 May 24 15:49
drwx------    4 root     root            86 May 24 15:49 .
drwxr-xr-x    9 root     root           261 Aug  6 11:34 ..

Where does this data

Choices: ['cbd87596afc3@2020-05-24T15:49:41Z (20a9)', '63e0cd57369e@2020-06-18T16:54:15Z (cee2)', '44db9f584532@2020-06-18T19:17:29Z (db3e)']. 

come from?

Sorry, my bad…

/opt/certbot # ls -latr /etc/letsencrypt/accounts/
total 0
drwxr-xr-x    3 root     root            23 May 24 15:49 ..
drwx------    2 root     root            64 May 24 15:49 20a9a8143e358826aee1f1a1f58d0b6c
drwx------    2 root     root            64 Jun 18 21:24 cee23e8597839e6c3997716d2577e5d8
drwx------    2 root     root            64 Jun 18 21:28 db3ecf679a03bd2538dc383fb3ac40a1
drwx------    5 root     root           126 Jun 18 21:28 .
/opt/certbot #

Still, this data does not match.

Ok, found it. Choosing one of these Ids seems to work, but produces new errors. I will keep you informed.

1 Like

Got it

The dry run was successful

/opt/certbot # certbot certonly --webroot -w /www -d --dry-run --account 20a9a8143e358826aee1f1a1f58d0b6c
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for
Using the webroot path /www for all unmatched domains.
Waiting for verification...
Cleaning up challenges

 - The dry run was successful.

Some background info:

The main challenge after the crucial hint of @_az regarding --webroot was the .well-known/acme-challenge nginx 404 error, well-known by itself.

To this end I used a dummy file 1234 to test – it delivered 403 Forbidden first and then 404 Not Found.

The follwing proves those problems solved:

# curl ""

2 levels of nginx

Also, both this instance of nginx and that of the real server being proxied had to be corrected:

        location ^~ /.well-known/acme-challenge/ { 
            allow all;
            default_type "text/plain";
#return 404 "==119=====$server_name==========$uri== testing";  # testing
            try_files $uri =404; # /index.html;


        location ~ /\.(?!well-known).* {
            deny all;

        location ^~ /.well-known/acme-challenge/ { 
            allow all;
            root /www;
            default_type "text/plain";
            try_files $uri /index.html;

This took care of the 403 error.

Those instructions differ which reflect my search for the right definition, they can certainly be unified, but I leave it at that – it works.

Intermediate proxy

I have another webserver in between those two acting as proxy to provide caching services. In order to make it work I had to manipulate that one to not cache calls to .well-known

webroot access

Also it was crucial that my proxy nginx had access to the webroot of this domain – an obvious condition not needed otherwise.

      - /root/2proxy/nginx.conf:/etc/nginx/nginx.conf
      - /root/2proxy/nginx/log/:/var/log/nginx/
      - /root/2proxy/nginx/cache/:/etc/nginx/cache
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /var/www/:/var/www/
      - /www/:/www/

This correction took care of the 404 error.

Further strategy

In order to check if the automatic renewal works, I leave it at --dry-run as well.

This is a special solution with dedicated parameters. Looking at the automatic procedure

entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

there may be some quirks to take care of. I might even test it right away.

Hopefully this will work for the other two domains on this server at due time. I’ll check a second server along these lines as well after these lessons learned.

Thank you all very much.

I now understand much better what I am doing here.


You can probably get rid of the location blocks about acme-challenge and just leave

location /.well-known/acme-challenge {
  root /www;

as to why you would deny all all other dotfiles, I have no clue, just deny htaccess and htpasswd in all directories.

1 Like

It’s a common default in configurations because of the unfortunate way many people deploy web applications.


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