home.arpa : Renouvellement automatique des certificats
Le plus simple est de tout centraliser sur la machine qui détient la clé de la CA (votre poste Arch, par exemple). Un timer systemd y lance un script qui réémet le certificat si nécessaire, puis le pousse en SSH vers chaque serveur et recharge le service concerné. Les serveurs n’ont donc besoin ni de timer ni de la clé de la CA, ce qui règle aussi le cas d’Alpine, qui n’a pas systemd.
- Cibles : le script lit votre CSV et retient les lignes dont
Optcontientcert. - Utilisateur : le script tourne en timer utilisateur (
systemctl --user), car vos clés SSH sont dans votre~/.ssh. Un timer système en root ne les verrait pas. La clé de la CA doit donc être lisible par votre utilisateur. - Droits distants : les serveurs ont un petit script root, appelable via
sudosans mot de passe, qui installe le certificat puis lance des hooks propres à chaque machine (nginx, Proxmox, etc.).
Script sur chaque serveur cible
1 - Script /usr/local/sbin/homearpa-cert-install
Créer le script /usr/local/sbin/homearpa-cert-install (root:root, chmod 755) sur chaque serveur cible
1
2
3
4
5
6
7
8
9
10
#!/bin/sh
set -eu
DIR=/etc/ssl/homearpa
mkdir -p "$DIR"
case "${1:-}" in
key) umask 077; cat > "$DIR/homearpa.key.new" && mv "$DIR/homearpa.key.new" "$DIR/homearpa.key" ;;
cert) umask 022; cat > "$DIR/homearpa.crt.new" && mv "$DIR/homearpa.crt.new" "$DIR/homearpa.crt" ;;
reload) for h in /etc/homearpa-cert/reload.d/*; do [ -x "$h" ] && "$h"; done; exit 0 ;;
*) echo "usage: $0 key|cert|reload" >&2; exit 1 ;;
esac
2 - Autoriser exécution script dans sudoers
Il utilise sh pur, donc il fonctionne aussi sur Alpine. Autorisez-le dans sudoers sans mot de passe avec le nom d’utilisateur de la machine :
1
sudo visudo -f /etc/sudoers.d/homearpa-cert
cwwk
1
yick ALL=(root) NOPASSWD: /usr/local/sbin/homearpa-cert-install
3 - Hook exécutable par le script
Ensuite, déposez dans /etc/homearpa-cert/reload.d/
1
2
# si dossier inexistant
sudo mkdir -p /etc/homearpa-cert/reload.d/
un hook exécutable par service :
cwwk /etc/homearpa-cert/reload.d/10-nginx
1
2
3
# 10-nginx (Debian/Arch)
#!/bin/sh
systemctl reload nginx
proxmox /etc/homearpa-cert/reload.d/10-pve
1
2
3
# 10-pve (Proxmox : méthode officielle)
#!/bin/sh
pvenode cert set /etc/ssl/homearpa/homearpa.crt /etc/ssl/homearpa/homearpa.key --force 1 --restart 1
Alpine /etc/homearpa-cert/reload.d/10-alpine
1
2
3
# 10-nginx (Alpine)
#!/bin/sh
rc-service nginx reload
Si le service qui lit la clé ne tourne pas en root, ajustez le groupe ou les droits dans le hook.
Poste PC1 EndeavourOS
Script renouvellement certificats home.arpa
Les informations homearpaCA.crt + homearpaCA.key sont dans un coffre
Solution recommandée : un fichier dans le coffre Cryptomator La passphrase est stockée à côté de la clé de la CA, donc chiffrée au repos par le coffre, qui est inaccessible tant qu’il est verrouillé.
1
2
3
4
5
6
7
8
CA_DIR="$HOME/.local/share/Cryptomator/mnt/yann-crypto/home.arpa"
# Création du fichier sans laisser la passphrase dans l'historique
read -rsp "Passphrase de la CA : " p; echo
( umask 077; printf '%s\n' "$p" > "$CA_DIR/ca.pass" ); unset p
# Test : la clé se lit sans interaction ?
openssl pkey -in "$CA_DIR/homearpaCA.key" -passin file:"$CA_DIR/ca.pass" -noout && echo "OK"
Créer le script ~/.local/bin/homearpa-cert-renew (chmod 700) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env bash
set -euo pipefail
CSV="${CSV:-$HOME/.ssh/.ssh_servers}" # À ADAPTER : votre fichier CSV
KEYDIR="$HOME/.ssh" # dossier des clés (champ SSH_Key)
# Les informations homearpaCA.crt + homearpaCA.key sont dans un coffre verrouillé en fermeture de session
CA_DIR="$HOME/.local/share/Cryptomator/mnt/yann-crypto/home.arpa/" # homearpaCA.crt + homearpaCA.key (chmod 600)
OUT="$HOME/.local/share/homearpa-certs"
NAME=homelab
DOMAIN=home.arpa
DAYS=90
RENEW_BEFORE=$((30*86400))
HELPER=/usr/local/sbin/homearpa-cert-install
# Lecture passphrase
CA_PASS="$CA_DIR/ca.pass"
for f in homearpaCA.crt homearpaCA.key ca.pass; do
[[ -r "$CA_DIR/$f" ]] || { echo "Introuvable : $CA_DIR/$f (coffre Cryptomator verrouillé ?)" >&2; exit 1; }
done
# SAN_EXTRA="${SAN_EXTRA:-}" # ex. "DNS:alias.home.arpa,DNS:autre.home.arpa"
SAN_EXTRA="DNS:*.home.arpa, DNS:home.arpa, DNS:cwwk.home.arpa, DNS:dns.home.arpa, DNS:ged.home.arpa, DNS:link.home.arpa, DNS:lldap.home.arpa, DNS:portainer.home.arpa, DNS:pve.home.arpa, DNS:site.home.arpa, DNS:terminal.home.arpa"
mkdir -p "$OUT"; cd "$OUT"; umask 077
# Cibles : Opt (champ 9) contient "cert" → alias|user|host|port|key|ipver
mapfile -t TARGETS < <(awk -F';' 'NR>1 && $1!="" {
n=split($9,o,","); for(i=1;i<=n;i++) if(o[i]=="cert") print $1"|"$2"|"$3"|"$4"|"$5"|"$10 }' "$CSV")
[[ ${#TARGETS[@]} -gt 0 ]] || { echo "Aucune ligne avec l'option cert" >&2; exit 1; }
# SAN : alias.home.arpa (ou l'hôte s'il finit déjà par .home.arpa) + IP si le champ est une IPv4
sans=()
for t in "${TARGETS[@]}"; do
IFS='|' read -r alias user host port key ver <<<"$t"
if [[ "$host" == *.$DOMAIN ]]; then sans+=("DNS:$host"); else sans+=("DNS:$alias.$DOMAIN"); fi
if [[ "$host" =~ ^[0-9]+(\.[0-9]+){3}$ ]]; then sans+=("IP:$host"); fi
done
SAN=$(IFS=,; echo "${sans[*]}")
[[ -n "$SAN_EXTRA" ]] && SAN="$SAN,$SAN_EXTRA"
norm() { sed 's/IP Address:/IP:/g' | tr -d ' ' | tr ',' '\n' | sort | tr '\n' ','; }
WANT=$(echo "$SAN" | norm)
CUR=$(openssl x509 -in $NAME.crt -noout -ext subjectAltName 2>/dev/null | tail -n1 | norm || true)
# 1. Réémission si les noms ont changé ou s'il reste moins de 30 jours
if [[ "$CUR" != "$WANT" ]] || ! openssl x509 -in $NAME.crt -noout -checkend $RENEW_BEFORE >/dev/null 2>&1; then
echo "Réémission ($DAYS jours) : $SAN"
cat > $NAME.ext <<EOF
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = $SAN
EOF
openssl req -new -newkey rsa:2048 -nodes -keyout $NAME.key -out $NAME.csr \
-subj "/C=FR/ST=Pays-de-la-Loire/L=Beaupreau/O=HomeLab/CN=$DOMAIN"
openssl x509 -req -in $NAME.csr -CA "$CA_DIR/homearpaCA.crt" -CAkey "$CA_DIR/homearpaCA.key" \
-passin file:"$CA_PASS" -CAcreateserial -days $DAYS -sha256 -extfile $NAME.ext -out $NAME.crt
openssl verify -CAfile "$CA_DIR/homearpaCA.crt" $NAME.crt
fi
# 2. Déploiement idempotent (n'agit que sur les serveurs pas à jour)
rc=0
for t in "${TARGETS[@]}"; do
IFS='|' read -r alias user host port key ver <<<"$t"
opts=(-i "$KEYDIR/$key" -p "$port" -o IdentitiesOnly=yes -o BatchMode=yes -o ConnectTimeout=10)
if [[ "$ver" == 4 || "$ver" == 6 ]]; then opts+=("-$ver"); fi
S=(ssh "${opts[@]}" "$user@$host")
if "${S[@]}" "cat /etc/ssl/homearpa/homearpa.crt" 2>/dev/null | cmp -s - $NAME.crt; then continue; fi
echo "Déploiement sur $alias"
if "${S[@]}" "sudo -n $HELPER key" < $NAME.key \
&& "${S[@]}" "sudo -n $HELPER cert" < $NAME.crt \
&& "${S[@]}" "sudo -n $HELPER reload"; then echo " OK"; else echo " ÉCHEC sur $alias" >&2; rc=1; fi
done
exit $rc
Ce script suppose deux choses à vérifier :
- Nom DNS : l’alias correspond au nom Technitium (
cwwkdonnecwwk.home.arpa, ce que vous avez validé). Siproxtinouproxmoxont un autre nom en DNS, utilisezSAN_EXTRAou renommez l’enregistrement. - Clés SSH : le champ
SSH_Keydésigne un fichier dans~/.ssh. Si votre scriptsshmles cherche ailleurs, changezKEYDIR.
La ligne proxy (rnmkcy.eu, sans option cert) est ignorée, ce qui est normal : un nom public ne relève pas de votre CA locale.
Automatiser le renouvellement (systemd timer utilisateur)
Créer le service utilisateur~/.config/systemd/user/homearpa-cert.service :
1
2
3
4
5
6
[Unit]
Description=Renouvellement et déploiement du certificat home.arpa
[Service]
Type=oneshot
ExecStart=%h/.local/bin/homearpa-cert-renew
Créer le timer utilisateur ~/.config/systemd/user/homearpa-cert.timer :
1
2
3
4
5
6
7
8
9
10
[Unit]
Description=Vérification hebdomadaire du certificat home.arpa
[Timer]
OnCalendar=weekly
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
Rechargement, activation, exécution et vérification
1
2
3
4
systemctl --user daemon-reload
systemctl --user enable --now homearpa-cert.timer
systemctl --user start homearpa-cert.service # premier passage manuel
journalctl --user -u homearpa-cert.service -e
Le journal
1
2
oct. 22 15:08:35 pc1 systemd[819]: Starting Renouvellement et déploiement du certificat home.arpa...
oct. 22 15:08:36 pc1 systemd[819]: Finished Renouvellement et déploiement du certificat home.arpa.
Persistent=true rattrape un passage manqué si le poste était éteint.
Ordre de mise en route
- Installer le script root, la règle sudoers et les hooks sur les serveurs marqués
cert(e6230l n’en a pas besoin pour l’instant). - Copier la CA dans
$CA_DIR(chmod 600sur la clé). - Lancer le service à la main et lire le journal.
- Recharger
https://cwwk.home.arpadans Brave.
La clé de la CA est stockée sans passphrase pour permettre l’automatisation. Gardez donc des droits stricts sur ce dossier et ne le synchronisez pas.
Conclusions
En résumé :
homearpaCA.crt: la racine, à installer dans les magasins de confiance. C’est déjà fait, vous n’y touchez plus.homearpaCA.key: la clé de la CA, qui reste dans le coffre Cryptomator.homelab.crtethomelab.key: le certificat serveur renouvelé tous les 90 jours et déployé par le script sur les machines marquéescert.
Parfait, Brave accepte maintenant le domaine, ce qui confirme que le certificat avec noms explicites est bien déployé.
Le journal ne contient que « Starting » et « Finished », sans aucune ligne « Réémission » ni « Déploiement ». Ce passage n’a donc rien eu à faire : le certificat était déjà à jour (mêmes noms, plus de 30 jours de validité) et chaque serveur avait déjà la bonne version. C’est le comportement attendu d’un script idempotent, probablement parce que vous aviez déjà fait un premier passage à la main. Une confirmation rapide :
1
2
3
4
5
# Validité et noms du certificat courant
openssl x509 -in ~/.local/share/homearpa-certs/homelab.crt -noout -dates -ext subjectAltName
# Prochain passage du timer
systemctl --user list-timers homearpa-cert.timer
Vous devriez voir environ 90 jours de validité et un DNS: pour chaque machine marquée cert. Pour contrôler un serveur précis, openssl s_client -connect cwwk.home.arpa:443 -servername cwwk.home.arpa </dev/null 2>/dev/null | openssl x509 -noout -dates doit afficher les mêmes dates.
Le renouvellement se déclenchera tout seul quand il restera moins de 30 jours, soit autour de fin décembre. Un test utile avant cette date : ajouter l’option cert à une nouvelle ligne du CSV, relancer le service avec systemctl --user start homearpa-cert.service, et vérifier que le journal affiche « Réémission » puis « Déploiement sur … ».
