#!/usr/bin/env bash # encrypt-secrets.sh — encrypt secrets/ directory to secrets.enc/ using age # # Usage: # ./encrypt-secrets.sh [SECRETS_DIR] [AGE_RECIPIENT_OR_KEY_FILE] # # SECRETS_DIR plaintext secrets directory (default: ./secrets) # AGE_RECIPIENT_OR_KEY_FILE age public key, public-key file, or private-key # file with public-key comment # (default: ~/.config/net-kingdom/age.key) # # Encrypts each *.env file (and pi.enc if present) to # secrets.enc//.age. Prefer passing a public age recipient # for normal bootstrap; the private key is needed only for decrypt/apply. # # After a successful encrypt, shreds the plaintext secrets directory unless # --no-shred is passed. # # Run after gen-secrets.sh to store secrets safely in the repo. # Commit secrets.enc/ to git. set -euo pipefail SECRETS_DIR="${1:-./secrets}" AGE_RECIPIENT_OR_KEY="${2:-$HOME/.config/net-kingdom/age.key}" NO_SHRED=false for arg in "$@"; do [[ "$arg" == "--no-shred" ]] && NO_SHRED=true; done if [[ ! -d "$SECRETS_DIR" ]]; then echo "ERROR: secrets directory not found: $SECRETS_DIR" >&2 echo "Run gen-secrets.sh first." >&2 exit 1 fi resolve_recipient() { local source="$1" if [[ "$source" == age1* ]]; then printf '%s\n' "$source" return 0 fi if [[ ! -f "$source" ]]; then echo "ERROR: age recipient/key file not found: $source" >&2 echo "Pass an age public recipient such as age1... or a file containing it." >&2 return 1 fi local recipient recipient=$(grep -m1 '^age1' "$source" || true) if [[ -n "$recipient" ]]; then printf '%s\n' "$recipient" return 0 fi recipient=$(grep -m1 'public key:' "$source" | awk '{print $NF}' || true) if [[ -n "$recipient" ]]; then printf '%s\n' "$recipient" return 0 fi if grep -q 'AGE-SECRET-KEY-1' "$source"; then recipient=$(age-keygen -y "$source" 2>/dev/null || true) if [[ -n "$recipient" ]]; then printf '%s\n' "$recipient" return 0 fi fi echo "ERROR: could not resolve an age public recipient from $source" >&2 return 1 } PUBKEY=$(resolve_recipient "$AGE_RECIPIENT_OR_KEY") ENC_DIR="$(dirname "$SECRETS_DIR")/secrets.enc" mkdir -p "$ENC_DIR" echo "Encrypting secrets → $ENC_DIR/" echo "Recipient: $PUBKEY" echo "" count=0 for component_dir in "$SECRETS_DIR"/*/; do component=$(basename "$component_dir") mkdir -p "$ENC_DIR/$component" for f in "$component_dir"*; do [[ -f "$f" ]] || continue fname=$(basename "$f") out="$ENC_DIR/$component/$fname.age" age -r "$PUBKEY" -o "$out" "$f" echo " encrypted: $component/$fname → secrets.enc/$component/$fname.age" count=$((count + 1)) done done echo "" echo "$count file(s) encrypted to $ENC_DIR/" echo "" if [[ "$NO_SHRED" == false ]]; then echo "Shredding plaintext secrets..." find "$SECRETS_DIR" -type f -exec shred -u {} \; rm -rf "$SECRETS_DIR" echo "Done. Plaintext secrets shredded." else echo "(--no-shred: plaintext kept at $SECRETS_DIR)" fi echo "" echo "Next: commit secrets.enc/ to git."