Skip to content

v2.140

Choose a tag to compare

@github-actions github-actions released this 27 Apr 13:56
· 312 commits to main since this release

What's Changed

Fixed

  • Certificate SAN database columns now derived from the final SAN list (#94). When a CN is auto-promoted to an rfc822Name SAN at issuance, the san_email / san_dns / san_ip / san_uri columns are now written from the canonical SAN list instead of the raw form payload, so DB queries match the X.509 extension. Migration 027_backfill_san_email re-parses existing certificate PEMs and backfills any rows that were out of sync (idempotent on SQLite and PostgreSQL). Thanks @Hemsby.
  • Certificate and CA files written to disk on creation (#95). Added SQLAlchemy after_insert listeners on the Certificate and CA models that immediately materialize .crt / .key files under data/certs/ and data/cas/ for every creation path (UI, CSR signing, ACME, SCEP, import). The startup file-regeneration scan is kept as a safety net. File-write errors are logged but never abort the database transaction. Thanks @Hemsby.

📜 Recent release history (last 2 versions)

[2.139] - 2026-04-27

Added

  • ACME External Account Binding (EAB) — RFC 8555 §7.3.4. Full EAB credentials manager (backend models, API, UI under ACME → EAB Credentials). Operators can issue, list, rotate and revoke kid / hmac pairs; clients (cert-manager, certbot, acme.sh) bind their account on newAccount via JWS over the MAC key. Brings UCM in line with public ACME CAs (Let's Encrypt EAB, ZeroSSL, Google Trust Services).
  • ACME custom DNS resolvers for DNS-01 validation. Per-account override of system resolvers when validating _acme-challenge TXT records. Useful for split-horizon DNS, internal authoritatives, or when public resolvers cache stale records during automated renewals.
  • ACME on internal / private IPs — gated by acme.allow_private_ips SystemConfig (default true). HTTP-01 and TLS-ALPN-01 validation now works out of the box for RFC1918, loopback, .lan / .local / .corp targets — UCM's primary deployment model. Cloud metadata IPs (169.254.169.254) remain blocked unconditionally.
  • Kubernetes & cert-manager integration. Reference manifests under examples/kubernetes/cert-manager/ (HTTP-01 ClusterIssuer, DNS-01 ClusterIssuer with EAB, sample Certificate, EAB Secret template, README). Full integration guide on the wiki and on https://ucm.tools/docs.

Changed

  • ACME audit & RBAC hardening. Challenge state transitions now produce audit records on terminal states (valid / invalid) instead of every poll, eliminating audit log noise. account.key_change (RFC 8555 §7.3.5) is audited. delete:acme permission added to the operator role to match write:acme.
  • ACME backup/restore parity. acme_eab_credentials is now exported and restored alongside acme_accounts; full account fields (contact, status, terms-of-service, external-account-binding metadata) are now round-tripped end-to-end.

Fixed

  • backend/services/ssh_cas.py — converted f-strings containing escape sequences to raw f-strings to silence Python SyntaxWarning: invalid escape sequence on 3.12+.

[2.138] - 2026-04-25

Fixed

  • CAs page silently dropped CAs beyond the first 20 (#89)GET /api/v2/cas defaulted to per_page=20 even when no pagination parameters were supplied, so a fresh import of 24 CAs only displayed 20 in Certificate Authorities. The endpoint now returns the full set when no pagination is requested, and continues to honour page / per_page when they are explicitly provided.
  • API key creation UX & no-expiration support (#90) — three regressions in Account → API Keys:
    • Newly issued keys are now shown in a dedicated modal with the full key in a <code> block, an explicit copy button, and a warning that the key won't be shown again. The previous toast disappeared too quickly and its copy button copied the literal string undefined.
    • The list view's per-key "copy" affordance now renders the real key prefix (e.g. ucm_ak_AbC1) instead of undefined…. Backed by a new key_prefix column persisted at creation time. Migration 026_add_api_key_prefix adds the column on SQLite and PostgreSQL; legacy keys without a stored prefix render an "unavailable (legacy key)" placeholder.
    • Leaving the expiration field empty now creates a key that never expires, matching the field's helper text. The backend distinguishes "field absent" (keeps the historical 365-day default for API/CLI compatibility) from explicit null / 0 / "" (no expiration). Validation rejects negative or non-integer values with HTTP 400.

Full history: CHANGELOG.md


Installation

Docker (Recommended)

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

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

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

Debian/Ubuntu

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

Fedora/RHEL

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

Silent/Automated Install

# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.140_all.deb

Default Credentials

  • Username: admin
  • Password: Check /etc/ucm/ucm.env after install, or shown during install

Change the password immediately after first login!

Documentation