✨ Adds TrueNAS Certificate Deployer with deployment logic and configuration
This commit is contained in:
6 files changed
+427
-1
No files matched your search
@@ -0,0 +1,75 @@
|
||||
TrueNAS Certificate Deployer
|
||||
===========================
|
||||
|
||||
Imports acme.sh ECC certificates from `/certs/<domain>_ecc/` and selects them
|
||||
for the TrueNAS web interface. The entrypoint runs reconciliation at startup
|
||||
and whenever `/certs/.deploy-signal` changes.
|
||||
|
||||
Certificate Rotation
|
||||
--------------------
|
||||
|
||||
The final name is `acme_<domain with dots replaced by underscores>`, for example
|
||||
`acme_zagreus_ad_kritikos_io`. TrueNAS does not support replacing an imported
|
||||
certificate's PEM or private key in place, so each renewal receives a new ID.
|
||||
|
||||
1. Query TrueNAS and reuse a managed record containing the current full chain,
|
||||
preferring the record already selected for the UI.
|
||||
2. If no matching record exists, import one with a temporary name ending in
|
||||
`_pending_<16-character full-chain hash>`.
|
||||
3. Select its ID for the UI and request a UI restart when needed. Connect directly
|
||||
to HTTPS and require an exact match against the expected leaf certificate.
|
||||
4. Confirm the selected UI certificate ID, then delete superseded managed records
|
||||
using non-forced deletion jobs. TrueNAS checks service dependencies and refuses
|
||||
deletion of certificates still referenced by services.
|
||||
5. Rename the retained record to the stable name, request another UI restart to
|
||||
refresh certificate paths, and check the served certificate again.
|
||||
6. Write the full-chain fingerprint to `/state/<domain>.fp` only after completion.
|
||||
|
||||
Managed names are the exact stable name, that name plus a numeric timestamp from
|
||||
the previous deployer, or that name plus the temporary hash suffix. Only existing
|
||||
certificate records not managed by TrueNAS's native ACME implementation qualify.
|
||||
These names are reserved for this deployer. The default TrueNAS certificate,
|
||||
other domains, CSRs, and differently named records are not deleted.
|
||||
|
||||
A failure leaves reconciliation incomplete and produces a nonzero deployer exit
|
||||
status. The next startup or signal retries from TrueNAS's actual records, even
|
||||
when the fingerprint is unchanged. It does not import another copy merely
|
||||
because the previous switch, deletion, or rename failed. There is no periodic
|
||||
retry loop beyond startup and certificate signals.
|
||||
|
||||
If another service still references an older certificate, move that service to
|
||||
the new certificate separately. This deployer manages only the UI reference;
|
||||
it does not alter other services or force deletion. The temporary name and old
|
||||
records can remain until the dependency is removed and reconciliation reruns.
|
||||
Failed activation retains old records but does not automatically roll back the
|
||||
UI selection.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
- `TRUENAS_URI`: direct middleware WebSocket URL, default `ws://localhost/api/current`.
|
||||
- `TRUENAS_API_KEY`: required credential supplied outside the image and repository.
|
||||
- `TRUENAS_DEPLOY_DOMAINS`: comma-separated domains matching the ECC directory names.
|
||||
- `TRUENAS_UI_RESTART`: defaults to `true`; required to finalize a new or legacy
|
||||
certificate's stable name. With `false`, the deployer never requests a restart
|
||||
and defers naming cleanup. Activation verification still applies.
|
||||
- `TRUENAS_JOB_TIMEOUT`: job and TLS-verification timeout in seconds, default `300`.
|
||||
|
||||
TLS verification connects to the hostname in `TRUENAS_URI` and the configured
|
||||
TrueNAS `ui_httpsport`, using the certificate domain as SNI. That hostname must
|
||||
reach the TrueNAS UI directly, not a reverse proxy serving a different certificate.
|
||||
The exact leaf certificate is pinned to the local ACME output; the probe does not
|
||||
depend on the container's CA trust store. A connection failure or certificate
|
||||
mismatch prevents cleanup.
|
||||
|
||||
TrueNAS has one UI certificate setting. Domains are processed in order, and the
|
||||
last successfully selected domain owns that setting. Normally configure just the
|
||||
UI certificate domain, including any additional names as SANs on that certificate.
|
||||
|
||||
The API key needs certificate read/write, system-general read/write, and access
|
||||
to the jobs used by certificate create, delete, and update. The implementation
|
||||
targets TrueNAS 27. Its `system.general.config` and `system.general.update`
|
||||
responses expose `ui_certificate` as an integer ID or null, not an embedded
|
||||
certificate object. Both selection checks use that ID directly, as defined by
|
||||
the [TrueNAS 27 schema](https://github.com/truenas/middleware/blob/master/src/middlewared/middlewared/api/v27_0_0/system_general.py).
|
||||
Renaming preserves the new ID, not the old certificate's ID.
|
||||
Reference in new issue
Block a user