HTTPS Certificate Configuration (Version 4.x, 5.0 and 5.1)
Introduction
This is a howto for changing the web server certificate used by Proxmox VE, in order to enable the usage of publicly trusted certificates issued by a CA of your choice (like Let's Encrypt or a commercial CA). It has been tested on a Proxmox VE 4.1 installation, using certificates from https://www.letsencrypt.org.
Note: the previous, outdated version of this HowTo is archived at HTTPSCertificateConfigurationOld
Revert to default configuration
If you have used the previous HowTo and replaced any of the certificate or key files generated by PVE, you need to revert to the default state before proceeding.
Delete or move the following files:
- /etc/pve/pve-root-ca.pem
- /etc/pve/priv/pve-root-ca.key
- /etc/pve/nodes/<node>/pve-ssl.pem
- /etc/pve/nodes/<node>/pve-ssl.key
The latter two need to be repeated for all nodes if you have a cluster.
Afterwards, run the following command on each node of the cluster to re-generate the certificates and keys:
pvecm updatecerts -f
CAs other than Let's Encrypt
Install certificate chain and key
Since pve-manager 4.1-20, it is possible to provide alternative SSL files for each node's web interface. The following steps need to be repeated for each node where you want to use alternative certificate files.
First check your version of pve-manager and upgrade if necessary:
pveversion
You will need the following two files provided by your CA:
- fullchain.pem (your certificate and all intermediate certificates, excluding the root certificate, in PEM format)
- private-key.pem (your private key, in PEM format, without a password)
Now copy those files to the override locations in /etc/pve/nodes/<node> (make sure to use the correct certificate files and node!):
cp fullchain.pem /etc/pve/nodes/<node>/pveproxy-ssl.pem cp private-key.pem /etc/pve/nodes/<node>/pveproxy-ssl.key
and restart the web interface:
systemctl restart pveproxy
The system log should inform you about the usage of the alternative SSL certificate ("Using '/etc/pve/local/pveproxy-ssl.pem' as certificate for the web interface."):
journalctl -b -u pveproxy.service
When accessing the web interface on this node, you should be presented with the new certificate. Note that the alternative certificate is only used by the web interface (including noVNC), but not by the Spice Console/Shell.
Let's Encrypt using le.sh
Prerequisites
Let's Encrypt enables everyone with a publicly resolvable domain name to be issued SSL certificates for free.
Your domain name needs to be publicly resolvable both ways. (Check with `$ drill -x Your.Ip.Address` or `$ dig -x Your.Ip.Address`)
The following steps show how to achieve this using the le.sh bash script and standalone HTTP authentication.
These steps need to be repeated on each node where you want to use Let's Encrypt certificates.
You need at least pve-manager >= 4.1-20 (see `$ pveversion`), so upgrade if necesasry.
Install certificate chain and key
1) Install le.sh
Install the le.sh script from https://github.com/Neilpang/le (this howto was tested with commit 9e6c420872e6e843a6a86ee31f2472574eeda3f6):
Via git:
git clone https://github.com/Neilpang/le.git le-master
Or direct download:
wget 'https://github.com/Neilpang/le/archive/master.zip' unzip master.zip
2) Run the install script
You must do this from within the script's directory, othrewise it won't find le.sh!
mkdir /etc/pve/.le cd /root/le-master ACCOUNT_CONF_PATH=/etc/pve/.le/account.conf ACCOUNT_KEY_PATH=/etc/pve/.le/account.key /root/le-master/le.sh install
3) Edit the account config
Edit the config file in /etc/pve/.le/account.conf and set:
- the ACCOUNT_EMAIL variable
- the ACCOUNT_KEY_PATH to "/etc/pve/.le/account.key"
4) Make sure port 80 is open to the public
As part of the certificate creation process, le.sh will listen for a confirmation from LetsEncrypt's servers on port 80. Check that this port is therefore not blocked by any firewall to the machine you are certifying.
You can close the port once you're done issuing all certificates for your cluster. However, be aware that as part of the certificate renewal process (managed with a cron job that le.sh installs), port 80 must also be open. You may therefore need to work out an automated way (not covered in this guide) of opening up port 80 for the renewal process.
5) Issue your first certificate
Now you can issue your first certificate, replacing $DOMAIN with your node's fully qualified domain:
ACCOUNT_CONF_PATH=/etc/pve/.le/account.conf /root/.le/le.sh issue no $DOMAIN no 4096 /etc/pve/local/pveproxy-ssl.pem /etc/pve/local/pveproxy-ssl.key /etc/pve/local/pveproxy-ssl.pem "systemctl restart pveproxy"
Warnings like "cp: preserving permissions for ‘/etc/pve/local/pveproxy-ssl.pem.bak’: Function not implemented" can be safely ignored.
By prepending the previous command with STAGE=1 you can issue a certificate using the staging (i.e., testing) CA instead of the production CA:
STAGE=1 ACCOUNT_CONF_PATH=/etc/pve/.le/account.conf /root/.le/le.sh issue no $DOMAIN no 4096 /etc/pve/local/pveproxy-ssl.pem /etc/pve/local/pveproxy-ssl.key /etc/pve/local/pveproxy-ssl.pem "systemctl restart pveproxy"
To "upgrade" to a production certificate, you need to rerun the issue command with a prepended FORCE=1 instead of STAGE=1, in order to replace the existing (test) certificate even though it is not yet expired. This can also be used in case the node's domain name has changed:
FORCE=1 ACCOUNT_CONF_PATH=/etc/pve/.le/account.conf /root/.le/le.sh issue no $DOMAIN no 4096 /etc/pve/local/pveproxy-ssl.pem /etc/pve/local/pveproxy-ssl.key /etc/pve/local/pveproxy-ssl.pem "systemctl restart pveproxy"
Finally
If necessary, close the firewall port again.
The system log should inform you about the usage of the alternative SSL certificate ("Using '/etc/pve/local/pveproxy-ssl.pem' as certificate for the web interface."):
journalctl -b -u pveproxy.service
When accessing the web interface on this node, you should be presented with the new certificate. Note that the alternative certificate is only used by the web interface (including noVNC), but not by the Spice Console/Shell.
le.sh installs a cron job that checks the installed certificate(s) and automatically renews them before they expire. The requirements for issuing certificates apply for renewals as well: the configured domain name must be resolvable and reachable on port 80 from the public internet. The cron job needs to be adapted to use the account.conf file stored on the cluster file systems. Simply replace
LE_WORKING_DIR="/root/.le"
with
ACCOUNT_CONF_PATH="/etc/pve/.le/account.conf" LE_WORKING_DIR="/root/.le"
using "crontab -e", followed by "crontab -l" to verify that the changes were saved correctly.
Updating le.sh
le.sh can be updated with the following commands:
cd /root/le-master git pull ACCOUNT_CONF_PATH=/etc/pve/.le/account.conf ACCOUNT_KEY_PATH=/etc/pve/.le/account.key /root/le/le.sh install
Account key
It is recommended to do an off-site/offline backup of the account key file in /etc/pve/.le/account.key, in case one of your certificate private key files is lost or compromised, it can be used to revoke the associated certificate.
Let's Encrypt using other clients
It should also be possible to use other Let's Encrypt clients, as long as care is taken that the issued as well as renewed certificates and the associated keys are copied to the correct locations, and the pveproxy service is restarted afterwards.