github NeySlim/ultimate-ca-manager v2.217

2 hours ago

What's Changed

Fixed

  • ACME proxy: the dns-01 TXT values computed with the CLIENT account keys are now published next to the upstream CA's value (the proxy knows every client thumbprint), so the propagation pre-checks of lego, Traefik and Caddy find the value they expect and no longer need to be disabled; the extra records are cleaned up with the others (#306, #307)
  • ACME proxy: a client retrying new-order for the same identifiers now gets its still-pending order back (checked against the upstream CA) instead of opening a new upstream order on every attempt, mirroring upstream behavior and stopping order accumulation under retry-happy clients (#303, reported by @gb-123-git)
  • Email notifications skip recipients that are not valid mailbox addresses at send time (one log line names them) instead of handing them to SMTP and bouncing; nothing changes at input time, so "tag only" account contacts keep working (#303, reported by @gb-123-git)
  • Local ACME server: once an authorization is validated, the unused sibling challenges are deprovisioned and no longer listed (RFC 8555 section 7.1.6, matching Let's Encrypt), so clients like Caddy stop seeing leftover pending http-01/tls-alpn-01 challenges next to the validated one; authorizations validated before this change also stop listing their leftover siblings (#303, reported by @gb-123-git)
  • Certificate issue form: the "No template" choice is back in the template selector, so a selected template can be deselected to return to manual mode. The select component silently dropped every empty-value option (a library constraint workaround); those options are now rendered through an internal sentinel, which also restores the "No template" choice in SCEP profiles and the "None (base role only)" choice in user role assignment (#303, reported by @gb-123-git)
  • ACME proxy: several downstream accounts can now order the same domain. The upstream CA reuses one authorization across them (the proxy signs upstream with a single account), and the proxy resolved it to the first account's order, so every other account was refused with 403 "Authorization does not belong to this account". Shared authorizations now resolve to the requesting account's order, the dns-01 automation for a shared challenge fires once instead of once per account, and the cross-account protections are unchanged (#307, contributed by @Hemsby)
  • TSA: timestamp requests no longer fail with 503 "TSA certificate does not include the timeStamping EKU" when the signing CA is a constrained sub-CA whose certificate carries an EKU without timeStamping. It is accepted with a warning like a CA certificate without any EKU; a dedicated end-entity signer lacking the EKU is still refused, and tsa_require_dedicated_cert still enforces the strict mode (#309, contributed by @Hemsby)

Added

  • Guardrails for the admin Base URL: saving a base URL that does not resolve or answer is refused with an explicit error (resend with "force": true to apply anyway), the canonical redirect steps aside whenever the configured host stops resolving instead of redirecting the whole UI into a wall, and starting the service with UCM_DISABLE_CANONICAL_REDIRECT=1 disables the redirect entirely to recover a locked-out instance (#303, reported by @gb-123-git)
  • The certificate applied to the web UI (Settings > HTTPS) is now remembered: when that certificate is renewed (including by the auto-renewal scheduler), the HTTPS files are re-materialized and the service restarts by itself, so the UI never keeps serving the pre-renewal certificate. Regenerating a self-signed certificate clears the binding; on Docker a log line asks for a container restart instead (#303, reported by @gb-123-git)
  • Local ACME server: orders now have a dedicated view (ACME > Local orders) with status filter, per-order deletion and a purge action, and a scheduled task removes expired non-issued orders with their authorizations and challenges every 6 hours, so they stop accumulating forever; issued orders are kept as history (#303, reported by @gb-123-git)
  • Local ACME server: the signing digest for orders that select no certificate profile is now configurable (ACME > Local ACME > Certificate profiles, sha256/sha384/sha512, default unchanged at sha256); profiles that omit their own digest inherit it (#303, reported by @gb-123-git)
  • Optional what's new window after an update: enable "Show release notes after an update" in Settings > Updates (off by default) and every user gets a one-time popup with the installed version, the install date and the release notes the next time a new version is running. Dismissal is per user and follows the account across browsers (#308)
  • The listen address is now configurable: HOST in ucm.env (or the container environment) is honored by the HTTPS server and the HTTP protocol port, not only by the development server. HOST=:: listens on IPv6 and IPv4 at once (dual-stack); the default stays 0.0.0.0. IPv4 clients reaching a dual-stack listener are normalized from ::ffff:a.b.c.d to plain IPv4 before trusted-proxy, rate-limit and audit handling, so existing UCM_TRUSTED_PROXIES values keep matching
  • Dedicated TSA signing certificate — Settings > TSA now has a "Signing certificate" section to point the RFC 3161 timestamp signer at an already-issued end-entity certificate instead of the CA's own certificate. Only certificates whose private key UCM holds and can decrypt and that carry the timeStamping EKU are offered; protocol-enrolled (client-key) and AD CS-proxied certificates are excluded. The signer is resolved by refid at signing time so an in-place renewal is followed automatically, and it is re-checked on every request: an expired, revoked or undecryptable signer fails the request with 503 and an explicit log line and never falls back to the CA certificate. The token embeds the signer's issuer chain (leaf plus its issuing CA chain) when the client asks for certificates, and the ESSCertIDv2 / SigningCertificate signed attribute follows the selected signer. The tsa_require_dedicated_cert toggle is only operable once a usable dedicated signer is saved. With no signer configured (tsa_signer_cert_refid unset) the token is byte-for-byte what it was — existing deployments see no change. No schema change (new tsa_signer_cert_refid SystemConfig key). One-click issuance of a TSA signing certificate is a planned follow-up (#312, contributed by @Hemsby)

📜 Recent release history (last 2 versions)

[2.216] - 2026-08-29

Fixed

  • Translation cleanup across the 8 non-English locales (about 1,100 strings): a February locale sync had left whole sections in English (template pinning, public endpoints, webhooks, remote syslog, expiry alerts, trust store, service restart, audit integrity, SSH CA messages), 15 strings garbled by a broken word substitution in six locales ("Trusted for issuing certificatees", "Password must be at theast 12 characters", "Dandhande backup", "resand the database"), and roughly a hundred half-translated Spanish strings ("Error to eliminar CA", "Waiting for seguridad clave"). Every affected string was retranslated from the English reference; placeholders and technical terms are unchanged
  • The "Create CA" quick action was labelled in French in the German UI (now "CA erstellen", contributed by @gladiac, #304); the same untranslated label is also fixed in Spanish, Italian, Japanese, Portuguese and Ukrainian
  • ACME proxy orders in the Let's Encrypt view no longer offer Verify / Finalize / Renew: those orders are driven by the external ACME client (it answers the challenges, finalizes with its own key and downloads the certificate), so finalizing from UCM could only fail, previously with a misleading "ACME outbound URL blocked: URL has no hostname". The API now answers 409 with an explanation and the UI shows a hint instead of the buttons (#306)
  • Migrating to PostgreSQL with a role that is not a superuser no longer fails with "Can't operate on closed transaction inside context manager" and 0 rows copied: the FK-check bypass (session_replication_role) is now attempted inside a savepoint, so a refused SET falls back to the topological insert order as intended instead of aborting the whole copy. The switch-without-migration bootstrap (which copies users to the new backend) had the same failure class and is fixed by the same change (#305)

[2.215] - 2026-08-28

Added

  • Automatic updates — a daily background check on your chosen channel surfaces new versions in the UI and through the notification pipeline (new system.update_available / system.update_initiated / system.update_installed / system.update_failed webhook events), and an opt-in unattended install (off by default) downloads, verifies and installs the update at a configurable hour, with a full audit trail. Channels are strict: stable takes final releases only and rc additionally takes rcN prereleases only — alpha/beta/dev tags never qualify for either. The install outcome is truthful end-to-end: system.update_initiated fires when the checksum-verified trigger is written, then the privileged update watcher installs the package, verifies the installed version against the target and records a durable result; system.update_installed or system.update_failed (with the failing step) is emitted from that result after the restart — never before the install actually happened. The unattended install refuses to run when its anti-repeat marker cannot be persisted, and the settings PATCH is transactional (an error is reported instead of a partially saved config). DEB/RPM installs only — Docker deployments get the check and notification with a pointer to pull the new image (#301)
  • Update downloads are now verified against the release's published SHA256 checksum — a manual install refuses to proceed when the published checksum can't be retrieved or doesn't cover the package, and an unattended install additionally requires a checksum to exist; RPM releases now publish a .sha256 next to the package like DEB releases already did (#301)
  • Webhook event names shown in the webhook form and list are now localized in all 9 languages
  • External-CSR CAs: installing a renewal certificate now reports the superseded certificate's serial and expiry (API response, notice in the upload dialog, audit log) as a reminder to revoke it at the external root — UCM cannot publish that revocation itself, since the issuer's key is not held here (follow-up to #298)
  • Deploy hooks — push issued and renewed certificates to remote hosts over SSH. Admin-only deploy targets (Settings › Deployment) hold key-based SSH credentials (encrypted at rest, ed25519 key generated by UCM or imported, host key pinned on first connect with a UI action to reset the pin after a legitimate host reinstall) and one fixed reload command; certificates are attached to targets from the certificate detail view with per-file destination paths (certificate / private key / full chain — distinct paths enforced — written atomically over SFTP with restrictive key permissions). Attaching a target queues the first deployment immediately; renewals redeploy automatically. Pushes run asynchronously through a durable delivery queue with retry/backoff (per-delivery status, manual deploy-now and retry, full audit trail). Deleting targets/bindings requires the delete:deploy scope. Use a dedicated low-privilege SSH account on each target (migration 081, new dependency paramiko) (#299)
  • Externally-signed CRLs for offline / key-less CAs — a CRL generated next to an offline root (file-exported offline CA, certificate-only import, external-CSR parent) can now be uploaded (POST /api/v2/cas/<id>/crl, PEM or DER, also from the CA detail view) and served at that CA's existing CDP endpoint. The upload is validated before being accepted: the signature must verify against the CA certificate, the issuer must match, and the CRL must be newer than the currently served one (CRL number / thisUpdate monotonicity). OCSP consults the uploaded CRL for that issuer's serials on every request shape (single and multi-CertID), the upload invalidates the CA's cached OCSP responses so a pre-generated good never outlives the CRL that revokes it, and the CA detail view shows thisUpdate / nextUpdate / entry count with a stale warning once nextUpdate has passed (migration 080) (#302)
  • OCSP for key-less CAs: the signing identity is now resolved delegated-responder-first, so a certificate-only import or an offline file-exported CA answers signed OCSP through a delegated responder kept online; without any usable key the responder answers unauthorized (RFC 6960) instead of internalError (#302)

Fixed

  • TSA: selecting the signing CA on the TSA settings page now persists — the page echoed the read-only ca_id field back to the API, which silently overrode the just-saved ca_refid (selection wiped on first save, reverted to the previous CA when switching) while the UI still reported "saved" (#300)

Full history: CHANGELOG.md


Installation

Docker (Recommended)

# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.217

# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.217

# Run
docker run -d -p 8443:8443 \
  -e SECRET_KEY=$(openssl rand -hex 32) \
  --name ucm neyslim/ultimate-ca-manager:2.217

Debian/Ubuntu

wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.217/ucm_2.217_all.deb
sudo dpkg -i ucm_2.217_all.deb
sudo apt-get install -f

Fedora/RHEL

wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.217/ucm-2.217-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.217-1.fc43.noarch.rpm

Silent/Automated Install

# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.217_all.deb

Default Credentials

  • Username: admin
  • Password: changeme123

Change the password immediately after first login!

Documentation

Don't miss a new ultimate-ca-manager release

NewReleases is sending notifications on new releases.