Project LetsEncrypt: Difference between revisions

From JoBaPedia
Jump to navigation Jump to search
(Created page with "= LetsEncrypt Today I replaced my self signed certs with official ones from Lets Encrypt: == Request First Cert ssh root@job4 cd /usr/local/bin sudo wget https://dl.eff....")
 
 
(22 intermediate revisions by the same user not shown)
Line 1: Line 1:
= LetsEncrypt
= Let's Encrypt =


Today I replaced my self signed certs with official ones from Lets Encrypt:
I replaced my self signed certs of my dyndns domain with official ones from [[https://letsencrypt.org/ Let’s Encrypt]]:


== Request First Cert
== 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
  ssh root@job4
Line 10: Line 54:
  sudo certbot-auto --apache
  sudo certbot-auto --apache


== Apache Config Preparation
== Apache Config Preparation ==


At first, this did not work. The script needs a vhost for port 80, so I created one:
At first, this did not work. The script needs a vhost for port 80, so I created one:
Line 34: Line 78:
* systemctl restart apache2
* systemctl restart apache2


== Automation
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.
The cert is only valid for 90 days. Better automate the renewal.
Line 44: Line 97:
  python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew
  python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew


== Fritz Box Cert
No idea why python came into the game. This should work as well...


To use the cert with the fritz box web interface,
#!/bin/bash
sleep $((RANDOM/9)) && /usr/local/bin/certbot-auto renew
 
== Fritz Box Cert ==
 
=== Automatic Update ===
 
[https://gist.github.com/joba-1/365b30c6378f2d1f38687fb87ed1f7c9 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
  ssh root@job4 'cat /etc/letsencrypt/live/banzhaf.chickenkiller.com/[pf]*.pem' >fritz.pem
Line 52: Line 119:
Then upload this file in the fritz box cert store with the web interface (Internet/Freigaben/Fritzbox Dienste/)
Then upload this file in the fritz box cert store with the web interface (Internet/Freigaben/Fritzbox Dienste/)


Planned: use this script to automate: https://gist.github.com/joba-1/6b2fe7294ebda3f6a5d058c6fd9ea44a
== 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

Latest revision as of 13:50, 12 September 2024

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