Running into strange Certificate Error - unable to get local issuer certificate (20)

crankintheburn

New Member
Aug 26, 2025
2
0
1
Hello community,

I've been searching the forum for a while now, trying to fix my certificate issue which ultimately leads to a blank Web GUI. I tried literally any suggested steps mentioned in different posts, but I'm still running into the same Error.

Key facts:
  • ~4 days old PVE installation on Hetzner dedicated
  • all no-subscription updates installed
  • after testing some VMs I wanted to order an ACME certificate
  • successfully ordered Let's Encrypt SSL-Cert via Hetzner DNS API at GUI level
  • Error: GUI blank
  • Reverted back to self-signed. Still blank.
restarted services with no error
Code:
systemctl restart pveproxy.service pvedaemon.service

journalctl -xe
Code:
journalctl -xe
░░ The unit pveproxy.service has successfully entered the 'dead' state.
Aug 26 07:59:49 <HOST> systemd[1]: Stopped pveproxy.service - PVE API Proxy Server.
░░ Subject: A stop job for unit pveproxy.service has finished
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░
░░ A stop job for unit pveproxy.service has finished.
░░
░░ The job identifier is 10489 and the job result is done.
Aug 26 07:59:49 <HOST> systemd[1]: pveproxy.service: Consumed 5min 58.803s CPU time, 415.5M memory peak.
░░ Subject: Resources consumed by unit runtime
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░
░░ The unit pveproxy.service completed and consumed the indicated resources.
Aug 26 07:59:49 <HOST> systemd[1]: Starting pveproxy.service - PVE API Proxy Server...
░░ Subject: A start job for unit pveproxy.service has begun execution
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░
░░ A start job for unit pveproxy.service has begun execution.
░░
░░ The job identifier is 10489.
Aug 26 07:59:51 <HOST> pveproxy[1570806]: Using '/etc/pve/local/pveproxy-ssl.pem' as certificate for the web interface.
Aug 26 07:59:51 <HOST> pveproxy[1570808]: starting server
Aug 26 07:59:51 <HOST> pveproxy[1570808]: starting 3 worker(s)
Aug 26 07:59:51 <HOST> pveproxy[1570808]: worker 1570809 started
Aug 26 07:59:51 <HOST> pveproxy[1570808]: worker 1570810 started
Aug 26 07:59:51 <HOST> pveproxy[1570808]: worker 1570811 started
Aug 26 07:59:51 <HOST> systemd[1]: Started pveproxy.service - PVE API Proxy Server.
░░ Subject: A start job for unit pveproxy.service has finished successfully
░░ Defined-By: systemd
░░ Support: https://www.debian.org/support
░░
░░ A start job for unit pveproxy.service has finished successfully.
░░
░░ The job identifier is 10489.


Forcefully ordered a new cert
Code:
pvenode acme cert order --force
Loading ACME account details
Placing ACME order
Order URL: https://acme-v02.api.letsencrypt.org/acme/order/1234567/1234567

Getting authorization details from 'https://acme-v02.api.letsencrypt.org/acme/authz/1234567897'
<HOST> is already validated!

All domains validated!

Creating CSR
Checking order status
Order is ready, finalizing order
valid!

Downloading certificate
Setting pveproxy certificate and key
Restarting pveproxy
Task OK

also tried
Code:
apt --reinstall install pve-manager
apt --reinstall install proxmox-widget-toolkit

trying with IP
Code:
curl -k -v https://<IP>:8006
*   Trying <IP>:8006...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / RSASSA-PSS
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: CN=<HOST>
*  start date: Aug 26 04:59:52 2025 GMT
*  expire date: Nov 24 04:59:51 2025 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R13
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to <IP> (<IP>) port 8006
* using HTTP/1.x
> GET / HTTP/1.1
> Host: <IP>:8006
> User-Agent: curl/8.14.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Request completely sent off
< HTTP/1.1 200 OK
< Cache-Control: max-age=0
< Connection: Keep-Alive
< Date: Tue, 26 Aug 2025 06:28:11 GMT
< Pragma: no-cache
< Server: pve-api-daemon/3.0
< Content-Length: 2667
< Content-Type: text/html; charset=utf-8
< Expires: Tue, 26 Aug 2025 06:28:11 GMT
<



