๐ Recent release history (last 2 versions)
[2.185] - 2026-07-06
Added
- ACME proxy multi-CA with per-account slug endpoints โ the ACME proxy upstream is now selected per external CA account (
AcmeClientAccount), so several CAs (Let's Encrypt staging, production, ZeroSSL, โฆ) can be exposed in parallel. Each account can opt in to the proxy with a unique slug, served at/acme/proxy/<slug>/directoryalongside the legacy/acme/proxy/directory(backward compatible). Reserved slugs (directory,new-order,acct,challenge, โฆ) prevent collisions with existing routes. Migrations050(acme.proxy.acme_account_id) and051(proxy_enabled,proxy_slug) backfill the account already linked in proxy settings. The UI surfaces a toggle and slug field on external CA accounts and lists all enabled endpoints with a Certbot example (#170). - Typed SAN validation for certificate issuance โ the Issue Certificate form (
POST /api/v2/certificates) now validates SAN entries per type (DNS, IP, Email, URI, UPN) on both backend and frontend, with cross-type errors (e.g. an FQDN entered in the IP field is rejected with a hint to use DNS) and ECDSA curve mapping (256/384/521 โprime256v1/secp384r1/secp521r1). The CN auto-SAN no longer adds an email CN as a DNS SAN on server certs; email SAN is added only for Email/Combined types. New RSA 3072 size and P-384/P-521 curve options appear in the Issue Certificate selector (#169). - CI: block bot Co-authored-by trailers โ a new
no-bot-attribution.ymlworkflow rejects PRs whose commits carryCo-authored-bytrailers from known AI agent identities (Cursor, Copilot, Claude, โฆ), so commits attributed to bots can no longer reachdev.
Fixed
- ACME DNS-01 propagation diagnostics and
dns_propagation_timeout=0โ the DNS-01 self-check succeeds as soon as the authoritative (or configured) resolver confirms the TXT record, but the per-public-resolver diagnostic log was emitted even on success and a flaky resolver (e.g. SERVFAIL from Quad9) was indistinguishable from a real propagation gap. Each failing public resolver is now logged at DEBUG with its exception type (NXDOMAIN/Timeout/ConnectionError/ โฆ) and the public-propagation line is explicitly marked(diagnostic, does not block issuance).dns_propagation_timeout=0now skips the pre-check entirely on both the auto-poll background path and the manual Verify path (was a single-pass probe), matching the "submit immediately" help text (#171). - TXT RDATA multi-string concatenation โ long ACME authorization tokens published as a single TXT RR carrying several
<character-string>elements (RFC 1035 ยง3.3.14; Quad9 splits them across quoted strings) are now joined before matching against the expected value. A correctly published record no longer renders asvalue_mismatch/pendingon such a resolver (#171). - Migration 050 NotNullViolation on PostgreSQL โ the proxy account backfill inserted legacy credentials into
acme_client_accountswithoutcreated_at/updated_at; on instances where those columns areNOT NULLwithout a serverDEFAULT, the raw INSERT failed at boot (null value in column "created_at"). The migration now provides both timestamps explicitly on the SQLite and PostgreSQL paths. - Flaky OCSP/CDP auto-URL tests โ CA OCSP/CDP/AIA auto-URL generation relied on
hostname -fvia_get_fqdn(), which on CI runners can return a short hostname without a domain and resolve toNone, flaking the update-CA tests. The shared test app fixture now pinsFQDN = 'ucm.test'so URL generation is deterministic.
[2.184] - 2026-07-05
Added
- Configurable RFC 5280 CA profile โ the Create CA wizard exposes signature digest (Auto aligns P-384 to SHA-384 and P-521 to SHA-512, or explicit SHA-256/384/512) and an expandable Certificate Profile section with Key Usage and Extended Key Usage. Roots default to
keyCertSign+cRLSign(nodigitalSignature) and no EKU; issuing CAs adddigitalSignatureand optionalserverAuth, matching common enterprise root/intermediate profiles (Let's Encrypt Root-YR / issuing CA style). Intermediate CAnotAfteris clamped to the parent CA expiry, andGET /api/v2/cas/:idnow returns the X.509 serial number (colon-separated hex) and SHA-1/SHA-256 thumbprints. The obsolete Create CA help step about optional template selection (templates removed in migration 017) has been removed (#160). - ACME external CSR and renewal key reuse โ the ACME request form now offers a Key Source selector: Generate new key (default), Reuse key on renewal (preserves the same private key across renewals for DANE/TLSA and key pinning; first issuance generates a key, renewals reload it), or Provide external CSR (paste a PEM CSR; UCM submits it at ACME finalize, the private key never enters UCM). CSR domains are validated against the order identifiers (case-insensitive, RFC 4343). Auto-renewal honours the selected key source. Migration
049addskey_source,csr_pemandsource_certificate_idonacme_client_orders(#161). - ACME staging preflight dry-run โ a Run Preflight action on the ACME request form validates domains, contact email, ACME account/EAB, CA connectivity and DNS-01 challenge setup against the Let's Encrypt staging directory without consuming production rate limits or changing the global environment. Two modes: Full (staging order + required DNS TXT records preview) and Validate only (config + connectivity). For manual DNS providers it displays the exact
_acme-challengeTXT records to add, with optional DNS propagation verification. Emits anacme.preflightwebhook event and anacme_preflightaudit entry (#162). - Typed SAN validation for CSR creation โ SAN entries are now validated per type (DNS, IP, Email, URI, UPN) on both backend and frontend, with clear cross-type errors (e.g. an FQDN entered in the IP field is rejected with a hint to use DNS). The frontend validation mirrors the backend rules so the client and server stay consistent (#167).
- NIST P-521 EC curve option and normalized EC key labels โ Generate CSR and Create CA now accept NIST P-256, P-384 and P-521 (ECDSA) key types through normalized labels (
EC P-256,NIST P-384,secp256r1,prime256v1, โฆ) that map to the OpenSSL curve names used internally. PreviouslyEC P-256failed because the UI label was stripped toP-256and validated against OpenSSL curve names. Thesecp256k1(Koblitz) curve remains intentionally unsupported (#167). - Hex serial number in certificate technical details โ the certificate details view shows the serial as colon-separated uppercase hex (browser/OpenSSL display style) alongside the decimal form, copyable. Conversion handles decimal,
0x-prefixed and compact/colon hex inputs and supports serials larger than 159 bits via arbitrary-precision integer math.
Fixed
- API key permission escalation โ a non-admin user with permission to create API keys (
POST /api/v2/account/apikeys) could mint a key carrying permissions their own role did not hold (e.g. a viewer grantingadmin:system). The create path now rejects any permission the creator does not have, with the same wildcard semantics as the auth checker. Sharing a wildcard key (*) requires the creator to be an admin (#163). - Forged mTLS enrollment via spoofed proxy headers โ
POST /api/v2/mtls/enrollhonoredX-SSL-Client-Verify,X-SSL-Client-S-DNandX-SSL-Client-Certheaders from any peer, so a caller who could reach gunicorn directly could forge a client certificate and enroll it as another user. The endpoint now gates onis_request_from_trusted_proxy()for those headers, matching the existing protection on thelogin_mtls()path (#163).
Full history: CHANGELOG.md
Installation
Docker (Recommended)
# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.186-rc1
# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.186-rc1
# Run
docker run -d -p 8443:8443 \
-e SECRET_KEY=$(openssl rand -hex 32) \
--name ucm neyslim/ultimate-ca-manager:2.186-rc1Debian/Ubuntu
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.186-rc1/ucm_2.186.rc1_all.deb
sudo dpkg -i ucm_2.186.rc1_all.deb
sudo apt-get install -fFedora/RHEL
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.186-rc1/ucm-2.186.rc1-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.186.rc1-1.fc43.noarch.rpmSilent/Automated Install
# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.186.rc1_all.debDefault Credentials
- Username:
admin - Password:
changeme123
Change the password immediately after first login!
Documentation
- Installation Guide
- API Documentation