Files
home-network-k3s-impl/bootstrap/sops/install-age-key.sh
T
jakman85andClaude Opus 4.8 84a2d762f0 Phase 1 (author-only): Flux + SOPS bootstrap + interface wiring (T-1.4)
bootstrap/sops (age-keygen refusing in-repo, .sops.yaml, install-age-key.sh
glue installing the sops-age Secret) + bootstrap/flux (bootstrap.sh: flux
install -> apply -k clusters/dev; decryption/url patches). PM wiring: place
.sops.yaml at repo root (SOPS walks to root); inline the 3 flux patches into
clusters/dev (avoids kustomize ../ load-restriction). clusters/dev builds with
decryption enabled; full CI gate PASS. No key material; nothing executed.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-16 01:21:01 -05:00

28 lines
1.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# bootstrap/sops/install-age-key.sh — install the age PRIVATE key into the cluster as the
# `sops-age` Secret in flux-system, so Flux can decrypt SOPS-encrypted manifests (ADR-0007,
# R-SEC-01). This is the scripted form of the runbook in age-key-secret.md, and the entrypoint
# the Ansible flux_bootstrap role calls (flux_bootstrap_sops_cmd) BEFORE bootstrap.sh.
#
# The private key NEVER lives in git. It is read from AGE_KEY_FILE (default: the standard sops
# age path) and passed to kubectl from a file (not argv). Run at bootstrap by the OPERATOR — not
# by any agent, and not during author-only Phase 1.
set -euo pipefail
AGE_KEY_FILE="${AGE_KEY_FILE:-${HOME}/.config/sops/age/keys.txt}"
NAMESPACE="${FLUX_NAMESPACE:-flux-system}"
SECRET_NAME="${SOPS_SECRET_NAME:-sops-age}"
[ -f "$AGE_KEY_FILE" ] || { echo "ERROR: age key not found at ${AGE_KEY_FILE} — run age-keygen.sh first." >&2; exit 1; }
grep -q 'AGE-SECRET-KEY-' "$AGE_KEY_FILE" || { echo "ERROR: ${AGE_KEY_FILE} contains no AGE-SECRET-KEY." >&2; exit 1; }
kubectl get namespace "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE"
# Flux reads keys ending in `.agekey` from the sops-age Secret. Idempotent create-or-update;
# the key is streamed from the file, never placed on the command line / in shell history.
kubectl create secret generic "$SECRET_NAME" \
--namespace "$NAMESPACE" \
--from-file=age.agekey="$AGE_KEY_FILE" \
--dry-run=client -o yaml | kubectl apply -f -
echo "Installed Secret ${NAMESPACE}/${SECRET_NAME} for Flux SOPS decryption."