Weechat Relay mit Let's Encrypt

von am
3 Minute(n) gelesen

Seit einiger Zeit bin ich auf Let's Encrypt umgestiegen für die vollautomatisierte Generierung aller meiner Zertifikate. Das ist sehr angenehm. Ich starte alles monatlich über systemd-Timer und systemd-Services. Dabei gab es aber ein Problem: manche Services brauchen die neuen Zertifikate und können mit den alten nichts mehr anfangen, so z.B. nginx, den man aber leicht neustarten kann mit einem systemctl reload. Komplexere Aktionen sind aber schwierig.

Das Zauberwort heißt --renew-hook "action". Das wird direkt von certbot Programm zur Verfügung gestellt und damit lässt sich hervorragend alles realisieren, was man benötigt.

Als Beispiel für den ganzen Prozess möchte ich hier einmal den Fluss nach der Erstellung des Zertifikates für mein XMPP/Jabber/Weechat Relay vorstellen, welches ich über Glowing Bear nutze, um überall auf IRC und Jabber zuzugreifen ohne mehrere Sessions zu öffnen. Denkbar ist das natürlich auch für Postfix und Dovecot, eben alles: --renew-hook "systemctl restart postfix dovecot".

Beginnen wir mit dem systemd-Service, der für das Starten von /usr/bin/weechat zuständig ist. Dies ist nur zu Vollständigkeit, es ist irrelevant, wie der Client für das Relay neugestartet wird. Zu sehen ist das auch später im eigentlichen Script. Ich benutze screen für meinen Weechat.

[Unit]
Description=weechat-screen-myuser

[Service]
Type=forking
User=myuser
ExecStart=/usr/bin/screen -d -m -S weechat /usr/bin/weechat
ExecStop=/usr/bin/screen -S weechat -X quit
WorkingDirectory=/home/myuser

[Install]
WantedBy=multi-user.target

Was soll nun aber passieren, wenn Let's Encrypt ein neues Zertifikat für das im Weechat verwendete Relay generiert hat? Genau:

  • Zusammenfügen von privkey und fullchain für die spezifizierte Domain,
  • chown, da certbot als root in einem systemd-Service ausgeführt wird und
  • Neustart von Weechat.

Dies erledigt folgendes Script, dass beliebig abgelegt werden kann, z.B. in /home/myuser/.weechat/ssl/weechat-certbot-renew-relay.sh.

#!/bin/bash
# Execute this with
#
# --renew-hook "sh path/to/script/weechat-certbot-renew-relay.sh" in certbot for $DOMAIN
#
# This script renews the relay weechat certificate if Let's Encrypt renewed it.
# It also restarts your weechat session if you provided a correct $RESTART_COMMAND.
#
# This is executed as root (which is required for certbot)

DOMAIN="example.com";
USER="myuser";
GROUP="myuser";
WEECHAT_DIR="/home/myuser/.weechat/ssl/";
WEECHAT_RELAY_CERTNAME="relay.pem";
RESTART_COMMAND="systemctl restart weechat-screen-myuser.service";

echo "Executing renew hook for weechat.";
echo "This hook uses $DOMAIN for relay configuration.";

cd $WEECHAT_DIR;
echo "Changed directory to $(pwd)";

cat /etc/letsencrypt/live/$DOMAIN/privkey.pem /etc/letsencrypt/live/$DOMAIN/fullchain.pem > $WEECHAT_RELAY_CERTNAME;
echo "Concated privkey and fullchain to $WEECHAT_RELAY_CERTNAME into $(pwd)";

chown $USER:$GROUP $WEECHAT_RELAY_CERTNAME;
echo "Chowned $WEECHAT_RELAY_CERTNAME for $USER:$GROUP";

echo "Restarting weechat with $RESTART_COMMAND";
$($RESTART_COMMAND)

Danach muss es nur noch mit --renew-hook im Let's Encrypt Service referenziert werden.

# /etc/systemd/system/letsencrypt-renew@example.com.service.d/override.conf
[Unit]
Description=renew certificates for %I

[Service]
Type=oneshot
ExecStartPre=/usr/bin/mkdir -p /tmp/letsencrypt-auto
ExecStart=/usr/bin/certbot certonly \
  --webroot \
  --webroot-path=/tmp/letsencrypt-auto \
  --renew-by-default \
  --renew-hook "sh /home/myuser/.weechat/ssl/weechat-certbot-renew-relay.sh" \
  --keep \
  --agree-tos \
  --email admin@example.com \
  -d %I
ExecStartPost=/usr/bin/nginx -s reload

[Install]
WantedBy=multi-user.target

Fertig. Das funktioniert hervorragend und ich muss nun keine Aktion auf dem Server mehr manuell ausführen durch den renew hook. Cloud, Jabber, Weechat (Relay) und alle sonstigen Services, die auf ein gültiges Zertifikat angewiesen sind, starten sich automatisch neu oder führen erforderliche Schritte nach einer Neugenerierung durch certbot aus.

comments powered by Disqus