#!/usr/bin/env bash # pack-bundle.sh — create an age-encrypted ops bundle from the secrets directory # # Usage: # ./pack-bundle.sh SECRETS_DIR RECIPIENT_PUBKEY [OUTPUT_FILE] # # RECIPIENT_PUBKEY is the age public key to encrypt to. # Generate one with: age-keygen -o ops-bundle.key (store key safely) # The public key appears on stdout and in the .key file header. # # OUTPUT_FILE defaults to ops-bundle-.tar.age in the current directory. # # Example: # age-keygen -o ~/ops-bundle.key # ./pack-bundle.sh ./secrets "age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p" set -euo pipefail if [[ $# -lt 2 ]]; then echo "Usage: $0 SECRETS_DIR RECIPIENT_PUBKEY [OUTPUT_FILE]" >&2 exit 1 fi SECRETS_DIR="${1%/}" RECIPIENT="$2" TIMESTAMP="$(date +%Y%m%dT%H%M%S)" OUTPUT="${3:-ops-bundle-${TIMESTAMP}.tar.age}" if [[ ! -d "$SECRETS_DIR" ]]; then echo "ERROR: $SECRETS_DIR is not a directory." >&2 exit 1 fi if ! command -v age &>/dev/null; then echo "ERROR: age is not installed. Install with: apt install age" >&2 exit 1 fi TMPTAR="$(mktemp --suffix=.tar)" trap 'shred -u "$TMPTAR" 2>/dev/null || rm -f "$TMPTAR"' EXIT echo "Packing: $SECRETS_DIR → (tar) → (age encrypt) → $OUTPUT" tar -C "$(dirname "$SECRETS_DIR")" -cf "$TMPTAR" "$(basename "$SECRETS_DIR")" age -r "$RECIPIENT" -o "$OUTPUT" "$TMPTAR" echo "Bundle written: $OUTPUT" echo "Recipient key : $RECIPIENT" echo "" echo "Store $OUTPUT offsite (cloud, external drive, second location)." echo "Decrypt with:" echo " age -d -i -o secrets.tar $OUTPUT && tar xf secrets.tar"