v2.128
What's Changed
Added
- Custom Extended Key Usage (EKU) OIDs when issuing certificates and signing CSRs (RFC 5280 §4.2.1.12) — the Issue Certificate form and the Sign CSR modal now expose an "Extra EKUs" multi-select that combines a dropdown of well-known EKUs (Microsoft RDP
1.3.6.1.4.1.311.54.1.2, smartcard logon1.3.6.1.4.1.311.20.2.2, document signing, IPsec, Kerberos PKINIT, etc. — 18 catalog entries via the newGET /api/v2/eku/knownendpoint) with a free-text input that accepts any well-formed dotted OID. The cert_type's default EKUs (e.g.serverAuthfor server certs) remain locked-in as chips and the extras are merged on top — never replaced. Backend validation (utils/eku_validation.py) enforces a 16-OID cap, the^[0-2](?:\.(?:0|[1-9]\d*)){1,15}$OID regex, and explicitly rejectsanyExtendedKeyUsage(2.5.29.37.0). For CSR signing, if the CSR already carries an EKU extension it is rebuilt with the merged set. Fixes #76. - Active filter state persisted across reloads — applying a filter on Certificates, CAs, Audit Logs, Templates, Policies, TrustStore, HSM, RBAC, SSH Certificates, SSH CAs, Users/Groups, or User Certificates now saves the live selection to
localStorage(one key per filter, e.g.ucm-filter-certs-status). Reloading the page or navigating away and back instantly restores the same filter, with no flash of unfiltered data — the newusePersistedStatehook reads the value synchronously in the React state initializer. Clearing a filter through the UI also removes the correspondinglocalStorageentry, so empty state stays clean. Works alongside the existing named filter presets (which keep using a separate…-presetskey). Fixes #57. - Windows quick-install script for SSH CA trust — the SSH CA setup script endpoint now accepts a
?platform=windowsquery parameter and returns a PowerShell (.ps1) script that configures the Windows OpenSSH Server to trust the CA (writes the public key to%ProgramData%\ssh, locks down ACLs, addsTrustedUserCAKeys/HostCertificatedirectives tosshd_config, validates withsshd -T, and restarts thesshdservice). Supports both user and host CAs, includes a-DryRunswitch, and works on the public unauthenticated/ssh/setup/<refid>endpoint too. The SSH CA detail panel now shows two download buttons (Linux/macOS.sh+ Windows.ps1) and two Quick Install one-liners (curl … | bashfor Linux/macOS,iwr … | iexfor Windows). Fixes #75. - User UI preferences persisted server-side — language, theme family, and theme mode are now saved per-user in the database (
users.preferencesJSON column) instead of only in the browser'slocalStorage. New endpointsGET/PUT /api/v2/account/preferences(whitelist-validated, admin or self) store the preferences, and/api/v2/auth/verifyreturns them so they are applied on every page load. Logging in from a fresh browser, a different device, or after clearing site data now restores the user's chosen language and theme instead of falling back to the browser locale and default theme. Migration022adds the column on both SQLite and PostgreSQL. Fixes #73. - ACME proxy orders linked to local accounts — proxy order rows now record which local
AcmeAccountinitiated them (FKaccount_idresolved from the client JWK thumbprint). The proxy order list now displays the account email/short id beside each order, and the account detail "Orders" tab now merges local + proxy orders with a "Proxy" badge so operators can see all activity per account in one place. Migration021backfillsaccount_idfor existing proxy orders by joining onacme_accounts.jwk_thumbprint. Fixes #71.
Fixed
- ACME renewal storm with Let's Encrypt —
AcmeClientOrder.expires_atwas being set from the ACME order resource'sexpiresfield (RFC 8555 §7.1.3, ~7 days for LE) instead of the issued certificate'snotAfter(typically 90 days). The renewal scheduler then re-issued the same certificate every tick, hitting the LE production rate limits.finalize_ordernow stores the leaf certificate'snotAfter, and migration020backfillsexpires_atfor all already-issued orders. Fixes #74.
Changed
- No more compilation toolchain required at install time —
gccandpython3-dev(DEB) /python3-devel(RPM) have been removed from package dependencies. Previously they were needed to build thetwofishC extension pulled in transitively bypyjks(Java KeyStore export). Investigation confirmedtwofishis only used by pyjks for the BKS UBER keystore format, which UCM never produces — UCM only exports JKS.pyjksis now installed viapip install --no-deps pyjks==20.0.0in the postinst scripts (with its actual runtime depsjavaobj-py3+pycryptodomexlisted inrequirements.txt), keeping the install pure-wheel and ~30 MB lighter on RPM systems.
Installation
Docker (Recommended)
# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.128
# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.128
# Run
docker run -d -p 8443:8443 \
-e SECRET_KEY=$(openssl rand -hex 32) \
--name ucm neyslim/ultimate-ca-manager:2.128Debian/Ubuntu
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.128/ucm_2.128_all.deb
sudo dpkg -i ucm_2.128_all.deb
sudo apt-get install -fFedora/RHEL
wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.128/ucm-2.128-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.128-1.fc43.noarch.rpmSilent/Automated Install
# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.128_all.debDefault Credentials
- Username:
admin - Password: Check
/etc/ucm/ucm.envafter install, or shown during install
Change the password immediately after first login!