Step-by-step guide to configure Proxmox Web GUI/API with Let’s Encrypt certificate and automatic validation using the ACME protocol in DNS alias mode with DNS TXT validation redirection to Duck DNS.
We want to use a certificate in Proxmox GUI/API issued for free by a Certificate Authority trusted by default in browsers and operating systems. The chosen Certificate Authority will be Let's Encrypt [1]. Since the issued certificates are valid for only 90 days, automating the certificate renewal process is crucial. For this purpose, the Automatic Certificate Management Environment (ACME, RFC8555) protocol will be used [2].
Proxmox server in an internal network without direct exposure to the Internet, making it impossible to perform the challenge using the HTTP method, and the DNS server used for the domain (e.g. proxmox.example.com) does not support TXT record provisioning through API (required for DNS challenge). Therefore, it is necessary to use the DNS alias mode of acme.sh [3], which is natively integrated with Proxmox [4]. The Let's Encrypt challenge process will be redirected to the Duck DNS service, which provides dynamic DNS for free [5]. The procedures have been validated with Proxmox VE 8.0.3.
- [1] https://letsencrypt.org/getting-started/
- [2] https://datatracker.ietf.org/doc/html/rfc8555
- [3] https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode
- [4] https://pve.proxmox.com/wiki/Certificate_Management
- [5] https://www.duckdns.org/about.jsp
- Register a free domain at www.duckdns.org and obtain the authentication token.
Example domain: example.duckdns.org
Example token: 12345678-abcd-1234-5678-1234567890ab
- Create a DNS record in the internal network's DNS service where the Proxmox domain is registered.
_acme-challenge.proxmox.example.com. 3600 IN CNAME _acme-challenge.example.duckdns.org.
# Testing with dig
$ dig +short _acme-challenge.proxmox.example.com CNAME
_acme-challenge.example.duckdns.org.
Note: Keep the CNAME record for future certificate renewals.
- Register an account with Let's Encrypt and configure it on Proxmox.
ssh [email protected]
root@proxmox:~# pvenode acme account register account-name [email protected]
Directory endpoints:
0) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory)
1) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory)
2) Custom
Enter selection: 0
Attempting to fetch Terms of Service from 'https://acme-v02.api.letsencrypt.org/directory'..
Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf
Do you agree to the above terms? [y|N]: y
Attempting to register the account with 'https://acme-v02.api.letsencrypt.org/directory'..
Generating the ACME account key..
Registering the ACME account..
Registration successful, account URL: 'https://acme-v02.api.letsencrypt.org/acme/acct/***'
Task OK
- Configure the DNS validation plugin.
root@proxmox:~# echo 'DuckDNS_Token=12345678-abcd-1234-5678-1234567890ab' > ~/duckdns_api_token
root@proxmox:~# pvenode acme plugin add dns duckdns-challenge --api duckdns --data ~/duckdns_api_token
root@proxmox:~# pvenode config set --acmedomain0 proxmox.example.com,alias=example.duckdns.org,plugin=duckdns-challenge
root@proxmox:~# pvenode config set --acme account=account-name
- Issue the Let's Encrypt certificate and do the Proxmox configuration.
root@proxmox:~# pvenode acme cert order
Loading ACME account details
Placing the ACME order
Order URL: https://acme-v02.api.letsencrypt.org/acme/order/123456789/123456789
Getting authorization details from 'https://acme-v02.api.letsencrypt.org/acme/authz-v3/123456789'
The validation for proxmox.example.com is pending!
[Fri Aug 18 16:43:59 -03 2023] Trying to add the TXT record
[Fri Aug 18 16:44:00 -03 2023] The TXT record has been successfully added to your DuckDNS domain.
[Fri Aug 18 16:44:00 -03 2023] Note that all subdomains under this domain use the same TXT record.
Add the TXT record: _acme-challenge.proxmox.example.com
Waiting 30 seconds to allow the TXT record to propagate
Triggering validation
Waiting for 5 seconds
Status is 'valid', domain 'proxmox.example.com' is OK!
[Fri Aug 18 16:44:36 -03 2023] Trying to remove the TXT record
[Fri Aug 18 16:44:36 -03 2023] The TXT record has been successfully removed from your DuckDNS domain.
Remove the TXT record: _acme-challenge.proxmox.example.com
All domains have been validated!
Creating a CSR
Checking order status
The order is ready, finalizing the order
Valid!
Downloading the certificate
Setting the pveproxy certificate and key
Restarting the pveproxy
- Verify the issued Let's Encrypt certificate.
$ echo "" | openssl s_client -connect proxmox.example.com:8006 2> /dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' | openssl x509 -noout -issuer -subject -dates -in -
issuer=C = US, O = Let's Encrypt, CN = R3
subject=CN = proxmox.example.com
notBefore=Aug 18 18:44:39 2023 GMT
notAfter=Nov 16 18:44:38 2023 GMT
thanks, this totally helped me figure it out, i was doing this exact scenario pretty much