#!/usr/bin/env bash
# scripts/rotate-secrets.sh
# Rotate a named secret (from /srv/homelab/secrets), write the new
# value atomically, and reload / SIGHUP any consumers that need it.
#
# Usage: rotate-secrets.sh <secret-name>
#
# Docs: mercemay.top/src/homelab-compose/
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=/dev/null
. "${HERE}/lib/log.sh"
SECRETS_DIR="${SECRETS_DIR:-/srv/homelab/secrets}"
declare -A RELOAD=(
[authelia_jwt]="authelia"
[authelia_session]="authelia"
[authelia_storage]="authelia"
[lldap_jwt]="lldap"
[lldap_key_seed]="lldap"
[slack_webhook]="alertmanager"
[redis_password]="redis authelia"
[caddy_api_token]="caddy"
)
name="${1:-}"
if [[ -z "${name}" ]]; then
printf 'usage: %s <secret-name>\n' "$0" >&2
exit 2
fi
if [[ -z "${RELOAD[${name}]:-}" ]]; then
log_err "unknown secret ${name}"
exit 2
fi
dst="${SECRETS_DIR}/${name}"
tmp="${dst}.new"
case "${name}" in
*_webhook)
log_err "webhook secrets cannot be auto-rotated, please paste manually"
exit 2
;;
*)
openssl rand -hex 48 > "${tmp}"
;;
esac
chmod 0600 "${tmp}"
if [[ -f "${dst}" ]]; then
install -m 0600 "${dst}" "${dst}.prev"
fi
mv -f "${tmp}" "${dst}"
log_info "wrote ${dst}"
for svc in ${RELOAD[${name}]}; do
log_info "reloading ${svc}"
if docker inspect "${svc}" >/dev/null 2>&1 \
|| docker inspect "homelab-${svc}-1" >/dev/null 2>&1; then
docker kill -s HUP "${svc}" 2>/dev/null \
|| docker restart "${svc}" 2>/dev/null \
|| docker restart "homelab-${svc}-1" 2>/dev/null \
|| log_warn "reload of ${svc} failed"
else
log_warn "service ${svc} not running, skipping reload"
fi
done
log_info "rotation done for ${name}"