* Add UniFi OS Server deploy hook
Uses UniFi OS Server's local REST API (login, list, upload, activate,
remove superseded) since it stores certificates in its own Postgres
database rather than flat config files, unlike the Cloud Key/UDM
hardware covered by the existing unifi deploy hook. Tested against
real instances on both macOS and Ubuntu 26.04 (self-hosted, remote).
* Address review: portable sed/grep, scoped HTTPS_INSECURE, fingerprint matching
- Replace GNU-only \n in sed replacement with a portable literal newline
(matches dnsapi/dns_cpanel_uapi.sh, dnsapi/dns_glesys.sh); pipe the
list response through _normalizeJson first for consistent formatting.
- Use grep -F for the domain-name match instead of an unescaped BRE --
a wildcard cert name (*.example.com) broke the regex.
- Drop \W (undocumented, GNU-only) from the cookie lookup in favor of
an anchored `^Set-Cookie: *NAME=` match.
- Scope HTTPS_INSECURE=1 inside the hook (matches deploy/proxmoxve.sh,
deploy/fritzbox.sh) instead of requiring the caller to export it for
the whole acme.sh run, which would also disable verification for the
connection to the ACME CA.
- On a duplicate-certificate response, match the existing entry by
fingerprint instead of taking the first name match -- with more than
one stale entry for a domain, the wrong one could get activated.
- Check the list endpoint's response code before proceeding.
- Save username/password with the "base64" flag (matches
deploy/synology_dsm.sh) since _save_conf wraps values in unescaped
single quotes.
* Rework certificate handling: unique names per upload, drop cleanup
Testing against a real UniFi OS Server showed the server enforces name
uniqueness independently of fingerprint uniqueness, and that activation is
exclusive server-wide regardless of name/domain. A unique name per upload
avoids the name-collision path entirely (previously only handled as a
retry-of-identical-content edge case), and removes the need for the
post-hoc cleanup loop, which risked deleting the wrong entry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Shorten generated certificate name to Unix epoch seconds
Real-hardware testing showed the UniFi OS Server certificate list's name
column is fixed-width and doesn't wrap, so a full human-readable timestamp
overlaps the Expires column and makes both unreadable. Epoch seconds are
still short enough to fit while remaining unique.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add scoped cleanup of old certificate entries, use _time helper
Per review: dropping cleanup entirely went further than the original bug
required, and left old entries (each holding a private key) accumulating
indefinitely. Since every upload now gets a name unique to its domain and
run, cleanup can safely target only entries whose name starts with that
domain -- entries this hook itself created -- excluding the one just
activated. Also swaps date +%s for the core _time helper, and rewrote the
design comments to make them clearer and match the current behavior
instead of the pre-redesign one.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>