are accepted out of the box on most modern operating systems and browsers.
Currently the two ACME endpoints implemented are Let's Encrypt (LE) and its
-staging environment (see https://letsencrypt.org), both using the standalone
-HTTP challenge.
+staging environment (see https://letsencrypt.org). Our ACME client supports
+validation of `http-01` challenges using a built-in webserver and validation of
+`dns-01` challenges using a DNS plugin.
Because of https://letsencrypt.org/docs/rate-limits/[rate-limits] you should use
LE `staging` for experiments.
+ACME Plugin configuration is stored in `/etc/pve/priv/acme/plugins.cfg`. There
+is always an implicitly configured `standalone` plugin for validating `http-01`
+challenges via the built-in webserver spawned on port 80.
+
There are a few prerequisites to use Let's Encrypt:
-1. **Port 80** of the node needs to be reachable from the internet.
-2. There **must** be no other listener on port 80.
-3. The requested (sub)domain needs to resolve to a public IP of the Node.
-4. You have to accept the ToS of Let's Encrypt.
+* You have to accept the ToS of Let's Encrypt to register an account.
+
+For `http-01` challenges:
+
+* **Port 80** of the node needs to be reachable from the internet.
+* There **must** be no other listener on port 80.
+* The requested (sub)domain needs to resolve to a public IP of the Node.
+
+For `dns-01` challenges:
+
+* DNS needs to be handled by a server that allows automatic provisioning of
+TXT records
At the moment the GUI uses only the default ACME account.
(either via pvenode or via the GUI), the certificate will be automatically
renewed by the pve-daily-update.service. Currently, renewal will be attempted
if the certificate has expired already, or will expire in the next 30 days.
+
+Configuring DNS APIs for validation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+On systems where external access for validation via the `http-01` method is
+not possible or desired, it is possible to use the `dns-01` validation method.
+This validation method requires a DNS server that allows provisioning of `TXT`
+records via an API.
+
+{PVE} re-uses the DNS plugins developed for the `acme.sh`
+footnote:[acme.sh https://github.com/acmesh-official/acme.sh]
+project, please refer to its documentation for details on configuration of
+specific APIs.
+
+Combining `http-01` and `dns-01` validation is possible in case your node is
+reachable via multiple domains with different requirements / DNS provisioning
+capabilities. Mixing DNS APIs from multiple providers or instances is also
+possible by specifying different plugin instances per domain.
+
+A special `alias` mode can be used to handle the validation on a different
+domain/DNS server, in case your primary/real DNS does not support provisioning
+via an API. Manually set up a permanent `CNAME` record for
+`_acme-challenge.domain1.example` pointing to `_acme-challenge.domain2.example`
+and set the `alias` property in the {PVE} node configuration file to
+`domain2.example` to allow the DNS server of `domain2.example` to validate all
+challenges for `domain1.example`.
+
+.Example: Setting up the OVH API for validating a domain
+
+Note:: the account registration steps are the same no matter which plugins are used, and are not repeated here.
+Note:: `OVH_AK` and `OVH_AS` need to be obtained from OVH according to the OVH API documentation
+
+----
+root@proxmox:~# cat /path/to/api-token
+OVH_AK=XXXXXXXXXXXXXXXX
+OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
+root@proxmox:~# source /path/to/api-token
+root@proxmox:~# curl -XPOST -H"X-Ovh-Application: $OVH_AK" -H "Content-type: application/json" \
+https://eu.api.ovh.com/1.0/auth/credential -d '{
+ "accessRules": [
+ {"method": "GET","path": "/auth/time"},
+ {"method": "GET","path": "/domain"},
+ {"method": "GET","path": "/domain/zone/*"},
+ {"method": "GET","path": "/domain/zone/*/record"},
+ {"method": "POST","path": "/domain/zone/*/record"},
+ {"method": "POST","path": "/domain/zone/*/refresh"},
+ {"method": "PUT","path": "/domain/zone/*/record/"},
+ {"method": "DELETE","path": "/domain/zone/*/record/*"}
+]
+}'
+{"consumerKey":"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ","state":"pendingValidation","validationUrl":"https://eu.api.ovh.com/auth/?credentialToken=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}
+
+(open validation URL and follow instructions to link Application Key with account/Consumer Key)
+
+root@proxmox:~# echo "OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" >> /path/to/api-token
+root@proxmox:~# pvenode acme plugin add dns example_plugin --api ovh --data /path/to/api_token
+root@proxmox:~# pvenode acme plugin config example_plugin
+┌────────┬──────────────────────────────────────────┐
+│ key │ value │
+╞════════╪══════════════════════════════════════════╡
+│ api │ ovh │
+├────────┼──────────────────────────────────────────┤
+│ data │ OVH_AK=XXXXXXXXXXXXXXXX │
+│ │ OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY │
+│ │ OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ │
+├────────┼──────────────────────────────────────────┤
+│ digest │ 867fcf556363ca1bea866863093fcab83edf47a1 │
+├────────┼──────────────────────────────────────────┤
+│ plugin │ example_plugin │
+├────────┼──────────────────────────────────────────┤
+│ type │ dns │
+└────────┴──────────────────────────────────────────┘
+root@proxmox:~# pvenode config set -acmedomain0 example.proxmox.com,plugin=example_plugin
+root@proxmox:~# pvenode acme cert order
+Loading ACME account details
+Placing ACME order
+Order URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/11111111/22222222
+
+Getting authorization details from 'https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/33333333'
+The validation for example.proxmox.com is pending!
+[Wed Apr 22 09:25:30 CEST 2020] Using OVH endpoint: ovh-eu
+[Wed Apr 22 09:25:30 CEST 2020] Checking authentication
+[Wed Apr 22 09:25:30 CEST 2020] Consumer key is ok.
+[Wed Apr 22 09:25:31 CEST 2020] Adding record
+[Wed Apr 22 09:25:32 CEST 2020] Added, sleep 10 seconds.
+Add TXT record: _acme-challenge.example.proxmox.com
+Triggering validation
+Sleeping for 5 seconds
+Status is 'valid'!
+[Wed Apr 22 09:25:48 CEST 2020] Using OVH endpoint: ovh-eu
+[Wed Apr 22 09:25:48 CEST 2020] Checking authentication
+[Wed Apr 22 09:25:48 CEST 2020] Consumer key is ok.
+Remove TXT record: _acme-challenge.example.proxmox.com
+
+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
+----