Commit Graph
100 Commits
Author SHA1 Message Date
neil 8e5ba60bee deploy/ssh: create the backup directory only when there is a file to back up
Follow-up to 9249c892 (#7249). The mkdir -p ran unconditionally before
the guarded cp calls, so a first deploy left an empty backup directory
behind. Move the mkdir into each guarded block.
2026-09-13 07:50:39 +02:00
neil 666bf75589 Honor an HTTP-date Retry-After when polling an order
HARICA answers a processing order with "Retry-After: <HTTP-date>" set
about two minutes after finalize (discussion 7190). Skipping the date
left the poll loop on its 2s fallback, and 30 rounds ran out 21 seconds
before the time the CA had named, so the issue failed although the
certificate was about to be signed.

Add _httpdate2time, which converts the IMF-fixdate form in shell
arithmetic: GNU, BSD and busybox date each want a different invocation
for it, and %a/%b are locale lookups. _retryafter_seconds prints
delay-seconds as before and turns a date into the seconds left until
then; a date in the past or an unparseable value still prints nothing.
2026-09-11 14:56:58 +08:00
neil efecf2a308 ci: run Pebble with PEBBLE_AUTHZREUSE=0 in PebbleStrict
Pebble reuses a valid authorization in a new order 50% of the time by
default, so the dns manual mode case was a coin flip: a reused
authorization left nothing for the TXT record to answer.
2026-09-11 14:23:38 +08:00
neil cbd68ddc02 Ignore an HTTP-date Retry-After when polling an order
Pebble answers a processing order with "Retry-After: <HTTP-date>". The
poll loop cut the value at the first colon and fed "Fri,11Sep202604" to
"[ -gt 0 ]", which errored with "integer expression expected" on every
round. Add _retryafter_seconds, which prints the header only in its
delay-seconds form, and use it at all four Retry-After sites. The two
sites that already filtered on digits used "[0-9]\+", which Solaris grep
does not support.
2026-09-11 12:42:47 +08:00
neil 9249c89221 Both confirmed and fixed in dev.
1. The four backup cp calls (KEYFILE/CERTFILE/CAFILE/FULLCHAIN) ran
   unguarded. With USE_SCP=yes MULTI_CALL is implicit, so each cp is its
   own ssh call and a missing source aborted the deploy. In batched mode
   it was masked because the exit code is that of the last command.
   Each cp is now wrapped in a remote [ -f ] test.
2. deploy/ssh.sh tested DEPLOY_SSH_FULLCHAIN = "yes" instead of
   DEPLOY_SSH_MULTI_CALL (since 2017). Effect was only that the
   fullchain backup got deferred to the next batch. Fixed as well.

Please upgrade with acme.sh --upgrade -b dev and retest.
2026-09-11 11:51:07 +08:00
neil 15bed65ce1 ci: enable the dns manual mode case in PebbleStrict
TEST_DNS_MANUAL=1 turns on le_test_dns_manual_renew, which answers the
dns-01 challenge through the pebble-challtestsrv that the compose setup
already runs.
2026-09-10 21:56:59 +08:00
neil 63ee7cb16e ci: tolerate 422 when the latest release tag has no workflow_dispatch 2026-09-07 12:33:21 +08:00
neil 94d2f62626 fix 2026-09-04 15:51:12 +08:00
neil 41b6371afa minor 2026-09-04 15:27:35 +08:00
neil f2b0484137 add trigger 2026-09-04 15:27:06 +08:00
neil 7b5a902755 Let an explicit --days or --valid-to outrank the ARI window
ARI has overridden Le_NextRenewTime unconditionally since 3.1.4, so a user
who passed --days never got the schedule they asked for, and --valid-to was
guarded at issue time but not on the renewal check: the guard survived one
run before the next cron rewrote it and saved it back.

An explicit --days or --valid-to now pins the schedule. The window is still
taken when it is earlier than what the user asked for, so a CA can pull an
urgent renewal forward but can never push a pinned renewal back.
Le_RenewalDays is only written to the domain conf when --days was actually
passed, so its presence there is what marks a schedule as pinned.

A fixed-date --valid-to opts out of ARI entirely: that cert is not renewed
automatically at all, so pulling it forward would change what it does, not
just when it renews.

Both call sites go through the new _calc_ari_renew_time.
2026-09-01 20:26:34 +08:00
neil 4a3f8b5dea Wait for the order to be ready instead of failing the finalize 2026-09-01 18:59:56 +08:00
neil 08ac83459d Treat alreadyRevoked as a successful revocation 2026-08-31 09:24:41 +08:00
neil 2b7487ba72 Back off between retries instead of a flat two seconds 2026-08-30 21:24:02 +08:00
neil 19efdf269a Retry a gateway error from the CA instead of failing the order 2026-08-30 20:47:24 +08:00
neil cdca555cad Add OPNsense and HardenedBSD to CI 2026-08-30 17:46:48 +08:00
neil cce4a28b99 Fix the standalone port check on the bsds, macos and haiku 2026-08-30 17:39:57 +08:00
neil 4756183e30 Never truncate the conf file when a saved value breaks the rewrite sed
A value holding a backslash-digit sequence (a backreference to sed) or an
embedded line break made _setopt's replace command fail after the shell
had already truncated the conf file, wiping the whole domain conf; the
next renewal then fails with an empty Le_API and no validation method.
Same class as #2426, which escaped only '&' and '|'.

Escape the backslash too, write the sed output back only when sed
succeeds, reject values holding a line break, and rewrite the file with
printf instead of echo in the append path and in _clear_conf: dash's
builtin echo interprets backslash escapes and corrupted such values on
every rewrite.

https://github.com/acmesh-official/acme.sh/issues/7213
2026-08-30 16:02:57 +08:00
neil 6e1deacac0 dns_azure: never read or persist AZUREDNS_BEARERTOKEN from account.conf
Versions up to 3.0.9 cached the internally-acquired access token as
SAVED_AZUREDNS_BEARERTOKEN. 3.1.0 repurposed that variable for
user-supplied bearer tokens, so after an upgrade the stale cached token
was read back as if user-supplied, skipped the refresh path, and failed
renewals with 401 forever once expired.

A bearer token is short-lived, so persisting it is never useful: take it
from the environment only, and clear any stale saved value on the next
run.

fix https://github.com/acmesh-official/acme.sh/issues/7218
2026-08-30 15:42:27 +08:00
neil b1a8eb1c95 installcronjob: match the stale cron path without grep -F 2026-08-20 08:40:49 +08:00
neil e0c0297ba3 fix cronjob 2026-08-19 22:50:03 +08:00
neil 1cbd223386 deploy/unifios: document UniFi OS hardware support, not just self-hosted
The certificate REST API this hook drives is UniFi OS's own, not
specific to the self-hosted UniFi OS Server: user reports confirm it on
a UDM Pro (UniFi OS 5.1.26) and a UCG Fiber (5.0.16). Reframe the scope
around the endpoint rather than the product line, state that the choice
between unifi and unifios is local/SSH file access vs remote REST API,
and note that the management port is 11443 on UniFi OS Server but 443
on hardware, so DEPLOY_UNIFIOS_HOST must be set there.
2026-08-17 13:42:10 +08:00
neil 5180911929 fix https://github.com/acmesh-official/acme.sh/issues/7195#issuecomment-5281002963 2026-08-14 12:15:15 +08:00
neil 5ff7f0a4e7 Mirror the tag object, not the commit, in vtag.yml
The v-prefixed mirror was created from github.sha, so for an annotated or
signed tag it would point at the commit and drop the signature: "git
verify-tag v3.1.3" fails with "cannot verify a non-tag object of type
commit" while "git verify-tag 3.1.3" succeeds. Resolve refs/tags/<tag>
and mirror whatever object it points at instead, which keeps the current
behaviour for lightweight tags. Also move the workflow expressions into
env instead of interpolating them into the shell command.
2026-08-14 11:53:43 +08:00
neil 4a3bc2c919 Fix dns_netcup reporting a bogus 4013 instead of the real zone error
The zone lookup walked the challenge name from the right and ended up
asking netcup for the full "_acme-challenge.<domain>" as a zone name.
That can never be a zone, so netcup answered 4013 "Validation Error",
which replaced the real 5028 "The zone <domain> could not be found" as
the error shown to the user.

Stop one label short of the full name, and fail explicitly when no zone
matched, reporting the last API response plus what to check. Before, a
run where every candidate returned 5028 fell through to logout and
returned success.
2026-08-10 10:00:26 +08:00
neil 05367d3598 Listen on both IPv4 and IPv6 in standalone mode by default
socat binds a single family unless told which one: up to 1.7.x the
default IP version for TCP-LISTEN is 4, and 1.8.0 made it "no
preference", which resolves to whatever getaddrinfo and bindv6only
happen to give. So an order carrying both an IPv4 and an IPv6
identifier could never pass both http-01 challenges.

Bind one socket per family instead, with ipv6only on the IPv6 one so
the two do not collide. IPv4-mapped IPv6 addresses are not a portable
alternative, OpenBSD does not support them at all. The IPv6 listener
is best effort, a host without IPv6 still gets the IPv4 one. The
python fallback does the same. --listen-v4 and --listen-v6 keep
forcing a single family, and passing both now means both.

Le_Listen_V4 and Le_Listen_V6 were mutually exclusive in the domain
conf, which silently dropped one of them on renewal, and
_starttlsserver let -4 win when both were set.

Fixes #7185
2026-08-08 13:09:30 +08:00
neil f67be78ff4 Fix dns_namecheap ignoring IsOurDNS when matching the root zone
_get_root_by_getList() matched the candidate suffix as an unanchored
substring of the whole domains.getList response and never looked at the
IsOurDNS attribute. A domain parked on Namecheap's webhosting DNS is
listed with IsOurDNS="false", yet it was still accepted as the root zone,
so _get_root() returned success and the domains.dns.getHosts probe that
would have found the real zone never ran. Every following getHosts call
was then refused with error 2030288 "not using proper DNS servers" and
the challenge failed with "invalid tld".

Match the exact <Domain Name="..."> entry instead and require
IsOurDNS="true", so a subdomain delegated to Namecheap BasicDNS/FreeDNS
under a parent that is not on Namecheap DNS now resolves to its own zone.
Matching the entry exactly also drops the old substring/regex match, in
which the dots of a domain matched any character.

Fixes #7178
2026-08-06 19:36:26 +08:00
neil 9aad4dcbd5 Fix multideploy MULTIDEPLOY_FILENAME conf read and allow an absolute path
_getdeployconf assigns and exports the variable, it does not print the
value, so wrapping it in a command substitution ran it in a subshell and
always yielded an empty string. A MULTIDEPLOY_FILENAME saved by an
earlier run was therefore never restored on renewal and the hook
silently fell back to multideploy.yml. Call it the same way every other
deploy hook does.

Also treat a MULTIDEPLOY_FILENAME starting with '/' as an absolute path
instead of always resolving it under DOMAIN_PATH, so one deploy file can
live outside the certificate directory and be shared by all domains.
Names without a leading '/' keep resolving under DOMAIN_PATH as before.
2026-08-05 23:01:54 +08:00
neil 603a126a7c Fix synology_dsm logging out after the temp admin is already deleted
_temp_admin_cleanup ran before _logout, so the logout request carried
the session id of an account synouser had already removed and DSM kept
the orphaned entry in Connected Users. Swap the order in both terminal
branches, and add the missing _logout to the two post-login error paths
(CRT list failure, certificate not found without SYNO_CREATE).

_logout overwrites the global $response, so the upload-failure branch
prints its error message before calling it.

Reported by @Bertl75 in #7174
2026-08-05 19:56:13 +08:00
neil 5e6c263211 Fix empty finalize URL when resuming a saved DNS-manual order
The decision to resume a pending order is keyed on Le_Vlist, but the
decision to keep Le_OrderFinalize/Le_LinkOrder was keyed on the webroot
being exactly "dns". Any other webroot with a saved Le_Vlist skipped
newOrder and then finalized against an empty URL.

Key both on Le_Vlist, and always clear Le_LinkCert, which is per-run
state that is never read back from the saved domain conf.

Fixes #7177
2026-08-05 19:53:52 +08:00
neil b4925052dd Fix dns_cyon cleanup failing on FreeBSD
_cyon_delete_txt relied on `printf "%b"` to convert a sed-injected literal
`\n` into a real newline, but `%b` also processes the `\"` escapes that the
JSON response is full of. glibc/bash/dash keep the backslash of such an
undefined escape, FreeBSD's printf (sh builtin and /usr/bin/printf alike)
drops it -- so `data-hash=\"..\"` became `data-hash=".."`, the extraction
regex matched nothing, _dns_entries stayed empty and no TXT record was ever
deleted.

Drop the newline injection and use _egrep_o, which already yields one match
per line, then parse each line with sed.

Also feed the read loop a newline-terminated list: `printf "%s"` left the
last line unterminated, so `read` returned non-zero at EOF and the loop
skipped the final entry on every platform.

Verified identical output on FreeBSD 14.3, Linux/bash and Linux/dash.

Fixes #7169
2026-08-02 21:55:52 +08:00
neil ea5e70564d Fix --make-dns-persist-value printing a wildcard TXT record name
For -d '*.example.com' the printed record name kept the literal '*' label
(_validation-persist.*.example.com). The CA never queries that name, so
issuance fails with "No TXT record found for DNS-PERSIST-01 challenge".

Per draft-ietf-acme-dns-persist-01 sec 4 and 10.2 the record is published at
the base domain's Validation Domain Name; the wildcard scope comes from
'policy=wildcard' in the record value (sec 5.1), not from a '*' label in the
record name. Strip the leading "*." in a new _dns_persist_txt_name helper,
and imply --dns-persist-wildcard for a wildcard -d, since without
policy=wildcard the printed record can never authorize the wildcard.

Fixes #7168
2026-08-02 21:47:51 +08:00
neil 9bfcf2cf1a Merge pull request #7128 from achmadalifn4/master
Fix Notify Waha
2026-07-17 21:58:41 +08:00
neil 7cc16cd09a Merge pull request #7126 from acmesh-official/dev
sync
2026-07-14 22:35:07 +08:00
neil 3e64b5e6f5 Merge pull request #7119 from acmesh-official/dev
sync
2026-07-12 10:11:32 +08:00
neil 347cc207cd Merge pull request #7096 from acmesh-official/dev
one-click revert and ban
2026-07-06 17:40:51 +08:00
neil 1651a5a609 Merge pull request #7095 from acmesh-official/dev
sync
2026-07-06 16:37:03 +08:00
neil 0c76c1f211 Merge pull request #7094 from acmesh-official/dev
wiki-guard: use WIKI_GUARD_TOKEN (PAT with read:org) to enumerate org…
2026-07-06 16:28:12 +08:00
neil e00d3cfde3 Merge pull request #7092 from acmesh-official/dev
wiki-guard: log the number of write-access members loaded
2026-07-06 15:24:23 +08:00
neil 4187ec23c1 Merge pull request #7091 from acmesh-official/dev
wiki-guard: trust repo/org members with write access in all rule checks
2026-07-06 15:12:22 +08:00
neil 9f0ef7abcd Merge pull request #7090 from acmesh-official/dev
sync
2026-07-06 14:28:08 +08:00
neil 0e2659b768 Merge pull request #7088 from acmesh-official/dev
add wiki-guard workflow: auto-restore wiki pages deleted or renamed b…
2026-07-06 13:37:00 +08:00
neil f50401a342 Merge pull request #7086 from acmesh-official/dev
sync
2026-07-06 10:37:29 +08:00
neil 992886c4eb Merge pull request #7078 from acmesh-official/dev
sync
2026-07-03 19:56:09 +08:00
neil 3c848adbb7 Merge pull request #7008 from acmesh-official/dev
sync
2026-06-04 22:50:25 +02:00
neil f265c304da Merge pull request #6968 from acmesh-official/dev
sync
2026-05-16 11:17:24 +02:00
neil 7c91ee1fc0 Merge pull request #6949 from acmesh-official/dev
fix format
2026-05-06 20:59:36 +02:00
neil d2780eb04e Merge pull request #6948 from acmesh-official/dev
sync
2026-05-06 20:52:11 +02:00
neil 7735cdf3ab Merge pull request #6937 from acmesh-official/dev
sync
2026-05-02 10:56:54 +02:00
neil 76d1377fc1 Merge pull request #6934 from acmesh-official/dev
sync
2026-04-28 22:22:24 +02:00
neil ed6d1f3447 Merge pull request #6929 from acmesh-official/dev
sync
2026-04-24 23:30:42 +02:00
neil d00b2722ee Merge pull request #6889 from achmadalifn4/dev
Add BytePlus ALB deployment script
2026-04-24 21:46:10 +02:00
neil df49dd2ec9 Merge pull request #6928 from acmesh-official/dev
sync
2026-04-24 21:36:58 +02:00
neil 50dbdd781b fix DEFAULT_RENEW
fix https://github.com/acmesh-official/acme.sh/issues/2217#issuecomment-4155894630
2026-04-05 10:46:29 +08:00
neil 346acc3f33 Update copilot-instructions.md 2026-04-05 10:40:35 +08:00
neil a79bdb9ef3 Merge branch 'dev' of https://github.com/acmesh-official/acme.sh into dev 2026-04-04 22:24:13 +08:00
neil 563415d21f Merge pull request #6895 from acmesh-official/dev
sync
2026-04-04 21:19:05 +08:00
neil c2c5c3cdb7 Update copilot-instructions.md 2026-04-04 21:18:36 +08:00
neil cf9c70a6c7 Update copilot-instructions.md 2026-04-04 21:16:40 +08:00
neil 5d158b1640 Merge pull request #6857 from acmesh-official/dev
sync
2026-03-13 20:19:12 +08:00
neil d08b4de794 Merge pull request #6832 from acmesh-official/dev
sync
2026-03-08 18:51:51 +08:00
neil da5e818907 Merge pull request #6796 from Tra5is/add_technitium_expiry_ttl
Add Expiry TTL option for Technitium DNS API
2026-03-04 15:17:02 +08:00
neil 89c86efc56 Merge pull request #6793 from ecm75/fix_kemplm
fixed checking for existing domain on loadmaster
2026-02-23 19:37:06 +08:00
neil 8304d3e323 Merge pull request #6800 from pgerber/ipv6-debug
Fix IPv6 URL when trying to fetch challenge ourselves for debugging
2026-02-22 22:35:25 +08:00
neil 12f147bf40 Merge pull request #6794 from infinitydev/pvefix
Add error check to Proxmox deploy hooks
2026-02-18 12:14:52 +08:00
neil bdfa988b65 Merge pull request #6436 from invario/localcopy-deploy-hook
Add 'localcopy' deploy-hook
2026-02-14 11:01:40 +08:00
neil 0e93d2bee1 Merge pull request #6786 from alexandergott-afk/dev
Allow more than one DNS server for HA environments #6785
2026-02-13 11:13:50 +08:00
neil f68a758974 Merge pull request #6775 from alexandergott-afk/master
Add some fixes for dns_nsupdate provider
2026-02-09 20:16:49 +08:00
neil 824e7b3d80 Merge pull request #6709 from invario/docker-non-root-supercronic
Docker with non-root using supercronic
2026-02-09 17:43:28 +08:00
neil b79146281c Merge pull request #6767 from dga-nagra/panos-api-key
Fix bug + Allow panos deploy-hook to use PANOS_KEY
2026-02-07 22:15:28 +08:00
neil ab3093d58c Merge pull request #6472 from UncleVic/master
feat: #6471 add message_thread_id to telegram notifications
2026-02-07 22:11:42 +08:00
neil c21db5c5d5 Change shebang to use env for portability 2026-02-07 22:10:48 +08:00
neil 80e39eb63c Merge pull request #6687 from kapouer/ssh-noscp-permissions
Ssh noscp permissions
2026-02-04 18:49:52 +08:00
neil 28c088611a Merge pull request #6440 from jf-lines/dns_infomaniak_API_v2
dns_infomaniak: upgraded to API v2. v1 is deprecated.
2026-02-01 17:15:02 +01:00
neil d8053ed6b2 Merge pull request #6760 from OpusDNS/add-opusdns-provider
[CLOUD-31] Add acme.sh OpusDNS provider
2026-01-24 07:51:13 +01:00
neil e44809c180 Update acme.sh 2026-01-24 07:49:18 +01:00
neil 8c384a92bf Merge pull request #6755 from zbindenp/master
Fix dns_cyon to use correct regex
2026-01-18 14:30:53 +01:00
neil ce2d9e9746 Merge pull request #6485 from Fangliding/master
Fix ipv6 cert cannot be found
2026-01-18 14:29:33 +01:00
neil f39d066ced Merge pull request #6754 from acmesh-official/dev
sync
2026-01-13 21:50:14 +01:00
neil e2882c536b disable notifications for myself
disable notifications for myself
2026-01-13 21:43:46 +01:00
neil 892b3ca219 fix account.conf permission
https://github.com/acmesh-official/acme.sh/issues/6708#issuecomment-3745737079
2026-01-13 21:28:14 +01:00
neil 4de00d4603 Merge pull request #6748 from acmesh-official/dev
sync
2026-01-11 21:50:00 +01:00
neil bc646d120e Merge pull request #6746 from d-kurz/dev
dns_dynv6: Allow challenge strings that contain "id"
2026-01-10 12:54:47 +01:00
neil c58da45917 Merge pull request #6678 from fratoro/master
Update dns_cyon to use unique user-agent and all cookies
2026-01-10 12:52:24 +01:00
neil 9e51432a6f Merge pull request #6745 from acmesh-official/dev
sync
2026-01-06 08:55:01 +01:00
neil 188aa515ce Merge pull request #6724 from h-haaks/base64-encode-pfx-password
Base64 encode pfx password
2026-01-05 21:46:34 +01:00
neil 6a9776b1f0 Merge pull request #6631 from rperper/dev
QUIC.cloud DNS API support (dns_api.sh)
2026-01-05 21:42:13 +01:00
neil 4b278dc1bb Merge pull request #6735 from JensSpanier/dev
Pushover: Remove asterisks
2026-01-05 20:54:00 +01:00
neil 9bf5179b55 Merge pull request #6739 from moaminsharifi/master
Add Virakcloud dns api
2026-01-05 20:51:43 +01:00
neil 06d9ca61a3 Merge pull request #6728 from jwaterwater/feat/qiniu-force-https-config
Feat/qiniu force https config
2026-01-02 15:36:09 +01:00
neil dc6a996cc3 Merge pull request #6731 from jdevera/posix_globs_for_list
Fix `--list` regression in POSIX / Docker environments
2026-01-02 15:34:27 +01:00
neil d795cb4850 Merge pull request #6717 from acmesh-official/ari
Ari
2025-12-27 12:29:55 +01:00
neil 1bd2922bc3 Merge pull request #6716 from acmesh-official/dev
sync
2025-12-27 11:49:21 +01:00
neil 47f24126f5 Update supported OS table in README
add openindiana
2025-12-27 11:47:16 +01:00
neil 76fdac59bc Add OpenIndiana CI workflow and badge
Introduced a new OpenIndiana job to the DNS GitHub Actions workflow for testing, including necessary environment variables and steps. Updated README to display the OpenIndiana workflow status badge.
2025-12-27 11:41:58 +01:00
neil 49a3d586a3 Add OpenIndiana CI workflow
Introduces a GitHub Actions workflow for OpenIndiana to automate testing of shell scripts.
2025-12-27 11:37:39 +01:00
neil 361e7c5ad4 use nfs for vms
use nfs for vms
2025-12-27 11:26:59 +01:00
neil 3ae9711892 Merge pull request #6715 from acmesh-official/dev
sync
2025-12-27 11:22:22 +01:00
neil fc7168e11d change default renew to 30 days
change default renew to 30 days
and fix readme
2025-12-27 11:20:22 +01:00
neil 260df0048b Merge pull request #6241 from tomo2403/multideploy-yaml
Multideploy: Deploy to multiple hooks of the same type
2025-12-27 11:04:17 +01:00