same result with hostname
Code:
curl -k -v https://<HOST>:8006
* Host <HOST>:8006 was resolved.
* IPv6: (none)
* IPv4: <IP>
*   Trying <IP>:8006...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / RSASSA-PSS
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: CN=<HOST>
*  start date: Aug 26 04:59:52 2025 GMT
*  expire date: Nov 24 04:59:51 2025 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R13
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to <HOST> (<IP>) port 8006
* using HTTP/1.x
> GET / HTTP/1.1
> Host: <HOST>:8006
> User-Agent: curl/8.14.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Request completely sent off
< HTTP/1.1 200 OK
< Cache-Control: max-age=0
< Connection: Keep-Alive
< Date: Tue, 26 Aug 2025 06:54:52 GMT
< Pragma: no-cache
< Server: pve-api-daemon/3.0
< Content-Length: 2667
< Content-Type: text/html; charset=utf-8
< Expires: Tue, 26 Aug 2025 06:54:52 GMT

I then revoked the ACME certificate but still have the same error
Code:
pvenode acme cert revoke
Loading ACME account details
Revoking old certificate
Deleting certificate files
Restarting pveproxy to revert to self-signed certificates
Task OK


trying with hostname
Code:
curl -k -v https://<HOST>:8006
* Host <HOST>:8006 was resolved.
* IPv6: (none)
* IPv4: <IP>
*   Trying <IP>:8006...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / RSASSA-PSS
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: OU=PVE Cluster Node; O=Proxmox Virtual Environment; CN=<HOST>
*  start date: Aug 25 06:43:54 2025 GMT
*  expire date: Aug 25 06:43:54 2027 GMT
*  issuer: CN=Proxmox Virtual Environment; OU=2d866dc6-ecd3-4cf9-aadd-b9d00088734a; O=PVE Cluster Manager CA
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to <HOST> (<IP>) port 8006
* using HTTP/1.x
> GET / HTTP/1.1
> Host: <HOST>:8006
> User-Agent: curl/8.14.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Request completely sent off
< HTTP/1.1 200 OK
< Cache-Control: max-age=0
< Connection: Keep-Alive
< Date: Tue, 26 Aug 2025 06:54:52 GMT
< Pragma: no-cache
< Server: pve-api-daemon/3.0
< Content-Length: 2667
< Content-Type: text/html; charset=utf-8
< Expires: Tue, 26 Aug 2025 06:54:52 GMT

Code:
openssl verify -CAfile /etc/pve/pve-root-ca.pem /etc/pve/local/pveproxy-ssl.pem
CN=<HOST>
error 20 at 0 depth lookup: unable to get local issuer certificate
error /etc/pve/local/pveproxy-ssl.pem: verification failed


Code:
openssl s_client -connect <HOST>:8006 -showcerts
Connecting to <IP>
CONNECTED(00000003)
depth=0 OU=PVE Cluster Node, O=Proxmox Virtual Environment, CN=<HOST>
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU=PVE Cluster Node, O=Proxmox Virtual Environment, CN=<HOST>
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 OU=PVE Cluster Node, O=Proxmox Virtual Environment, CN=<HOST>
verify return:1

Also tried updating the pve certs
Code:
pvecm updatecerts -f
(re)generate node files
generate new node certificate
merge authorized SSH keys

Any suggestions what further steps could solve my issue?

My latin reached the end.

So long... Jonas
 
Last edited:
I solved the issue by manually adding the Let's Encrypt CA to the certificate chain '/etc/pve/local/pveproxy-ssl.pem'.
Code:
wget https://letsencrypt.org/certs/lets-encrypt-r3.pem
cat lets-encrypt-r3.pem >> pveproxy-ssl.pem
After restarting the pveproxy service, the GUI was back and running.

Interesting: I then did another cert-renewal
Code:
pvenode acme cert order
and after successful renewal everything still works.

So long... Jonas
 
Last edited: