Certbot - DNS Challenge Guide


I have a few websites which are not publicly available and are used for internal company business only. We have recently started to move everything over to Let’s Encrypt.

I’m struggling to find a definitive answer to this question online: is it possible to automatically renew certs which do not have public http/https? I have seen reference to using the DNS-01 method, but from what I can tell this is not supported by the official cerbot client.

All I want to do is renew certs without having to change my firewall settings each time I do it (as this means it needs to be done manually). Can anyone recommend the best way to do this (and ideally some kind of tutorial?).



I have seen reference to using the DNS-01 method, but from what I can tell this is not supported by the official cerbot client.


There are several references to how to use DNS challenge



It’s supported, but not very comprehensively. You would likely have to write your own scripts to interact with your DNS provider’s API.

You might find it easier to use acme.sh or one of the other bash clients, which come with built-in support for several popular DNS providers.


Thanks - using acme.sh works, but it’s far from ideal. The reason is we like to run everything like this through Jenkins so we have visibility over everything rather than having server side processes which we don’t necessarily see if they fail. In this case, if the cert isn’t due for renewal then the job is marked as unstable because the renewal command fails. That means to keep it clean I need to use the --force flag on the renewal, which means it renews every time the job runs (currently fortnightly). That’s fine for now but isn’t scalable because of the cert per domain limits from Lets Encrypt.

With the certbot we could run the job weekly and if the cert wasn’t due, the job is still stable.


Hmm, I don’t think that should happen. What actual command are you running via Jenkins? AFAIK it marks the build as unstable if it gets a nonzero error code, and acme.sh’s default cron command returns zero for me.


The code I am running is:

/home/jenkins/.acme.sh/acme.sh --renew -d mydomain.com --force

I found the full path was needed and it had to be in the home directory for the jenkins user, or the job would fail because it didn’t recognise the acme.sh command - although when running it manually on the box it was recognised which I couldn’t understand.


I’m using --cron rather than --renew and it works as expected; --renew seems to work differently, in that it returns 0 for successful renewal, 1 for error or 2 if no renewal was needed. I guess you could catch that case with something like this:

/home/jenkins/.acme.sh/acme.sh --renew -d mydomain.com || [[ "$?" -eq 2 ]]

or just use --cron if that suits your needs.

The acme.sh installer adds an include to your .bashrc which sets up an alias; I guess this is not used by Jenkins. If you used the installer, note that it also sets up its own cron job which you may want to remove if you’re using Jenkins instead.


OK, great - thanks for both pieces of advice. I’ll give this a go when I get a bit more time.


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