What's Changed
Added
- Name constraints can now be set when creating a CA. The Create CA wizard's Advanced Constraints section gained permitted and excluded subtree fields (DNS, IP range, email), and
POST /api/v2/casacceptsnameConstraintsPermitted/nameConstraintsExcludedas{type, value}lists and emits them as the critical NameConstraints extension. The request validation previously required plain strings while the extension builder expected objects, so no payload actually produced a constrained CA; malformed entries are now rejected with 400 at the API boundary instead of being silently dropped or producing an unusable CA: unknown type, IP network with host bits set, empty value, a DNS value that is not a plain domain (URL, path, wildcard, underscore, or an RFC-5280-invalid leading dot), an e-mail value that is not a mailbox, host or.domainform with a valid local part, and non-ASCII values. rfc822Name constraints are also now enforced against the subject DNemailAddressattribute, not only SAN e-mail addresses, on every issuance path, and the three e-mail constraint forms are matched per RFC 5280 (example.com= that host only,.example.com= its subdomains only,user@example.com= that mailbox) so a constrained CA no longer issues certificates that fail OpenSSL chain validation. Constraints entered for an external-CSR CA are refused, since the signing CA applies them there. They still cannot be changed after creation, as the extension is part of the signed certificate (#316, reported by @JoseGoncalves, contributed by @Hemsby) - The certificate template editor's Key Type dropdown now offers
RSA-3072andEC-P521. Both were already accepted by the template API and produced working certificates at issuance; only the dropdown was missing them (#318 follow-up)
Fixed
- ACME proxy: a domain the upstream CA has already validated (a pre-validated or onboarded domain, typically on an EAB-bound account) no longer fails with "Upstream CA does not offer dns-01 challenge". An authorization the upstream reports as valid is now passed through untouched, so the client goes straight to finalize; a pending authorization without a dns-01 challenge is still refused, since the proxy can only automate dns-01 (#325, reported by @spijker)
- Certificate expiry alerts: every selected alert day is now stored and used. Saving 14, 7, 3 and 1 kept only 14 because the configuration row had a single threshold column, and the daily job then sent a reminder every day once a certificate entered that single window. Each selected threshold now fires once per validity period (and again after a renewal), the Include revoked certificates toggle is persisted and honoured, invalid selections are rejected with 400, and the in-memory alert settings module the scheduler never read has been removed. Upgrade note: existing installs keep their current single threshold until a new selection is saved, and alerts that used to repeat daily inside the window now go out once per threshold (#323, #324, reported by @JoseGoncalves)
- Email settings: choosing the None authentication method no longer shows Password after a reload. The API reported the stored default method even when SMTP authentication was off and dropped
noneon save; it now reportsnonewhenever authentication is disabled, accepts it, and the form derives the highlighted method from that field (#322, reported by @JoseGoncalves) - Certificate issue form: picking an EC certificate template (or switching Key Type from RSA to ECDSA) filled Key Type but left Key Size blank, so issuance failed with "EC curve must be P-256, P-384, or P-521". The Key Size dropdown swaps its options when the key type changes, and the shared Select wrapper was forwarding the reset event the list swap triggers as a real selection, wiping the value; it now ignores a change to a value that is not one of its current options. The same latent problem in the Create CA wizard's key size field is fixed by the same change. The issue API also fills the key size from the template when the request sends a key type but no size, on both the direct and the approval-workflow issuance paths, so an approved request for an EC template no longer drops to a P-256 key; a non-string key type in the payload now returns 400 instead of 500 (#318, reported by @JoseGoncalves, contributed by @Hemsby)
Security
- Private-key encryption now stops creating plaintext key mirrors and removes existing mirrors when enabled and at startup; Settings reports the on-disk count, disabling encryption recreates the mirrors, and Deployment adds a same-host SFTP preset for services that need key files. Upgrade note: on the first start with key encryption enabled, plaintext key files under the private directory are removed; anything that read them directly must move to deploy hooks (same-host SFTP target) or the API export. Certificate files are untouched (#320, reported by @kzshantonu)
📜 Recent release history (last 2 versions)
[2.219] - 2026-09-01
Fixed
- Local ACME accounts created from the admin UI now store their contact e-mail in the RFC 8555 format, so the address shows up in the accounts list and detail panel instead of a bare "Account #N"; accounts created before this fix keep displaying their address through a legacy-format fallback, and editing the e-mail also normalizes the stored value
- The 2.218 ACME and HTTPS quality-of-life additions are now actually discoverable: the account e-mail edit is a labeled button spanning the detail grid (it rendered as a cryptic icon squeezed against the address), the client orders got their own "Let's Encrypt orders" sidebar tab mirroring Local orders (the in-section list was easy to miss), and Settings > HTTPS states explicitly when no certificate is bound instead of showing nothing (#303, reported by @gb-123-git)
[2.218] - 2026-08-31
Added
- Local ACME accounts: the contact e-mail can now be edited from the account detail (the piece of #303 that had been accepted but not shipped in 2.217). Per RFC 8555 the contact belongs to the ACME client and its next account update may overwrite the value; the edit form says so (#303, reported by @gb-123-git)
- Settings > HTTPS now shows which certificate is bound to the web UI (renewals applied automatically) with a button to stop following renewals; the Let's Encrypt orders list gains the same status filter and naming as the Local orders view (#303, reported by @gb-123-git)
- One-click TSA signing certificate: Settings > TSA > Signing certificate now has a "Generate a signing certificate" action that issues an end-entity certificate purpose-built as an RFC 3161 timestamp signer:
BasicConstraintsCA:FALSE,KeyUsagedigitalSignatureonly (critical), and a critical, exclusivetimeStampingEKU. The generic issue path cannot produce this (it always emits the EKU non-critical and merges the base profile withextra_ekus), so before this an operator had to hand-craft the certificate outside UCM. The private key is stored encrypted at rest. The certificate is issued and committed first; when no usable dedicated signer is configured yet it is then selected astsa_signer_cert_refid(a second write), and if that selection write fails the certificate stays issued but unselected with a log line. An already-healthy signer is never swapped without an explicit request. Issued throughPOST /api/v2/tsa/signer-certificate(needs bothwrite:settingsandwrite:certificates), defaulting to the configured TSA CA,RSA 3072, and a 397-day validity clamped to the issuing CA's own expiry. The certificate is an ordinary UCM certificate: in-place renewal keeps the critical exclusive EKU and expiry alerts apply, but the auto-renewal scheduler only covers it ifmanualis added toauto_renewal_sources(defaultscep,acme,est); the generate form says so. The TSA page also now shows whether the active signer'stimeStampingEKU is critical/exclusive (eku_critical_exclusive), on both the candidate list and the status box (#312, contributed by @Hemsby) - Dashboard surfacing for a near-expiry TSA signer: the System Health widget now has a TSA badge (disabled / signing with the CA certificate / dedicated signer, turning amber within 30 days of the signer's expiry and grey when the signer is expired, revoked or undecryptable and
/tsais therefore returning 503), and the Next Expirations widget tags the configured dedicated signer with a "TSA signer" chip so its expiry reads as an infrastructure event rather than one certificate among many. Service badges now render a distinctwarningstate and show their status message on hover. A dedicated signer is an ordinary certificate, so the existing email expiry alerts already cover it; this adds the at-a-glance view (#312, contributed by @Hemsby)
Fixed
- ACME account detail: challenge status badges show valid in green and pending in yellow again (the API capitalizes statuses, the badge mapping compared lowercase, so everything rendered red); the scheduled purge and the purge button now also remove the leftover pending sibling challenges of authorizations validated before 2.217 (#303, reported by @gb-123-git)
- Dashboard: the Webhooks badge queried a column that does not exist, so it always showed "Not configured" no matter how many endpoints were configured; on PostgreSQL the failed query also aborted the transaction, dragging the badges probed after it (TSA included) into their fallback state. The query is fixed and every status probe now resets the session on failure so one broken probe cannot poison the next
Full history: CHANGELOG.md
Installation
Docker (Recommended)
# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.220
# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.220
# Run
docker run -d -p 8443:8443 \
-e SECRET_KEY=$(openssl rand -hex 32) \
--name ucm neyslim/ultimate-ca-manager:2.220Debian/Ubuntu
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.220/ucm_2.220_all.deb
sudo dpkg -i ucm_2.220_all.deb
sudo apt-get install -fFedora/RHEL
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.220/ucm-2.220-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.220-1.fc43.noarch.rpmSilent/Automated Install
# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.220_all.debDefault Credentials
- Username:
admin - Password:
changeme123
Change the password immediately after first login!
Documentation
- Installation Guide
- API Documentation