📜 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_failedwebhook 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:stabletakes final releases only andrcadditionally takes rcN prereleases only — alpha/beta/dev tags never qualify for either. The install outcome is truthful end-to-end:system.update_initiatedfires 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_installedorsystem.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
.sha256next 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:deployscope. 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-generatedgoodnever 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 ofinternalError(#302)
Fixed
- TSA: selecting the signing CA on the TSA settings page now persists — the page echoed the read-only
ca_idfield back to the API, which silently overrode the just-savedca_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_serialsstore keeps every revoked or superseded serial on the CRL and answeringrevokedover 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:
idandrefidnever change (API consumers and integrations keep their stored references),created_atpreserves the original issuance date, and newrenewed_at/renewed_timesfields track the renewal history. The superseded serial is published on the CRL (reasonsuperseded) 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:TRUEandkeyCertSign/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-rc1
# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.216-rc1
# Run
docker run -d -p 8443:8443 \
-e SECRET_KEY=$(openssl rand -hex 32) \
--name ucm neyslim/ultimate-ca-manager:2.216-rc1Debian/Ubuntu
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.216-rc1/ucm_2.216.rc1_all.deb
sudo dpkg -i ucm_2.216.rc1_all.deb
sudo apt-get install -fFedora/RHEL
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.216-rc1/ucm-2.216.rc1-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.216.rc1-1.fc43.noarch.rpmSilent/Automated Install
# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.216.rc1_all.debDefault Credentials
- Username:
admin - Password:
changeme123
Change the password immediately after first login!
Documentation
- Installation Guide
- API Documentation