Project LetsEncrypt
Let's Encrypt
I replaced my self signed certs of my dyndns domain with official ones from [Let’s Encrypt]:
Current Process
Install
sudo zypper in certbot-systemd-timer sudo systemctl enable certbot-renew.timer sudo systemctl start certbot-renew.timer
also install renewal scripts for fritzbox, openwrt, qnap, grafana (see post hooks below, but except apache and fritzbox, direct external access is not usually enabled/used)
maybe also needed: python311-certbot-apache
Configuration
/etc/letsencrypt/renewal-hooks/post:
lrwxrwxrwx 1 root root 38 Oct 15 2018 fritzbox-cert-update.sh -> /usr/local/bin/fritzbox-cert-update.sh lrwxrwxrwx 1 root root 37 Jul 7 2021 openwrt-cert-update.sh -> /usr/local/bin/openwrt-cert-update.sh -rwxr-xr-x 1 root root 1306 Mar 23 2022 mosquitto-copy.sh -rwxr-xr-x 1 root root 53 Aug 7 2022 grafana-restart.sh lrwxrwxrwx 1 root root 34 Oct 15 2022 qnap-cert-update.sh -> /usr/local/bin/qnap-cert-update.sh
- qnap needs /etc/letsencrypt/id_rsa.letsencrypt.pub in qnap:~admin/.ssh/authorized_keys
Check
note: starting the service (directly or via timer) uses a random delay of several minutes
Date of cert files
/etc/letsencrypt/live/banzhaf.chickenkiller.com:
-rw-r--r-- 1 root root 682 Aug 4 2018 README lrwxrwxrwx 1 root root 53 Aug 12 11:13 privkey.pem -> ../../archive/banzhaf.chickenkiller.com/privkey30.pem lrwxrwxrwx 1 root root 55 Aug 12 11:13 fullchain.pem -> ../../archive/banzhaf.chickenkiller.com/fullchain30.pem lrwxrwxrwx 1 root root 51 Aug 12 11:13 chain.pem -> ../../archive/banzhaf.chickenkiller.com/chain30.pem lrwxrwxrwx 1 root root 50 Aug 12 11:13 cert.pem -> ../../archive/banzhaf.chickenkiller.com/cert30.pem
Systemd status
systemctl status certbot-renew.timer
Journal
journalctl -u certbot-renew.service journalctl -f -u certbot-renew.service
Request First Cert
ssh root@job4 cd /usr/local/bin sudo wget https://dl.eff.org/certbot-auto sudo certbot-auto --apache
Apache Config Preparation
At first, this did not work. The script needs a vhost for port 80, so I created one:
/etc/apache2/vhosts.d/vhost-chickenkiller.conf:
<VirtualHost *:80> ServerAdmin joachim.banzhaf@gmail.com ServerName banzhaf.chickenkiller.com ServerAlias banzhaf.chickenkiller.com DocumentRoot /srv/www/htdocs ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined </VirtualHost>
Then it complained about syntax errors in my apache config that I needed to fix (quotes not closed). Finally the validation failed due to access errors. I had to remove all old style access control and use the new apache 2.4 style, which was more straightforward than I expected:
- remove all "Order deny/allow" stuff that was not ifdefd
- replace all "Allow/Deny from all" by "Require all granted/denied" if not ifdefd
- replace all "Allow from ip/hostname/net" by "Require host ip/hostname/net"
- remove module access_compat from /etc/sysconfig/apache2 variable APACHE_MODULES
- systemctl restart apache2
The script offered to configure forwarding http to https, which I accepted. I think it just added these lines to the virtual host file above:
RewriteEngine on RewriteCond %{SERVER_NAME} =banzhaf.chickenkiller.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
Now the cert was used and validated as safe (although chromium needed some time to accept it)
Automation
The cert is only valid for 90 days. Better automate the renewal. It is enough to create this script
/etc/cron.daily/certbot-auto-renew
#!/bin/sh python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew
No idea why python came into the game. This should work as well...
#!/bin/bash sleep $((RANDOM/9)) && /usr/local/bin/certbot-auto renew
Fritz Box Cert
Automatic Update
This script logs into the fritzbox and updates the cert for you. Just edit the variables at the start (user, pass, certpath). I use a separate fritzbox user for this.
To make it even more easy: Store this script in /etc/letsencrypt/renewal-hooks/post and it gets run on updates (I'll see if that works in 2 months)
Manual Update
To use the cert with the fritz box web interface
ssh root@job4 'cat /etc/letsencrypt/live/banzhaf.chickenkiller.com/[pf]*.pem' >fritz.pem
Then upload this file in the fritz box cert store with the web interface (Internet/Freigaben/Fritzbox Dienste/)
OpenWRT
Manual Setup
copy cert (cat crt+key in one pem) to /etc/letsencrypt by post hook script
add host to HOSTS in job4:/etc/letsencrypt/renewal-hooks/post/openwrt-cert-update.sh
nginx
uci set nginx._lan.ssl_certificate=/etc/letsencrypt/banzhaf.chickenkiller.com.pem uci set nginx._lan.ssl_certificate_key=/etc/letsencrypt/banzhaf.chickenkiller.com.pem uci set nginx._lan.uci_manage_ssl='my_letsencrypt'
uhttp (default)
uci set uhttpd.main.key='/etc/letsencrypt/banzhaf.chickenkiller.com.pem' uci set uhttpd.main.cert='/etc/letsencrypt/banzhaf.chickenkiller.com.pem'
Automatic Renewal
put this in /etc/letsencrypt/renewal-hooks/post (create the id_rsa.letsencrypt ssh key and deploy it to openwrt router /etc/letsencrypt/)
#!/bin/bash # parameters CERT_SRC="/etc/letsencrypt/live/banzhaf.chickenkiller.com" CERT_DST="/etc/letsencrypt" CERT_FILE="banzhaf.chickenkiller.com.pem" SSH_ID="/etc/letsencrypt/id_rsa.letsencrypt" HOSTS="ax1 ax2" cd "$CERT_SRC" for h in $HOSTS; do cat fullchain.pem privkey.pem | ssh -i "$SSH_ID" root@$h "mkdir -p '$CERT_DST' && cat >'$CERT_DST/$CERT_FILE' && /etc/init.d/uhttpd restart" done
Grafana
put this into /etc/grafana/grafana.ini
# https certs & key file cert_file = /etc/letsencrypt/live/banzhaf.chickenkiller.com/fullchain.pem cert_key = /etc/letsencrypt/live/banzhaf.chickenkiller.com/privkey.pem
then it just needs a restart on cert renewal by putting this to /etc/letsencrypt/renewal-hooks/post
#!/bin/bash systemctl restart grafana-server.service
Mosquitto Broker
put this script in /etc/letsencrypt/renewal-hooks/post
MY_DOMAIN=banzhaf.chickenkiller.com CERTIFICATE_DIR=/etc/mosquitto/certs if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then # Copy new certificate to Mosquitto directory cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key # Set ownership to Mosquitto chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key # Ensure permissions are restrictive chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key # Tell Mosquitto to reload certificates and configuration pkill -HUP -x mosquitto fi