go-acme / lego

Let's Encrypt/ACME client and library written in Go
https://go-acme.github.io/lego/
MIT License
7.91k stars 1.02k forks source link

Option to retry failed challenge #297

Open etiennetremel opened 7 years ago

etiennetremel commented 7 years ago

I'm generating multi-domain certificates, something like 20 domains, I often get error because of the challenge (dial udp: i/o timeout, did not return the expected TXT record, etc.) and need to rerun the full command which can take quite some time.

Would it be a good idea to add a flag which allow the user to re-run failed challenge? or add an exponential/custom retry strategy?

xenolf commented 7 years ago

Have you tried using the --dns-timeout flag to increase the timeout?

etiennetremel commented 7 years ago

I see, so it seems that the binary from the latest release doesn't include that flag, see below:

lego --help
NAME:
   lego - Let's Encrypt client written in Go

USAGE:
   lego [global options] command [command options] [arguments...]

VERSION:
   v0.3.1-0-g96a2477

COMMANDS:
   run      Register an account, then create and install a certificate
   revoke   Revoke a certificate
   renew    Renew a certificate
   dnshelp  Shows additional help for the --dns global option
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --domains, -d [--domains option --domains option]            Add domains to the process
   --server, -s "https://acme-v01.api.letsencrypt.org/directory"    CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.
   --email, -m                              Email used for registration and recovery contact.
   --accept-tos, -a                         By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
   --key-type, -k "rsa2048"                     Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384
   --path "/home/etremel/workspace/src/bitbucket.org/xivart/.lego"  Directory to use for storing the data
   --exclude, -x [--exclude option --exclude option]            Explicitly disallow solvers by name from being used. Solvers: "http-01", "tls-sni-01".
   --webroot                                Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge
   --http                               Set the port and interface to use for HTTP based challenges to listen on. Supported: interface:port or :port
   --tls                                Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port
   --dns                                Solve a DNS challenge using the specified provider. Disables all other challenges. Run 'lego dnshelp' for help on usage.
   --help, -h                               show help
   --version, -v                            print the version

Building the Docker image from the source allow use to use it:

docker run -t -i lego -help
NAME:
   lego - Let's Encrypt client written in Go

USAGE:
   lego [global options] command [command options] [arguments...]

VERSION:
   0.3.1

COMMANDS:
     run      Register an account, then create and install a certificate
     revoke   Revoke a certificate
     renew    Renew a certificate
     dnshelp  Shows additional help for the --dns global option
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --domains value, -d value   Add domains to the process
   --csr value, -c value       Certificate signing request filename, if an external CSR is to be used
   --server value, -s value    CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v01.api.letsencrypt.org/directory")
   --email value, -m value     Email used for registration and recovery contact.
   --accept-tos, -a            By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
   --key-type value, -k value  Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384 (default: "rsa2048")
   --path value                Directory to use for storing the data (default: "/.lego")
   --exclude value, -x value   Explicitly disallow solvers by name from being used. Solvers: "http-01", "tls-sni-01".
   --webroot value             Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge
   --http value                Set the port and interface to use for HTTP based challenges to listen on. Supported: interface:port or :port
   --tls value                 Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port
   --dns value                 Solve a DNS challenge using the specified provider. Disables all other challenges. Run 'lego dnshelp' for help on usage.
   --http-timeout value        Set the HTTP timeout value to a specific value in seconds. The default is 10 seconds. (default: 0)
   --dns-timeout value         Set the DNS timeout value to a specific value in seconds. The default is 10 seconds. (default: 0)
   --dns-resolvers value       Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use Google's DNS resolvers.
   --pem                       Generate a .pem file by concatanating the .key and .crt files together.
   --help, -h                  show help
   --version, -v               print the version

I have hit the weekly rate limit, I will try again next week and let you know if that --dns-timeout helped.

xenolf commented 7 years ago

Did it help @etiennetremel ?

etiennetremel commented 7 years ago

@xenolf sorry for this late reply, I still get error message related to the challenge, I used --dns-timeout=60 then get the the same error message [...]did not return the expected TXT record[...]. Should I use a higher value, ie 120?

This time, on 40 domains only 1 domain failed. They are all sub-domains so when I try again I get a rateLimited message from acme but looking at the letsencrypt rate limits page, it seems possible to combine them into a single certificate. Unfortunately I didn't find any documentation here, maybe you have some tips?

xenolf commented 7 years ago

Are you passing all of your domains into one command or are you running lego 40 times? The former will already create a so called SAN certificate which has all your domains on it. Which of the rate limits are you hitting?

etiennetremel commented 7 years ago

I'm running the following command, multiple domain at the same time:

lego --dns-timeout=60 \
  --domains=test-1.domain.com \
  --domains=test-2.domain.com \
  --domains=test-x.domain.com \
  --email=email@address.com \
  --dns=cloudflare \
  --accept-tos run

The the rate limit I'm facing is Error creating new cert :: Too many certificates already issued for domain.com

jj777 commented 7 years ago

Hi, I'm facing this issue (DNS timeout) not existing on the binary version - Google DNS isn't propogating a TXT record fast enough for one server.

Would you be able to build a binary that has this supported?

rwngallego commented 6 years ago

@etiennetremel were you able to solve the problem?

etiennetremel commented 6 years ago

Unfortunately I can't recall, I guess I just dropped the idea to do it this way.

Atemu commented 8 months ago

This is still an issue. I've set lego to query the authorative name server (in my case: ns1.desec.io) but somehow the challenge still fails with

acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.... - check that a DNS record exists for this domain

I'd like lego to retry at least once after some time when this happens.