github NeySlim/ultimate-ca-manager v2.216

latest releases: v2.238, v2.238-rc1, v2.237...
one month ago

What's Changed

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)

📜 Recent release history (last 2 versions)

[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)

[2.214] - 2026-08-25

Security

  • Certificates: a valid, non-revoked X.509 certificate can no longer be deleted — deletion removed the record while the certificate stayed trusted until expiry, with no CRL/OCSP trace; revoke it first so relying parties see the change (single delete returns 409, bulk delete reports the item as failed). Expired or revoked certificates, and CSR-only records, are unaffected (#296, contributed by @gb-123-git & PMGA Tech LLP)
  • Revocations now survive certificate deletion — a new persistent revoked_serials store keeps every revoked or superseded serial on the CRL and answering revoked over OCSP until the original certificate's notAfter, even after the certificate record itself is deleted. A revocation and its persistent record are written in one transaction, and removing a certificate hold deletes both atomically, so relying parties can never observe a half-applied state (migration 078) (#297, contributed by @gb-123-git & PMGA Tech LLP)
  • Renewing a revoked certificate is refused (409) instead of silently clearing its revocation state — issue a new certificate instead (#297, contributed by @gb-123-git & PMGA Tech LLP)
  • Renewed private keys are encrypted at rest exactly as at issuance — bulk renewal previously stored them unencrypted, silently downgrading deployments with a master key configured (#297, contributed by @gb-123-git & PMGA Tech LLP)

Changed

  • Certificate renewal is now in-place — manual, bulk and automatic renewal share a single implementation that updates the existing certificate record: id and refid never change (API consumers and integrations keep their stored references), created_at preserves the original issuance date, and new renewed_at / renewed_times fields track the renewal history. The superseded serial is published on the CRL (reason superseded) and over OCSP until the old expiry. Certificates whose key UCM holds are re-keyed on renewal; protocol-enrolled certificates (SCEP/EST/ACME) are re-signed with their existing public key, since the private key lives on the client (#297, contributed by @gb-123-git & PMGA Tech LLP)

Added

  • CA signed by an external CA (CSR) — a new CA creation mode for the canonical offline-root / online-issuing-CA pattern: UCM generates the key pair (local or HSM-backed) and a CA-flavored CSR (basicConstraints CA:TRUE and keyCertSign/cRLSign, both critical), and the CA waits in an "awaiting certificate" state with the CSR downloadable — the private key never leaves UCM. Uploading the certificate signed by the external root (PEM or DER) activates the CA after strict checks: the certificate's public key must match the stored private key, CA BasicConstraints/KeyUsage are enforced, the effective pathLen comes from the signed certificate, and the chain links automatically when the external root was imported (certificate only; AKI→SKI match with issuer-DN fallback, signature verified). Renewal re-issues a CSR from the same key so the SKI stays stable across renewals, and a pending CA is excluded from every signing, CRL, OCSP and protocol path until activated (migration 079). Smoke-tested end-to-end on SQLite and PostgreSQL. Requested in #298
  • Optional auto-purge of stale revoked-serial records (expired ones only) during CRL generation — default off, so records are kept as renewal-chain history unless an admin enables it (#297, contributed by @gb-123-git & PMGA Tech LLP)

Fixed

  • Auto-renewal notification settings are now honored — the notify toggles were never read back (notifications always sent) and boolean values did not survive a settings round-trip; malformed JSON in the auto-renewal configuration no longer crashes the scheduler (#297, contributed by @gb-123-git & PMGA Tech LLP)

Full history: CHANGELOG.md


Installation

Docker (Recommended)

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

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

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

Debian/Ubuntu

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

Fedora/RHEL

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

Silent/Automated Install

# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.216_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.