github NeySlim/ultimate-ca-manager v2.186

latest releases: v2.239, v2.239-rc1, v2.238...
3 months ago

What's Changed

Fixed

  • ACME proxy /directory on fresh install — the legacy /acme/proxy/directory and /new-nonce endpoints returned a 500 (No external ACME CA account configured for the proxy) on a brand-new instance before any external CA account was added, because the proxy service resolved the upstream AcmeClientAccount eagerly in its constructor. Resolution is now lazy: only the upstream directory URL (config-derived, defaults to Let's Encrypt staging) is needed for /directory and /new-nonce, and the account row is looked up on the first key-bearing operation (new-account, new-order, signing), preserving the helpful configuration error for actual signing paths. This had broken the release smoke gate on a fresh Docker container.
  • ACME manual verify DNS wait and authorization poll cadence — the synchronous manual-verify endpoint ran the DNS self-check up to the full configured dns_propagation_timeout (max 3600 s), risking client/proxy timeouts; it is now capped at 30 s (background auto-poll still honors the full timeout). The auto-poll loop also queried per-domain authorization status on every iteration, doubling CA traffic; it is now checked every max(poll_interval × 5, 15) s, with the order-status poll still catching terminal invalid states each interval.
  • Contact-less upstream account registration — AcmeClientService.register_account now accepts email=None and omits the contact field (RFC 8555 makes it optional; Let's Encrypt accepts contact-less registrations), so the proxy no longer blocks issuance when the only available email has a non-public TLD (.lan/.local).
  • ACME preflight staging order cleanup on failure — an ephemeral staging order created during a full preflight is now removed from the database even when a later stage of the preflight raises, instead of leaking an orphan row.
  • Key-reuse renewal fallback — key_source=reuse now falls back to the original source_certificate_id when the order's own certificate_id is missing (e.g. an order whose import failed), so the key-reuse chain survives across renewals.

📜 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>/directory alongside the legacy /acme/proxy/directory (backward compatible). Reserved slugs (directory, new-order, acct, challenge, …) prevent collisions with existing routes. Migrations 050 (acme.proxy.acme_account_id) and 051 (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.yml workflow rejects PRs whose commits carry Co-authored-by trailers from known AI agent identities (Cursor, Copilot, Claude, …), so commits attributed to bots can no longer reach dev.

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=0 now 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 as value_mismatch / pending on such a resolver (#171).
  • Migration 050 NotNullViolation on PostgreSQL — the proxy account backfill inserted legacy credentials into acme_client_accounts without created_at/updated_at; on instances where those columns are NOT NULL without a server DEFAULT, 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 -f via _get_fqdn(), which on CI runners can return a short hostname without a domain and resolve to None, flaking the update-CA tests. The shared test app fixture now pins FQDN = '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 (no digitalSignature) and no EKU; issuing CAs add digitalSignature and optional serverAuth, matching common enterprise root/intermediate profiles (Let's Encrypt Root-YR / issuing CA style). Intermediate CA notAfter is clamped to the parent CA expiry, and GET /api/v2/cas/:id now 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 049 adds key_source, csr_pem and source_certificate_id on acme_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-challenge TXT records to add, with optional DNS propagation verification. Emits an acme.preflight webhook event and an acme_preflight audit 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. Previously EC P-256 failed because the UI label was stripped to P-256 and validated against OpenSSL curve names. The secp256k1 (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 granting admin: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/enroll honored X-SSL-Client-Verify, X-SSL-Client-S-DN and X-SSL-Client-Cert headers 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 on is_request_from_trusted_proxy() for those headers, matching the existing protection on the login_mtls() path (#163).

Full history: CHANGELOG.md


Installation

Docker (Recommended)

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

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

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

Debian/Ubuntu

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

Fedora/RHEL

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

Silent/Automated Install

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