]> git.proxmox.com Git - pve-docs.git/blame - certificate-management.adoc
rework certificates chapter, section ordering, ..
[pve-docs.git] / certificate-management.adoc
CommitLineData
aeecd9ea
SI
1[[sysadmin_certificate_management]]
2Certificate Management
3----------------------
4ifdef::wiki[]
5:pve-toplevel:
6endif::wiki[]
7
8
a7dca4d1
TL
9Certificates for Intra-Cluster Communication
10~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aeecd9ea 11
a7dca4d1
TL
12Each {PVE} cluster creates by default its own (self-signed) Certificate
13Authority (CA) and generates a certificate for each node which gets signed by
14the aforementioned CA. These certificates are used for encrypted communication
15with the cluster's `pveproxy` service and the Shell/Console feature if SPICE is
16used.
aeecd9ea 17
2971c735 18The CA certificate and key are stored in the xref:chapter_pmxcfs[Proxmox Cluster File System (pmxcfs)].
aeecd9ea 19
0a1739bd 20
a7dca4d1
TL
21[[sysadmin_certs_api_gui]]
22Certificates for API and Web GUI
aeecd9ea
SI
23~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
0e9c6c13
FG
25The REST API and web GUI are provided by the `pveproxy` service, which runs on
26each node.
aeecd9ea
SI
27
28You have the following options for the certificate used by `pveproxy`:
29
0e9c6c13
FG
301. By default the node-specific certificate in
31`/etc/pve/nodes/NODENAME/pve-ssl.pem` is used. This certificate is signed by
0a1739bd
TL
32the cluster CA and therefore not automatically trusted by browsers and
33operating systems.
0e9c6c13 342. use an externally provided certificate (e.g. signed by a commercial CA).
0a1739bd 353. use ACME (Let's Encrypt) to get a trusted certificate with automatic
da30f82a 36renewal, this is also integrated in the {pve} API and Webinterface.
aeecd9ea 37
0e9c6c13 38For options 2 and 3 the file `/etc/pve/local/pveproxy-ssl.pem` (and
aeecd9ea
SI
39`/etc/pve/local/pveproxy-ssl.key`, which needs to be without password) is used.
40
da30f82a
TL
41NOTE: Keep in mind that `/etc/pve/local` is a node specific symlink to
42`/etc/pve/nodes/NODENAME`.
43
aeecd9ea
SI
44Certificates are managed with the {PVE} Node management command
45(see the `pvenode(1)` manpage).
46
0e9c6c13
FG
47WARNING: Do not replace or manually modify the automatically generated node
48certificate files in `/etc/pve/local/pve-ssl.pem` and
49`/etc/pve/local/pve-ssl.key` or the cluster CA files in
50`/etc/pve/pve-root-ca.pem` and `/etc/pve/priv/pve-root-ca.key`.
aeecd9ea 51
0a1739bd 52
a7dca4d1
TL
53[[sysadmin_certs_get_trusted_acme_cert]]
54Trusted certificates via Let's Encrypt (ACME)
55~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0a1739bd 56
aeecd9ea
SI
57{PVE} includes an implementation of the **A**utomatic **C**ertificate
58**M**anagement **E**nvironment **ACME** protocol, allowing {pve} admins to
0e9c6c13
FG
59interface with Let's Encrypt for easy setup of trusted TLS certificates which
60are accepted out of the box on most modern operating systems and browsers.
aeecd9ea 61
a7dca4d1
TL
62Currently the two ACME endpoints implemented are the
63https://letsencrypt.org[Let's Encrypt (LE)] production and its staging
64environment. Our ACME client supports validation of `http-01` challenges using
65a built-in webserver and validation of `dns-01` challenges using a DNS plugin
66supporting all the DNS API endpoints https://acme.sh[acme.sh] does.
aeecd9ea 67
a7dca4d1
TL
68[[sysadmin_certs_acme_account]]
69ACME Account
70^^^^^^^^^^^^
71You need to register an ACME account per cluster with the endpoint you want to
72use. The email address used for that account will server as contact point for
73renewal-due or similar notifications from the ACME endpoint.
aeecd9ea 74
a7dca4d1 75// TODO: screenshot of account register here
0b447f1c 76
a7dca4d1
TL
77You can register and deactivate ACME accounts over the web interface
78`Datacenter -> ACME` or using the `pvenode` command line tool.
79----
80 pvenode acme account register account-name mail@example.com
81----
aeecd9ea 82
a7dca4d1
TL
83TIP: Because of https://letsencrypt.org/docs/rate-limits/[rate-limits] you
84should use LE `staging` for experiments or if you use ACME for the first time.
0b447f1c 85
a7dca4d1
TL
86[[sysadmin_certs_acme_plugins]]
87ACME Plugins
88^^^^^^^^^^^^
0b447f1c 89
a7dca4d1
TL
90The ACME plugins task is to provide automatic verification that you, and thus
91the {pve} cluster under your operation, are the real owner of a domain. This is
92the basis building block for automatic certificate management.
0b447f1c 93
a7dca4d1
TL
94The ACME protocol specifies different types of challenges, for example the
95`http-01` where a webserver provides a file with a certain value to proof that
96it controls a domain. Sometimes this isn't possible, either because of
97technical limitations or if the address a domain points to is not reachable
98from the public internet. For such cases one could use the `dns-01` challenge.
99That challenge provides also a certain value, but not over a text file, but
100through a DNS record on the authority name server of the domain.
0b447f1c 101
a7dca4d1
TL
102{pve} supports both of those challenge types out of the box, you can configure
103plugins either over the web interface under `Datacenter -> ACME`, or using the
104`pvenode acme plugin add` command.
aeecd9ea 105
a7dca4d1 106ACME Plugin configurations are stored in `/etc/pve/priv/acme/plugins.cfg`.
aeecd9ea 107
a7dca4d1
TL
108[[sysadmin_certs_acme_http_challenge]]
109ACME HTTP Challenge Plugin
110~~~~~~~~~~~~~~~~~~~~~~~~~~
aeecd9ea 111
a7dca4d1
TL
112There is always an implicitly configured `standalone` plugin for validating
113`http-01` challenges via the built-in webserver spawned on port 80.
aeecd9ea 114
a7dca4d1
TL
115NOTE: The name `standalone` means that it can provide the validation on it's
116own, without any third party service. So, this plugin works also for cluster
117nodes.
aeecd9ea 118
a7dca4d1
TL
119There are a few prerequisites to use it for certificate management with Let's
120Encrypts ACME.
aeecd9ea 121
a7dca4d1
TL
122* You have to accept the ToS of Let's Encrypt to register an account.
123* **Port 80** of the node needs to be reachable from the internet.
124* There **must** be no other listener on port 80.
125* The requested (sub)domain needs to resolve to a public IP of the Node.
aeecd9ea 126
aeecd9ea 127
a7dca4d1
TL
128[[sysadmin_certs_acme_dns_challenge]]
129ACME DNS API Challenge Plugin
130~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aeecd9ea 131
a7dca4d1
TL
132On systems where external access for validation via the `http-01` method is
133not possible or desired, it is possible to use the `dns-01` validation method.
134This validation method requires a DNS server that allows provisioning of `TXT`
135records via an API.
0e9c6c13 136
a7dca4d1
TL
137[[sysadmin_certs_acme_dns_api_config]]
138Configuring ACME DNS APIs for validation
139^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19b04e77 140
a7dca4d1
TL
141{PVE} re-uses the DNS plugins developed for the `acme.sh`
142footnote:[acme.sh https://github.com/acmesh-official/acme.sh]
143project, please refer to its documentation for details on configuration of
144specific APIs.
19b04e77 145
a7dca4d1
TL
146The easiest way to configure a new plugin with the DNS API is using the web
147interface (`Datacenter -> ACME`).
19b04e77 148
a7dca4d1
TL
149Choose `DNS` as challenge type. Then you can select your API provider, enter
150the credential data to access your account over their API.
19b04e77 151
a7dca4d1
TL
152TIP: See the acme.sh
153https://github.com/acmesh-official/acme.sh/wiki/dnsapi#how-to-use-dns-api[How to use DNS API]
154wiki for more detailed information about getting API credentials for your
155provider.
19b04e77 156
a7dca4d1
TL
157As there are so many API endpoints {pve} autogenerates the formular for the
158credentials, but not all providers are annotated yet. For those you will see a
159bigger text area, simply copy all the credentials `KEY`=`VALUE` pairs in there.
d75e644b 160
a7dca4d1
TL
161DNS Validation through CNAME Alias
162^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19b04e77 163
a7dca4d1
TL
164A special `alias` mode can be used to handle the validation on a different
165domain/DNS server, in case your primary/real DNS does not support provisioning
166via an API. Manually set up a permanent `CNAME` record for
167`_acme-challenge.domain1.example` pointing to `_acme-challenge.domain2.example`
168and set the `alias` property in the {PVE} node configuration file to
169`domain2.example` to allow the DNS server of `domain2.example` to validate all
170challenges for `domain1.example`.
19b04e77 171
19b04e77 172
a7dca4d1
TL
173Combination of Plugins
174^^^^^^^^^^^^^^^^^^^^^^
175
176Combining `http-01` and `dns-01` validation is possible in case your node is
177reachable via multiple domains with different requirements / DNS provisioning
178capabilities. Mixing DNS APIs from multiple providers or instances is also
179possible by specifying different plugin instances per domain.
180
181TIP: Accessing the same service over multiple domains increases complexity and
182should be avoided if possible.
183
184[[sysadmin_certs_acme_automatic_renewal]]
0e9c6c13 185Automatic renewal of ACME certificates
a7dca4d1 186~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0e9c6c13
FG
187
188If a node has been successfully configured with an ACME-provided certificate
189(either via pvenode or via the GUI), the certificate will be automatically
190renewed by the pve-daily-update.service. Currently, renewal will be attempted
da30f82a 191if the certificate has expired already, or will expire in the next 30 days.
0b447f1c 192
0b447f1c 193
a7dca4d1
TL
194ACME Examples with `pvenode`
195~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0b447f1c 196
a7dca4d1
TL
197Example: Sample `pvenode` invocation for using Let's Encrypt certificates
198^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0b447f1c 199
a7dca4d1
TL
200----
201root@proxmox:~# pvenode acme account register default mail@example.invalid
202Directory endpoints:
2030) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory)
2041) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory)
2052) Custom
206Enter selection: 1
0b447f1c 207
a7dca4d1
TL
208Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
209Do you agree to the above terms? [y|N]y
210...
211Task OK
212root@proxmox:~# pvenode config set --acme domains=example.invalid
213root@proxmox:~# pvenode acme cert order
214Loading ACME account details
215Placing ACME order
216...
217Status is 'valid'!
218
219All domains validated!
220...
221Downloading certificate
222Setting pveproxy certificate and key
223Restarting pveproxy
224Task OK
225----
0b447f1c 226
a7dca4d1
TL
227Example: Setting up the OVH API for validating a domain
228^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0b447f1c 229
186c094b
TL
230NOTE: the account registration steps are the same no matter which plugins are
231used, and are not repeated here.
232
233NOTE: `OVH_AK` and `OVH_AS` need to be obtained from OVH according to the OVH
234API documentation
235
236
237First you need to get all information so you and {pve} can access the API.
0b447f1c
FG
238
239----
240root@proxmox:~# cat /path/to/api-token
241OVH_AK=XXXXXXXXXXXXXXXX
242OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
243root@proxmox:~# source /path/to/api-token
244root@proxmox:~# curl -XPOST -H"X-Ovh-Application: $OVH_AK" -H "Content-type: application/json" \
245https://eu.api.ovh.com/1.0/auth/credential -d '{
246 "accessRules": [
247 {"method": "GET","path": "/auth/time"},
248 {"method": "GET","path": "/domain"},
249 {"method": "GET","path": "/domain/zone/*"},
250 {"method": "GET","path": "/domain/zone/*/record"},
251 {"method": "POST","path": "/domain/zone/*/record"},
252 {"method": "POST","path": "/domain/zone/*/refresh"},
253 {"method": "PUT","path": "/domain/zone/*/record/"},
254 {"method": "DELETE","path": "/domain/zone/*/record/*"}
255]
256}'
257{"consumerKey":"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ","state":"pendingValidation","validationUrl":"https://eu.api.ovh.com/auth/?credentialToken=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}
258
259(open validation URL and follow instructions to link Application Key with account/Consumer Key)
260
261root@proxmox:~# echo "OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" >> /path/to/api-token
186c094b
TL
262----
263
264Now you can setup the the ACME plugin:
265
266----
0b447f1c
FG
267root@proxmox:~# pvenode acme plugin add dns example_plugin --api ovh --data /path/to/api_token
268root@proxmox:~# pvenode acme plugin config example_plugin
269┌────────┬──────────────────────────────────────────┐
270│ key │ value │
271╞════════╪══════════════════════════════════════════╡
272│ api │ ovh │
273├────────┼──────────────────────────────────────────┤
274│ data │ OVH_AK=XXXXXXXXXXXXXXXX │
275│ │ OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY │
276│ │ OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ │
277├────────┼──────────────────────────────────────────┤
278│ digest │ 867fcf556363ca1bea866863093fcab83edf47a1 │
279├────────┼──────────────────────────────────────────┤
280│ plugin │ example_plugin │
281├────────┼──────────────────────────────────────────┤
282│ type │ dns │
283└────────┴──────────────────────────────────────────┘
186c094b
TL
284----
285
286At last you can configure the domain you want to get certitficates for and
287place the certificate order for it:
288
289----
0b447f1c
FG
290root@proxmox:~# pvenode config set -acmedomain0 example.proxmox.com,plugin=example_plugin
291root@proxmox:~# pvenode acme cert order
292Loading ACME account details
293Placing ACME order
294Order URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/11111111/22222222
295
296Getting authorization details from 'https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/33333333'
297The validation for example.proxmox.com is pending!
298[Wed Apr 22 09:25:30 CEST 2020] Using OVH endpoint: ovh-eu
299[Wed Apr 22 09:25:30 CEST 2020] Checking authentication
300[Wed Apr 22 09:25:30 CEST 2020] Consumer key is ok.
301[Wed Apr 22 09:25:31 CEST 2020] Adding record
302[Wed Apr 22 09:25:32 CEST 2020] Added, sleep 10 seconds.
303Add TXT record: _acme-challenge.example.proxmox.com
304Triggering validation
305Sleeping for 5 seconds
306Status is 'valid'!
307[Wed Apr 22 09:25:48 CEST 2020] Using OVH endpoint: ovh-eu
308[Wed Apr 22 09:25:48 CEST 2020] Checking authentication
309[Wed Apr 22 09:25:48 CEST 2020] Consumer key is ok.
310Remove TXT record: _acme-challenge.example.proxmox.com
311
312All domains validated!
313
314Creating CSR
315Checking order status
316Order is ready, finalizing order
317valid!
318
319Downloading certificate
320Setting pveproxy certificate and key
321Restarting pveproxy
322Task OK
323----
a7dca4d1
TL
324
325[[sysadmin_certs_acme_switch_from_staging]]
326Example: Switching from the `staging` to the regular ACME directory
327^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
328
329Changing the ACME directory for an account is unsupported, but as {pve}
330supports more than one account you can just create a new one with the
331production (trusted) ACME directory as endpoint. You can also deactivate the
332staging account and recreate it.
333
334// TODO: add example with account screenshot here
335
336.Example: Changing the `default` ACME account from `staging` to directory using `pvenode`
337----
338root@proxmox:~# pvenode acme account deactivate default
339Renaming account file from '/etc/pve/priv/acme/default' to '/etc/pve/priv/acme/_deactivated_default_4'
340Task OK
341
342root@proxmox:~# pvenode acme account register default example@proxmox.com
343Directory endpoints:
3440) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory)
3451) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory)
3462) Custom
347Enter selection: 0
348
349Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf
350Do you agree to the above terms? [y|N]y
351...
352Task OK
353----