option is independent of the CLI command, so no human intervention
is required.
+ delay - apply an initial wait of "dns-delay" before proceeding. Without
+ "dns", the challenge is submitted after the delay expires. When
+ combined with "dns", the initial wait is applied before starting
+ the DNS pre-checks.
+
none - no readiness condition; the challenge is submitted to the ACME
server immediately without waiting for any external confirmation.
This option cannot be combined with others.
- Multiple values can be combined with a comma so that both conditions must be
- met. The order of the values is not significant. When "cli" and "dns" are
- combined, HAProxy first waits for the CLI confirmation before triggering the
- DNS propagation check.
+ Multiple values can be combined with a comma. When several conditions are
+ specified, HAProxy processes them in the following order: first it waits for
+ the CLI confirmation ("cli"), then applies the initial delay ("delay"), then
+ performs the DNS pre-checks ("dns").
This option is only compatible with the dns-01 challenge type.
directory https://acme-staging-v02.api.letsencrypt.org/directory
dns-delay <time>
- When "challenge-ready" includes "dns", configure the delay before the first
- DNS resolution attempt and between retries. The value is a time expressed in
- HAProxy time format (e.g. "5m", "300s"). Default is 30 seconds.
+ Configure the delay used by "challenge-ready" conditions "delay" and "dns".
+ The value is a time expressed in HAProxy time format (e.g. "5m", "300s").
+ Default is 30 seconds.
+
+ Its role depends on the "challenge-ready" conditions in use:
+
+ delay - the challenge is submitted after this delay expires, without
+ any DNS pre-check.
+
+ dns - the delay between two consecutive DNS resolution attempts.
+ The first probe fires immediately without any initial wait.
+
+ dns+delay - the initial wait before the first DNS resolution attempt, and
+ the delay between subsequent retries.
Note that the resolution goes through the configured "default" resolvers
section, not the authoritative name servers. Results may therefore still be
}
chunk_appendf(&trace_buf, ", st: ");
switch (ctx->state) {
- case ACME_RESOURCES: chunk_appendf(&trace_buf, "ACME_RESOURCES"); break;
- case ACME_NEWNONCE: chunk_appendf(&trace_buf, "ACME_NEWNONCE"); break;
- case ACME_CHKACCOUNT: chunk_appendf(&trace_buf, "ACME_CHKACCOUNT"); break;
- case ACME_NEWACCOUNT: chunk_appendf(&trace_buf, "ACME_NEWACCOUNT"); break;
- case ACME_NEWORDER: chunk_appendf(&trace_buf, "ACME_NEWORDER"); break;
- case ACME_AUTH: chunk_appendf(&trace_buf, "ACME_AUTH"); break;
- case ACME_CLI_WAIT : chunk_appendf(&trace_buf, "ACME_CLI_WAIT"); break;
- case ACME_RSLV_WAIT: chunk_appendf(&trace_buf, "ACME_RSLV_WAIT"); break;
- case ACME_RSLV_TRIGGER: chunk_appendf(&trace_buf, "ACME_RSLV_TRIGGER"); break;
- case ACME_RSLV_READY: chunk_appendf(&trace_buf, "ACME_RSLV_READY"); break;
- case ACME_CHALLENGE: chunk_appendf(&trace_buf, "ACME_CHALLENGE"); break;
- case ACME_CHKCHALLENGE: chunk_appendf(&trace_buf, "ACME_CHKCHALLENGE"); break;
- case ACME_FINALIZE: chunk_appendf(&trace_buf, "ACME_FINALIZE"); break;
- case ACME_CHKORDER: chunk_appendf(&trace_buf, "ACME_CHKORDER"); break;
- case ACME_CERTIFICATE: chunk_appendf(&trace_buf, "ACME_CERTIFICATE"); break;
- case ACME_END: chunk_appendf(&trace_buf, "ACME_END"); break;
+ case ACME_RESOURCES: chunk_appendf(&trace_buf, "ACME_RESOURCES"); break;
+ case ACME_NEWNONCE: chunk_appendf(&trace_buf, "ACME_NEWNONCE"); break;
+ case ACME_CHKACCOUNT: chunk_appendf(&trace_buf, "ACME_CHKACCOUNT"); break;
+ case ACME_NEWACCOUNT: chunk_appendf(&trace_buf, "ACME_NEWACCOUNT"); break;
+ case ACME_NEWORDER: chunk_appendf(&trace_buf, "ACME_NEWORDER"); break;
+ case ACME_AUTH: chunk_appendf(&trace_buf, "ACME_AUTH"); break;
+ case ACME_CLI_WAIT : chunk_appendf(&trace_buf, "ACME_CLI_WAIT"); break;
+ case ACME_INITIAL_DELAY: chunk_appendf(&trace_buf, "ACME_INITIAL_DELAY"); break;
+ case ACME_RSLV_RETRY_DELAY: chunk_appendf(&trace_buf, "ACME_RSLV_RETRY_DELAY"); break;
+ case ACME_RSLV_TRIGGER: chunk_appendf(&trace_buf, "ACME_RSLV_TRIGGER"); break;
+ case ACME_RSLV_READY: chunk_appendf(&trace_buf, "ACME_RSLV_READY"); break;
+ case ACME_CHALLENGE: chunk_appendf(&trace_buf, "ACME_CHALLENGE"); break;
+ case ACME_CHKCHALLENGE: chunk_appendf(&trace_buf, "ACME_CHKCHALLENGE"); break;
+ case ACME_FINALIZE: chunk_appendf(&trace_buf, "ACME_FINALIZE"); break;
+ case ACME_CHKORDER: chunk_appendf(&trace_buf, "ACME_CHKORDER"); break;
+ case ACME_CERTIFICATE: chunk_appendf(&trace_buf, "ACME_CERTIFICATE"); break;
+ case ACME_END: chunk_appendf(&trace_buf, "ACME_END"); break;
}
}
if (mask & (ACME_EV_REQ|ACME_EV_RES)) {
} else if (strcmp(str, "dns") == 0) {
/* wait for the DNS-check to run the challenge */
cur_acme->cond_ready |= ACME_RDY_DNS;
+ } else if (strcmp(str, "delay") == 0) {
+ /* wait for the DNS-check to run the challenge */
+ cur_acme->cond_ready |= ACME_RDY_DELAY;
} else if (strcmp(str, "none") == 0) {
if (cur_acme->cond_ready || (saveptr && *saveptr)) {
err_code |= ERR_ALERT | ERR_FATAL;
goto wait;
/* next step */
- st = ACME_RSLV_WAIT;
+ st = ACME_INITIAL_DELAY;
goto nextreq;
}
break;
- case ACME_RSLV_WAIT: {
+ case ACME_INITIAL_DELAY: {
+ struct acme_auth *auth;
+ int all_cond_ready = ctx->cfg->cond_ready;
+
+ for (auth = ctx->auths; auth != NULL; auth = auth->next) {
+ all_cond_ready &= auth->ready;
+ }
+
+ /* if everything is ready, let's do the challenge request */
+ if ((all_cond_ready & ctx->cfg->cond_ready) == ctx->cfg->cond_ready) {
+ st = ACME_CHALLENGE;
+ goto nextreq;
+ }
+
+ /* if we don't have an initial delay, let's trigger */
+ if (!(ctx->cfg->cond_ready & ACME_RDY_DELAY)) {
+ st = ACME_RSLV_TRIGGER;
+ goto nextreq;
+ }
+
+ for (auth = ctx->auths; auth != NULL; auth = auth->next) {
+ auth->ready |= ACME_RDY_DELAY;
+ }
+
+ /* either trigger the resolution of the challenge */
+ if (ctx->cfg->cond_ready & ACME_RDY_DNS)
+ st = ACME_RSLV_TRIGGER;
+ else
+ st = ACME_CHALLENGE;
+ ctx->http_state = ACME_HTTP_REQ;
+ ctx->state = st;
+ send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: waiting %ds\n",
+ ctx->store->path, ctx->cfg->dns_delay);
+
+ task->expire = tick_add(now_ms, ctx->cfg->dns_delay * 1000);
+ return task;
+ }
+ break;
+ case ACME_RSLV_RETRY_DELAY: {
struct acme_auth *auth;
int all_cond_ready = ctx->cfg->cond_ready;
st = ACME_RSLV_TRIGGER;
ctx->http_state = ACME_HTTP_REQ;
ctx->state = st;
- send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: triggering the resolution in %ds\n",
+ send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: retrying the resolution in %ds\n",
ctx->store->path, ctx->cfg->dns_delay);
task->expire = tick_add(now_ms, ctx->cfg->dns_delay * 1000);
}
/* not all ready yet, retry after dns-delay */
- st = ACME_RSLV_WAIT;
+ st = ACME_RSLV_RETRY_DELAY;
ctx->http_state = ACME_HTTP_REQ;
ctx->state = st;
goto nextreq;