---
# System prepended metadata

title: Certificate Renewal on PVE with wildcards
tags: [server]

---

---
tags: server
---

# Certificate Renewal on PVE with wildcards

Make sure PVE does _not_ renew certificates on its own.
All ACME plugins should be disabled.

Install certbot:

```
apt install python3-certbot-dns-cloudflare
```

Create `/etc/cloudflare.ini` and set the Cloudflare API token:

```ini
# Cloudflare API token used by Certbot
dns_cloudflare_api_token = ...
```

Make this file readable for `root` only:

```
chmod 0600 /etc/cloudflare.ini
```

Create a service file `certbot-renew.service` to automate the update.
Unfortunately, the PVE FUSE configuration file system does not allow symlinks.
That is why we need to copy the certificate.


```ini
[Unit]
Description=Certbot Renew

[Service]
Type=simple
ExecStart=/usr/bin/certbot certonly -n --agree-tos -m kiesow@elan-ev.de --dns-cloudflare --dns-cloudflare-credentials /etc/cloudflare.ini -d vm-test.elan.codes -d *.vm-test.elan.codes
ExecStopPost=/usr/bin/cp /etc/letsencrypt/live/vm-test.elan.codes/privkey.pem /etc/pve/local/pveproxy-ssl.key
ExecStopPost=/usr/bin/cp /etc/letsencrypt/live/vm-test.elan.codes/fullchain.pem /etc/pve/local/pveproxy-ssl.pem
ExecStopPost=-/bin/systemctl reload nginx.service
ExecStopPost=-/bin/systemctl reload pveproxy.service
```

Deploy this to `/etc/systemd/system/certbot-renew.service` and check if it works:

```
systemctl start certbot-renew.service
systemctl status certbot-renew.service
```

Create a timer to automatically trigger this service:

```ini
[Unit]
Description=Certbot Renew Scheduling.

[Timer]
OnCalendar=*-*-* 01:30:00

[Install]
WantedBy=multi-user.target
```

Deploy this to `/etc/systemd/system/certbot-renew.timer` and enable the timer:

```
systemctl start certbot-renew.timer
systemctl enable certbot-renew.timer
systemctl list-timers
```
