NetScaler (Citrix ADC) module
Uploads cert + key to NetScaler ADC over NITRO REST, creates the sslcertkey object, and chains intermediate certificates with fingerprint-based global names to survive multi-cert deployments. The module never relinks virtual servers: updating an existing certkey in place preserves its bindings automatically, while a newly created certkey must be bound to its vservers manually (outside CertAutoPilot).
Overview
- Transport: NITRO REST (HTTPS, port 443).
- Auth: username + password, or client TLS certificate.
- Artifacts:
/nitro/v1/config/systemfileuploads followed by/nitro/v1/config/sslcertkeyobject creation +linkto intermediate chain. - Intermediate naming: SHA-256 fingerprint prefix so identical intermediates across different certs converge on one object rather than duplicating.
- Rollback: not supported. Old sslcertkey objects remain. No delete on the next deploy — stale cleanup is out-of-band.
- Chain depth cap: 5 intermediates.
Prerequisites
- NSIP or SNIP reachable from the backend on 443.
- A management user with permission to create
sslcertkeyobjects and bind SSL profiles. - Firmware 12.0+ (NITRO REST is stable from there).
Create the module credential
- Settings → Distribution → Credentials → New → NetScaler.
- Username + password.
- Save.
Create a NetScaler target
- Settings → Distribution → Targets → New. Module: NetScaler.
- Fields:
- Host — NSIP or management DNS name.
- Port — default
443. - Credential.
- Chain error handling —
strict(fail if chain is incomplete) orsoft(warn-and-continue). - TLS skip verify — for management self-signed cert during bring-up.
- Save → health check calls
/nitro/v1/config/nsversion.
Object naming
CertKey Name is optional. Leave it empty and each certificate deploying through the target gets its own auto-generated certkey object:
cap-<token>-<domain> # token: 8-char hash derived from the certificate; truncated to 31 chars total
This lets one NetScaler target serve many certificates without their certkeys colliding. Set the name explicitly only to adopt an existing certkey already bound to vservers — the module then updates it in place, preserving all bindings. The name can also be set per distribution (per target, with a * default row) from the certificate's Distributions → Overrides drawer.
On-appliance file names are derived from the certkey name automatically; fixed cert_filename/key_filename values are only accepted together with an explicit certkey name (a shared fixed file would be rewritten by every certificate and served wrong after a config reload).
Execution flow
- Upload cert PEM + key PEM to
/nsconfig/ssl/viasystemfilewith fingerprint-suffixed names. - Upload each intermediate certificate as its own file (dedup by fingerprint — identical intermediates across certs become one object).
- Create the
sslcertkeyobject if missing, or update it. - Link the intermediate chain to the
sslcertkeyviasslcertkey_sslcertkey_binding. (The module does not touch any profile or virtual-server binding — bindings to vservers are managed outside CertAutoPilot.) - Verify the link graph (
GET sslcertkey?filter=certkey:...) and fail the distribution if any chain edge is missing.
If the target VS / profile already references a cert object not created by CertAutoPilot, the module treats it as read-only — we unbind our updates from it but never delete it. This prevents accidental removal of certs shared across unrelated services on the same ADC.
Rollback — not supported
Old sslcertkey objects remain. To revert manually, bind the profile/VS to the previous sslcertkey name (still present). Automated rollback is not offered because SSL profile rebinds can cause session drops.
Troubleshooting
"Chain link verification failed"
An intermediate referenced by the cert is missing from the upload set. Check the cert's issuer chain completeness (openssl crl2pkcs7 ...). If your CA consistently omits an intermediate you can pre-upload it manually to the NetScaler and set chain handling to soft.
"sslcertkey object locked"
Another administrative session is editing the object. Wait and retry, or force-save the other session.
"VS rebind failed"
The VS name in the target config doesn't exist, or the user lacks bind permission on it. show lb vserver <name> on the CLI to confirm.