Proxmox TLS Trust¶
Choose one TLS mode per connection. TLS certificate verification is always on; there is no "disable verification" switch.
| Mode | When | What the panel does |
|---|---|---|
system_ca (default) |
PVE serves a certificate chained to a public CA (a real hostname with Let's Encrypt, or an enterprise CA already in the panel host's system bundle). | Standard curl verification (verify=true). |
pinned_fingerprint |
Self-signed PVE certificate (the default PVE setup). | Public-key pinning: chain verification off, the presented SPKI must match the stored sha256//… pin. |
custom_ca |
An internal CA the panel host does not trust system-wide. | Paste the CA PEM into the connection; it is stored encrypted, written to a 0600 temp file only while a client is built, and passed to curl as the CA bundle. |
Pinned fingerprint¶
The pin format is exactly what curl's CURLOPT_PINNEDPUBLICKEY expects:
sha256//<base64(sha256(SPKI DER))>.
Capture it with the client's helper:
php artisan tinker --execute='echo \PteroCloud\Services\Providers\Proxmox\ProxmoxApiClient::captureCertificateFingerprint("pve.example.com", 8006), PHP_EOL;'
Or derive it yourself:
openssl s_client -connect pve.example.com:8006 </dev/null \
| openssl x509 -pubkey | openssl pkey -pubin -outform DER \
| openssl dgst -sha256 -binary | base64
Bootstrap flow: add the connection with pinned_fingerprint mode and no
fingerprint — until a pin exists the mode connects unverified (that IS the
bootstrap). Capture the pin out of band, store it via PATCH, and it is enforced
from then on. A later key change fails closed with TLS_FINGERPRINT_MISMATCH.
Error codes¶
| Code | Cause | Fix |
|---|---|---|
TLS_UNTRUSTED |
Self-signed cert under system_ca, or wrong/expired CA under custom_ca. |
Switch to pinned_fingerprint (bootstrap capture) or supply the correct CA PEM. |
TLS_FINGERPRINT_MISMATCH |
PVE certificate/key changed after the pin was captured. | Verify the change was expected, then re-capture (clear the fingerprint and test again). |