]>
Commit | Line | Data |
---|---|---|
aeecd9ea SI |
1 | [[sysadmin_certificate_management]] |
2 | Certificate Management | |
3 | ---------------------- | |
4 | ifdef::wiki[] | |
5 | :pve-toplevel: | |
6 | endif::wiki[] | |
7 | ||
8 | ||
9 | Certificates for communication within the cluster | |
10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
11 | ||
94958b8b | 12 | Each {PVE} cluster creates its own (self-signed) Certificate Authority (CA) and |
1a58a3c9 TL |
13 | generates a certificate for each node which gets signed by the aforementioned |
14 | CA. These certificates are used for encrypted communication with the cluster's | |
15 | `pveproxy` service and the Shell/Console feature if SPICE is used. | |
aeecd9ea | 16 | |
2971c735 | 17 | The CA certificate and key are stored in the xref:chapter_pmxcfs[Proxmox Cluster File System (pmxcfs)]. |
aeecd9ea SI |
18 | |
19 | Certificates for API and web GUI | |
20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
21 | ||
0e9c6c13 FG |
22 | The REST API and web GUI are provided by the `pveproxy` service, which runs on |
23 | each node. | |
aeecd9ea SI |
24 | |
25 | You have the following options for the certificate used by `pveproxy`: | |
26 | ||
0e9c6c13 FG |
27 | 1. By default the node-specific certificate in |
28 | `/etc/pve/nodes/NODENAME/pve-ssl.pem` is used. This certificate is signed by | |
29 | the cluster CA and therefore not trusted by browsers and operating systems by | |
30 | default. | |
31 | 2. use an externally provided certificate (e.g. signed by a commercial CA). | |
da30f82a TL |
32 | 3. use ACME (e.g., Let's Encrypt) to get a trusted certificate with automatic |
33 | renewal, this is also integrated in the {pve} API and Webinterface. | |
aeecd9ea | 34 | |
0e9c6c13 | 35 | For options 2 and 3 the file `/etc/pve/local/pveproxy-ssl.pem` (and |
aeecd9ea SI |
36 | `/etc/pve/local/pveproxy-ssl.key`, which needs to be without password) is used. |
37 | ||
da30f82a TL |
38 | NOTE: Keep in mind that `/etc/pve/local` is a node specific symlink to |
39 | `/etc/pve/nodes/NODENAME`. | |
40 | ||
aeecd9ea SI |
41 | Certificates are managed with the {PVE} Node management command |
42 | (see the `pvenode(1)` manpage). | |
43 | ||
0e9c6c13 FG |
44 | WARNING: Do not replace or manually modify the automatically generated node |
45 | certificate files in `/etc/pve/local/pve-ssl.pem` and | |
46 | `/etc/pve/local/pve-ssl.key` or the cluster CA files in | |
47 | `/etc/pve/pve-root-ca.pem` and `/etc/pve/priv/pve-root-ca.key`. | |
aeecd9ea SI |
48 | |
49 | Getting trusted certificates via ACME | |
50 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
51 | {PVE} includes an implementation of the **A**utomatic **C**ertificate | |
52 | **M**anagement **E**nvironment **ACME** protocol, allowing {pve} admins to | |
0e9c6c13 FG |
53 | interface with Let's Encrypt for easy setup of trusted TLS certificates which |
54 | are accepted out of the box on most modern operating systems and browsers. | |
aeecd9ea SI |
55 | |
56 | Currently the two ACME endpoints implemented are Let's Encrypt (LE) and its | |
0b447f1c FG |
57 | staging environment (see https://letsencrypt.org). Our ACME client supports |
58 | validation of `http-01` challenges using a built-in webserver and validation of | |
59 | `dns-01` challenges using a DNS plugin. | |
aeecd9ea SI |
60 | |
61 | Because of https://letsencrypt.org/docs/rate-limits/[rate-limits] you should use | |
62 | LE `staging` for experiments. | |
63 | ||
0b447f1c FG |
64 | ACME Plugin configuration is stored in `/etc/pve/priv/acme/plugins.cfg`. There |
65 | is always an implicitly configured `standalone` plugin for validating `http-01` | |
66 | challenges via the built-in webserver spawned on port 80. | |
67 | ||
aeecd9ea SI |
68 | There are a few prerequisites to use Let's Encrypt: |
69 | ||
0b447f1c FG |
70 | * You have to accept the ToS of Let's Encrypt to register an account. |
71 | ||
72 | For `http-01` challenges: | |
73 | ||
74 | * **Port 80** of the node needs to be reachable from the internet. | |
75 | * There **must** be no other listener on port 80. | |
76 | * The requested (sub)domain needs to resolve to a public IP of the Node. | |
77 | ||
78 | For `dns-01` challenges: | |
79 | ||
80 | * DNS needs to be handled by a server that allows automatic provisioning of | |
81 | TXT records | |
aeecd9ea SI |
82 | |
83 | At the moment the GUI uses only the default ACME account. | |
84 | ||
85 | .Example: Sample `pvenode` invocation for using Let's Encrypt certificates | |
86 | ||
b0014034 | 87 | ---- |
aeecd9ea SI |
88 | root@proxmox:~# pvenode acme account register default mail@example.invalid |
89 | Directory endpoints: | |
90 | 0) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory) | |
91 | 1) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory) | |
92 | 2) Custom | |
93 | Enter selection: | |
94 | 1 | |
95 | ||
96 | Attempting to fetch Terms of Service from 'https://acme-staging-v02.api.letsencrypt.org/directory'.. | |
97 | Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf | |
98 | Do you agree to the above terms? [y|N]y | |
99 | ||
100 | Attempting to register account with 'https://acme-staging-v02.api.letsencrypt.org/directory'.. | |
101 | Generating ACME account key.. | |
102 | Registering ACME account.. | |
103 | Registration successful, account URL: 'https://acme-staging-v02.api.letsencrypt.org/acme/acct/xxxxxxx' | |
104 | Task OK | |
105 | root@proxmox:~# pvenode acme account list | |
106 | default | |
107 | root@proxmox:~# pvenode config set --acme domains=example.invalid | |
108 | root@proxmox:~# pvenode acme cert order | |
109 | Loading ACME account details | |
110 | Placing ACME order | |
111 | Order URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/xxxxxxxxxxxxxx | |
112 | ||
113 | Getting authorization details from | |
114 | 'https://acme-staging-v02.api.letsencrypt.org/acme/authz/xxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxx' | |
115 | ... pending! | |
116 | Setting up webserver | |
117 | Triggering validation | |
118 | Sleeping for 5 seconds | |
119 | Status is 'valid'! | |
120 | ||
121 | All domains validated! | |
122 | ||
123 | Creating CSR | |
124 | Finalizing order | |
125 | Checking order status | |
126 | valid! | |
127 | ||
128 | Downloading certificate | |
129 | Setting pveproxy certificate and key | |
130 | Restarting pveproxy | |
131 | Task OK | |
d75e644b | 132 | ---- |
0e9c6c13 | 133 | |
19b04e77 | 134 | Switching from the `staging` to the regular ACME directory |
b0014034 | 135 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
19b04e77 SI |
136 | |
137 | Changing the ACME directory for an account is unsupported. If you want to switch | |
138 | an account from the `staging` ACME directory to the regular, trusted, one you | |
139 | need to deactivate it and recreate it. | |
140 | ||
141 | This procedure is also needed to change the default ACME account used in the GUI. | |
142 | ||
143 | .Example: Changing the `default` ACME account from the `staging` to the regular directory | |
144 | ||
d75e644b | 145 | ---- |
19b04e77 SI |
146 | root@proxmox:~# pvenode acme account info default |
147 | Directory URL: https://acme-staging-v02.api.letsencrypt.org/directory | |
148 | Account URL: https://acme-staging-v02.api.letsencrypt.org/acme/acct/6332194 | |
149 | Terms Of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf | |
150 | ||
151 | Account information: | |
152 | ID: xxxxxxx | |
153 | Contact: | |
154 | - mailto:example@proxmox.com | |
155 | Creation date: 2018-07-31T08:41:44.54196435Z | |
156 | Initial IP: 192.0.2.1 | |
157 | Status: valid | |
158 | ||
159 | root@proxmox:~# pvenode acme account deactivate default | |
160 | Renaming account file from '/etc/pve/priv/acme/default' to '/etc/pve/priv/acme/_deactivated_default_4' | |
161 | Task OK | |
d75e644b | 162 | |
19b04e77 SI |
163 | root@proxmox:~# pvenode acme account register default example@proxmox.com |
164 | Directory endpoints: | |
165 | 0) Let's Encrypt V2 (https://acme-v02.api.letsencrypt.org/directory) | |
166 | 1) Let's Encrypt V2 Staging (https://acme-staging-v02.api.letsencrypt.org/directory) | |
167 | 2) Custom | |
168 | Enter selection: | |
169 | 0 | |
170 | ||
171 | Attempting to fetch Terms of Service from 'https://acme-v02.api.letsencrypt.org/directory'.. | |
172 | Terms of Service: https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf | |
173 | Do you agree to the above terms? [y|N]y | |
174 | ||
175 | Attempting to register account with 'https://acme-v02.api.letsencrypt.org/directory'.. | |
176 | Generating ACME account key.. | |
177 | Registering ACME account.. | |
178 | Registration successful, account URL: 'https://acme-v02.api.letsencrypt.org/acme/acct/39335247' | |
179 | Task OK | |
d75e644b | 180 | ---- |
19b04e77 | 181 | |
0e9c6c13 FG |
182 | Automatic renewal of ACME certificates |
183 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
184 | ||
185 | If a node has been successfully configured with an ACME-provided certificate | |
186 | (either via pvenode or via the GUI), the certificate will be automatically | |
187 | renewed by the pve-daily-update.service. Currently, renewal will be attempted | |
da30f82a | 188 | if the certificate has expired already, or will expire in the next 30 days. |
0b447f1c FG |
189 | |
190 | Configuring DNS APIs for validation | |
191 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
192 | ||
193 | On systems where external access for validation via the `http-01` method is | |
194 | not possible or desired, it is possible to use the `dns-01` validation method. | |
195 | This validation method requires a DNS server that allows provisioning of `TXT` | |
196 | records via an API. | |
197 | ||
198 | {PVE} re-uses the DNS plugins developed for the `acme.sh` | |
199 | footnote:[acme.sh https://github.com/acmesh-official/acme.sh] | |
200 | project, please refer to its documentation for details on configuration of | |
201 | specific APIs. | |
202 | ||
203 | Combining `http-01` and `dns-01` validation is possible in case your node is | |
204 | reachable via multiple domains with different requirements / DNS provisioning | |
205 | capabilities. Mixing DNS APIs from multiple providers or instances is also | |
206 | possible by specifying different plugin instances per domain. | |
207 | ||
208 | A special `alias` mode can be used to handle the validation on a different | |
209 | domain/DNS server, in case your primary/real DNS does not support provisioning | |
210 | via an API. Manually set up a permanent `CNAME` record for | |
211 | `_acme-challenge.domain1.example` pointing to `_acme-challenge.domain2.example` | |
212 | and set the `alias` property in the {PVE} node configuration file to | |
213 | `domain2.example` to allow the DNS server of `domain2.example` to validate all | |
214 | challenges for `domain1.example`. | |
215 | ||
216 | .Example: Setting up the OVH API for validating a domain | |
217 | ||
186c094b TL |
218 | NOTE: the account registration steps are the same no matter which plugins are |
219 | used, and are not repeated here. | |
220 | ||
221 | NOTE: `OVH_AK` and `OVH_AS` need to be obtained from OVH according to the OVH | |
222 | API documentation | |
223 | ||
224 | ||
225 | First you need to get all information so you and {pve} can access the API. | |
0b447f1c FG |
226 | |
227 | ---- | |
228 | root@proxmox:~# cat /path/to/api-token | |
229 | OVH_AK=XXXXXXXXXXXXXXXX | |
230 | OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY | |
231 | root@proxmox:~# source /path/to/api-token | |
232 | root@proxmox:~# curl -XPOST -H"X-Ovh-Application: $OVH_AK" -H "Content-type: application/json" \ | |
233 | https://eu.api.ovh.com/1.0/auth/credential -d '{ | |
234 | "accessRules": [ | |
235 | {"method": "GET","path": "/auth/time"}, | |
236 | {"method": "GET","path": "/domain"}, | |
237 | {"method": "GET","path": "/domain/zone/*"}, | |
238 | {"method": "GET","path": "/domain/zone/*/record"}, | |
239 | {"method": "POST","path": "/domain/zone/*/record"}, | |
240 | {"method": "POST","path": "/domain/zone/*/refresh"}, | |
241 | {"method": "PUT","path": "/domain/zone/*/record/"}, | |
242 | {"method": "DELETE","path": "/domain/zone/*/record/*"} | |
243 | ] | |
244 | }' | |
245 | {"consumerKey":"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ","state":"pendingValidation","validationUrl":"https://eu.api.ovh.com/auth/?credentialToken=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"} | |
246 | ||
247 | (open validation URL and follow instructions to link Application Key with account/Consumer Key) | |
248 | ||
249 | root@proxmox:~# echo "OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" >> /path/to/api-token | |
186c094b TL |
250 | ---- |
251 | ||
252 | Now you can setup the the ACME plugin: | |
253 | ||
254 | ---- | |
0b447f1c FG |
255 | root@proxmox:~# pvenode acme plugin add dns example_plugin --api ovh --data /path/to/api_token |
256 | root@proxmox:~# pvenode acme plugin config example_plugin | |
257 | ┌────────┬──────────────────────────────────────────┐ | |
258 | │ key │ value │ | |
259 | ╞════════╪══════════════════════════════════════════╡ | |
260 | │ api │ ovh │ | |
261 | ├────────┼──────────────────────────────────────────┤ | |
262 | │ data │ OVH_AK=XXXXXXXXXXXXXXXX │ | |
263 | │ │ OVH_AS=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY │ | |
264 | │ │ OVH_CK=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ │ | |
265 | ├────────┼──────────────────────────────────────────┤ | |
266 | │ digest │ 867fcf556363ca1bea866863093fcab83edf47a1 │ | |
267 | ├────────┼──────────────────────────────────────────┤ | |
268 | │ plugin │ example_plugin │ | |
269 | ├────────┼──────────────────────────────────────────┤ | |
270 | │ type │ dns │ | |
271 | └────────┴──────────────────────────────────────────┘ | |
186c094b TL |
272 | ---- |
273 | ||
274 | At last you can configure the domain you want to get certitficates for and | |
275 | place the certificate order for it: | |
276 | ||
277 | ---- | |
0b447f1c FG |
278 | root@proxmox:~# pvenode config set -acmedomain0 example.proxmox.com,plugin=example_plugin |
279 | root@proxmox:~# pvenode acme cert order | |
280 | Loading ACME account details | |
281 | Placing ACME order | |
282 | Order URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/11111111/22222222 | |
283 | ||
284 | Getting authorization details from 'https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/33333333' | |
285 | The validation for example.proxmox.com is pending! | |
286 | [Wed Apr 22 09:25:30 CEST 2020] Using OVH endpoint: ovh-eu | |
287 | [Wed Apr 22 09:25:30 CEST 2020] Checking authentication | |
288 | [Wed Apr 22 09:25:30 CEST 2020] Consumer key is ok. | |
289 | [Wed Apr 22 09:25:31 CEST 2020] Adding record | |
290 | [Wed Apr 22 09:25:32 CEST 2020] Added, sleep 10 seconds. | |
291 | Add TXT record: _acme-challenge.example.proxmox.com | |
292 | Triggering validation | |
293 | Sleeping for 5 seconds | |
294 | Status is 'valid'! | |
295 | [Wed Apr 22 09:25:48 CEST 2020] Using OVH endpoint: ovh-eu | |
296 | [Wed Apr 22 09:25:48 CEST 2020] Checking authentication | |
297 | [Wed Apr 22 09:25:48 CEST 2020] Consumer key is ok. | |
298 | Remove TXT record: _acme-challenge.example.proxmox.com | |
299 | ||
300 | All domains validated! | |
301 | ||
302 | Creating CSR | |
303 | Checking order status | |
304 | Order is ready, finalizing order | |
305 | valid! | |
306 | ||
307 | Downloading certificate | |
308 | Setting pveproxy certificate and key | |
309 | Restarting pveproxy | |
310 | Task OK | |
311 | ---- |