Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save meehatpa/a20fa0809536c0d93aa8940b06df64be to your computer and use it in GitHub Desktop.
Save meehatpa/a20fa0809536c0d93aa8940b06df64be to your computer and use it in GitHub Desktop.
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.

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.


Objective

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].


Scenario

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.


References

Steps

  1. 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

  1. 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.

  1. Register an account with Let's Encrypt and configure it on Proxmox.
ssh root@proxmox.example.com

root@proxmox:~# pvenode acme account register account-name mail@example.com

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
  1. 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
  1. 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
  1. 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

Passo a passo para configurar Proxmox Web GUI/API com certificado Let’s Encrypt e validação automática com protocolo ACME no modo DNS alias com redirecionamento da validação DNS TXT para o Duck DNS.


Objetivo

Utilizar no Proxmox GUI/API um certificado emitido gratuitamente por Autoridade Certificadora confiada por padrão nos navegadores e sistemas operacionais. A Autoridade Certificadora utilizada será a Let's Encrypt [1]. Como os certificados emitidos são válidos por apenas 90 dias, é importante automatizar o processo de renovação dos certificados. Para isso, será utilizado o protocolo Automatic Certificate Management Environment (ACME, RFC8555) [2]


Cenário

Servidor Proxmox em rede interna sem exposição na Internet, não sendo possível realizar o challenge pelo método HTTP e o servidor o DNS utilizado para o domínio (ex. proxmox.exemplo.com) não possue funcionalidade de provisionamento de registros TXT via API (necessário para o challenge DNS). Dessa forma, se faz necessário utilizar o modo DNS alias do acme.sh [3] que é nativamente integrado ao Proxmox [4]. O processo de validação (challenge) do Let's Encrypt será direcionado para o serviço Duck DNS que provê DNS dinâmico gratuitamente [5]. Os procedimentos validados com Proxmox VE 8.0.3.


Referências


Passos

  1. Registrar gratuitamente um domínio em www.duckdns.org e obter o token de autenticação.

Domínio de exemplo: exemplo.duckdns.org

Token de exemplo: 12345678-abcd-1234-5678-1234567890ab

  1. Criar apontamento no serviço DNS da rede interna onde está registrado o domínio do Proxmox.

_acme-challenge.proxmox.exemplo.com. 3600 IN CNAME _acme-challenge.exemplo.duckdns.org.

# Testing with dig
$ dig +short _acme-challenge.proxmox.exemplo.com CNAME
_acme-challenge.exemplo.duckdns.org.

OBS: manter registro CNAME para futuras renovações do certificado.

  1. Registrar um conta no Let's Encrypt e fazer a configuração no Proxmox.
ssh root@proxmox.exemplo.com

root@proxmox:~# pvenode acme account register account-name mail@example.com

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 account with 'https://acme-v02.api.letsencrypt.org/directory'..
Generating ACME account key..
Registering ACME account..
Registration successful, account URL: 'https://acme-v02.api.letsencrypt.org/acme/acct/***'
Task OK
  1. Configurar Plugin para validação por DNS.
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.exemplo.com,alias=exemplo.duckdns.org,plugin=duckdns-challenge

root@proxmox:~# pvenode config set --acme account=account-name
  1. Emitir Certificado Let's Encrypt com configuração no Proxmox.
root@proxmox:~# pvenode acme cert order

Loading ACME account details
Placing 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.examplo.com is pending!
[Fri Aug 18 16:43:59 -03 2023] Trying to add TXT record
[Fri Aug 18 16:44:00 -03 2023] 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 uses the same TXT record.
Add TXT record: _acme-challenge.proxmox.exemplo.com
Sleeping 30 seconds to wait for TXT record propagation
Triggering validation
Sleeping for 5 seconds
Status is 'valid', domain 'proxmox.examplo.com' OK!
[Fri Aug 18 16:44:36 -03 2023] Trying to remove TXT record
[Fri Aug 18 16:44:36 -03 2023] TXT record has been successfully removed from your DuckDNS domain.
Remove TXT record: _acme-challenge.proxmox.exemplo.com

All domains validated!

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

Downloading certificate
Setting pveproxy certificate and key
Restarting pveproxy
  1. Verificando o certificado Let's Encrypt emitido
$ echo "" | openssl s_client -connect proxmox.exemplo.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.examplo.com
notBefore=Aug 18 18:44:39 2023 GMT
notAfter=Nov 16 18:44:38 2023 GMT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment