github NeySlim/ultimate-ca-manager v2.184-rc1

latest releases: v2.235, v2.235-rc1, v2.234...
pre-release3 months ago
πŸ“œ Recent release history (last 2 versions)

[2.183] - 2026-07-03

Added

  • Operator-configurable HSTS (Strict-Transport-Security) header β€” the HSTS policy was previously hardcoded to max-age=31536000; includeSubDomains on every HTTPS response. Instances serving self-signed certificates during initial setup can now opt out entirely, drop the includeSubDomains directive, or shorten max-age from Settings β†’ Security. The setting can also be forced via UCM_HSTS_ENABLED, UCM_HSTS_INCLUDE_SUBDOMAINS and UCM_HSTS_MAX_AGE environment variables in /etc/ucm/ucm.env (takes precedence over the database); when set, the corresponding toggle in the UI is locked with a badge (#154).
  • mTLS PKCS#12 export from Account β€” after generating an mTLS certificate from the Account page, both PEM and PKCS#12 (.p12) download are now offered client-side, with password-protected PKCS#12 for browser or OS keychain import. The download endpoint enforces POST with a JSON body for PKCS#12 (password never sent via query string, avoiding leakage in proxy logs), minimum 8-character password, and returns the AuthCertificate id usable by list/download/export (#156).

Fixed

  • WebSocket handshake fails when if HTTPS_PORT was set to 443 - CORS_ORIGINS always appended :{HTTPS_PORT} to every allowed origin, so on port 443 the list contained entries such as https://ucm.example.com:443. Browsers omit the port number from the Origin header when it is the scheme default so it would never match. As Socket.IO performs server-side checks on Origin, WebSocket connections would be silently rejected. CORS_ORIGINS now omits the port suffix when HTTPS_PORT is 443 (#155).
  • SSH setup script command injection via hostname β€” the public GET /ssh/setup/<refid> endpoint accepted arbitrary hostname query values that were embedded into generated shell/PowerShell scripts without validation. A payload such as $(id) or ";id;" would execute when an operator piped the script to bash. Hostnames are now validated against ^[a-zA-Z0-9._-]+$ via a shared helper on both the public and authenticated setup routes, and the Windows script generator escapes single quotes (#157).

[2.182] - 2026-07-02

Added

  • Per-CA ACME timing settings and robust DNS-01 TXT verification β€” each external ACME CA account now carries its own order poll timeout, poll interval and HTTP timeout (migration 048 adds acme_client_accounts.order_poll_timeout_sec, order_poll_interval_sec, http_timeout_sec), so a slow authority no longer inherits the global hardcoded values. The DNS-01 challenge self-check now resolves the expected TXT record through the authoritative nameservers first, then public resolvers, with per-resolver diagnostic logging, and invalid ACME authorizations are detected during polling instead of stalling until timeout. The Gandi DNS provider was also hardened (URL-encoding of record values, post-create verification, missing Any import) (#150).

Fixed

  • ACME auto-renewal no longer crashes when refreshing the order expiry β€” the renewal service read new_cert.not_after to copy the new certificate's expiry onto the order's expires_at, but the Certificate model exposes that date as valid_to. The AttributeError aborted the renewal right after the new certificate had been issued and imported, so expires_at was never updated and the scheduler re-requested the same certificate on every tick. The renewal path now reads valid_to, and expires_at is updated correctly so a renewed certificate is not renewed again until its next due window.

Added

  • Multi-CA management for the ACME client β€” UCM can now issue certificates from several external ACME authorities (Let's Encrypt, Actalis, ZeroSSL, Google Trust Services, HARICA…) instead of a single one. ACME CA accounts are managed from the UI (CRUD, per-account External Account Binding, default selection, registration status), each certificate request picks its issuing CA, and the order is pinned to that account so renewals stay on the same authority. The AcmeClientOrder.acme_client_account_id foreign key (migration 047) links each order to its external CA account; AcmeClientService.for_issuance(environment, account_id=) resolves explicit account > configured custom directory > Let's Encrypt environment, and for_order(order) reuses the pinned account on verify/finalize/status/renewal (#149).

Full history: CHANGELOG.md


Installation

Docker (Recommended)

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

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

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

Debian/Ubuntu

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

Fedora/RHEL

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

Silent/Automated Install

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