Compare commits

..

View file

@ -73,10 +73,13 @@ in
when it is missing or near expiry; because it shares the CA
anchor, a rotation does not disturb consumer trust. Agents and
federation peers validate against the CA, not browser CA/B-forum
limits. The weekly `hive-tls-resign` timer re-signs the leaf once
it is within half its validity of expiry and propagates the new
leaf into the running gateway, so a long-uptime host renews
automatically without a reboot.
limits. NOTE: at this short a window the re-sign must run more
often than the leaf lifetime. Today `hive-tls-ca` re-signs at
service activation (boot/rebuild) only there is no periodic
re-sign timer yet so a hive that does not reboot within the
validity window would let the leaf expire. Keep that in mind (or
add a re-sign timer) when running a hive that stays up for long
stretches without a rebuild.
'';
};
};
@ -162,109 +165,6 @@ in
'';
};
# Weekly re-sign of the gateway leaf so short-lived leaves renew
# without depending on a reboot.
#
# `hive-tls-ca` only re-signs at service activation (boot/rebuild); a
# long-uptime host would otherwise let a 30-day leaf lapse silently.
# This service re-signs the leaf directly (not by bouncing hive-tls-ca)
# and propagates the new leaf into the running gateway container when
# the file actually changed.
#
# Propagation mechanism: nginx in the gateway container serves a *copy*
# of the leaf written by `hive-gateway-self-signed-cert` (which runs at
# container start). A host-side `systemctl -M hive-gateway` call
# triggers the re-import + reload, mirroring how hive-c0re reloads the
# gateway after each agents.conf write. A path unit *inside* the
# container was tried first but does not work: IN_MOVED_TO from an
# atomic rename on the host does not propagate across the nspawn
# mount-namespace boundary.
#
# `|| true` on propagation so a stopped gateway never fails the unit —
# its next boot will import the already-rotated leaf anyway.
systemd.services.hive-tls-resign = {
description = "Re-sign the gateway TLS leaf and propagate it into the gateway container";
# hive-tls-ca must have run first so the CA key exists before we try
# to re-sign under it. On first boot `Persistent=true` on the weekly
# timer fires immediately; without this ordering the resign could race
# the CA initialisation and fail with "no such file" on the CA key.
after = [ "hive-tls-ca.service" ];
path = [
pkgs.openssl
pkgs.coreutils
pkgs.systemd
];
serviceConfig = {
Type = "oneshot";
UMask = "0077";
SyslogIdentifier = "hive-tls-resign";
};
script = ''
set -euo pipefail
d=${lib.escapeShellArg cfg.stateDir}
ca="$d/ca.pem"
cak="$d/ca-key.pem"
leaf="$d/gateway.pem"
leafk="$d/gateway-key.pem"
# Re-sign only when the leaf is within half its validity of expiry.
# The weekly cadence catches this window well before the leaf lapses.
halflife=$(( ${toString cfg.leafValidityDays} * 86400 / 2 ))
if [ -s "$leaf" ] && \
openssl x509 -in "$leaf" -noout -checkend "$halflife" >/dev/null 2>&1; then
echo "gateway leaf valid for more than half its lifetime no resign needed"
exit 0
fi
echo "gateway leaf missing or near expiry re-signing under current CA"
before="$(sha256sum "$leaf" 2>/dev/null || true)"
csr="$(mktemp "$d/gateway.csr.XXXXXX")"
ext="$(mktemp "$d/leaf.ext.XXXXXX")"
trap 'rm -f "$csr" "$ext"' EXIT
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout "$leafk" -out "$csr" \
-subj "/CN=${domain}"
{
printf 'subjectAltName=DNS:%s,DNS:forge.%s,DNS:matrix.%s,DNS:*.%s\n' \
${lib.escapeShellArg domain} ${lib.escapeShellArg domain} \
${lib.escapeShellArg domain} ${lib.escapeShellArg domain}
printf 'basicConstraints=critical,CA:FALSE\n'
printf 'keyUsage=critical,digitalSignature,keyEncipherment\n'
printf 'extendedKeyUsage=serverAuth\n'
} > "$ext"
openssl x509 -req -in "$csr" -CA "$ca" -CAkey "$cak" \
-CAcreateserial -days ${toString cfg.leafValidityDays} -sha256 \
-extfile "$ext" -out "$leaf"
chmod 0600 "$leafk"
chmod 0644 "$leaf"
after="$(sha256sum "$leaf" 2>/dev/null || true)"
if [ "$before" != "$after" ]; then
echo "gateway leaf rotated propagating into hive-gateway"
systemctl -M hive-gateway restart hive-gateway-self-signed-cert.service || true
systemctl -M hive-gateway reload nginx.service || true
else
echo "gateway leaf unchanged (already up to date)"
fi
'';
};
systemd.timers.hive-tls-resign = {
description = "Weekly gateway-leaf re-sign and propagation";
wantedBy = [ "timers.target" ];
timerConfig = {
# Run weekly; Persistent=true fires a missed run on next boot if
# the timer was not active (e.g. the host was off on the scheduled
# day), preventing a dormant timer from letting the leaf lapse.
OnCalendar = "weekly";
Persistent = true;
};
};
# Signal the hive-c0re lifecycle that a hive CA exists: it bind-mounts
# this file (read-only, the CA cert ONLY — never the key) into each
# agent container so agents + their tools can trust the gateway's