Files
vm-skills/secrets-vault/scripts/11_apply.sh
Vault Sovereign eac77ef7b4 Initial commit: VaultMesh Skills collection
Collection of operational skills for VaultMesh infrastructure including:
- backup-sovereign: Backup and recovery operations
- btc-anchor: Bitcoin anchoring
- cloudflare-tunnel-manager: Cloudflare tunnel management
- container-registry: Container registry operations
- disaster-recovery: Disaster recovery procedures
- dns-sovereign: DNS management
- eth-anchor: Ethereum anchoring
- gitea-bootstrap: Gitea setup and configuration
- hetzner-bootstrap: Hetzner server provisioning
- merkle-forest: Merkle tree operations
- node-hardening: Node security hardening
- operator-bootstrap: Operator initialization
- proof-verifier: Cryptographic proof verification
- rfc3161-anchor: RFC3161 timestamping
- secrets-vault: Secrets management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 00:25:00 +00:00

131 lines
3.3 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${VAULT_ROOT:=~/infrastructure/vault}"
: "${AGE_KEY_DIR:=~/.config/sops/age}"
: "${AGE_KEYS_FILE:=~/.config/sops/age/keys.txt}"
: "${RECIPIENTS_FILE:=$SKILL_ROOT/outputs/recipients.txt}"
: "${BACKUP_DIR:=$SKILL_ROOT/outputs/backups}"
backup_file() {
local f="$1"
mkdir -p "$BACKUP_DIR"
if [[ -f "$f" ]]; then
ts="$(date -Iseconds | tr ':' '-')"
cp -p "$f" "$BACKUP_DIR/$(basename "$f").${ts}.bak"
fi
}
main() {
confirm_gate
mkdir -p "$SKILL_ROOT/outputs" "$BACKUP_DIR"
vr="$(expand_path "$VAULT_ROOT")"
kd="$(expand_path "$AGE_KEY_DIR")"
kf="$(expand_path "$AGE_KEYS_FILE")"
mkdir -p "$vr/secrets"
mkdir -p "$kd"
# 1) ensure age identity exists
if [[ ! -f "$kf" ]]; then
log_info "Generating age identity: $kf"
age-keygen -o "$kf" >/dev/null
chmod 600 "$kf"
else
log_info "Using existing age identity: $kf"
chmod 600 "$kf" || true
fi
# extract recipient (public key)
recipient="$(grep -E '^# public key: ' "$kf" | head -n1 | sed 's/^# public key: //')"
[[ -n "$recipient" ]] || die "Could not parse public key from $kf"
echo "$recipient" > "$RECIPIENTS_FILE"
# 2) write .sops.yaml policy
policy="$vr/.sops.yaml"
backup_file "$policy"
cat > "$policy" <<EOF
creation_rules:
- path_regex: secrets/.*\\.enc\\.(yaml|yml|json|env)$
encrypted_regex: '^(data|stringData|secrets|values)$'
age: ["$recipient"]
EOF
# 3) scaffold encrypted templates
# plaintext templates are generated into a temp file then immediately encrypted and removed.
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
# cloudflare
cat > "$tmpdir/cloudflare.yaml" <<EOF
data:
account_id: "REPLACE_ME"
tunnel_token: "REPLACE_ME"
api_token: "REPLACE_ME"
EOF
sops --encrypt --age "$recipient" "$tmpdir/cloudflare.yaml" > "$vr/secrets/cloudflare.enc.yaml"
# gitea
cat > "$tmpdir/gitea.yaml" <<EOF
data:
admin_username: "REPLACE_ME"
admin_password: "REPLACE_ME"
admin_email: "REPLACE_ME"
secret_key: "REPLACE_ME"
EOF
sops --encrypt --age "$recipient" "$tmpdir/gitea.yaml" > "$vr/secrets/gitea.enc.yaml"
# registry
cat > "$tmpdir/registry.yaml" <<EOF
data:
htpasswd: "REPLACE_ME"
tls_cert_pem: "REPLACE_ME"
tls_key_pem: "REPLACE_ME"
EOF
sops --encrypt --age "$recipient" "$tmpdir/registry.yaml" > "$vr/secrets/registry.enc.yaml"
# k8s
cat > "$tmpdir/k8s.yaml" <<EOF
data:
kubeconfig: "REPLACE_ME"
cluster_token: "REPLACE_ME"
EOF
sops --encrypt --age "$recipient" "$tmpdir/k8s.yaml" > "$vr/secrets/k8s.enc.yaml"
# 4) vault README
readme="$vr/README.md"
backup_file "$readme"
cat > "$readme" <<EOF
# Vault (age + sops)
This folder stores **encrypted secrets** for GitOps.
## Edit a secret
\`\`\`bash
sops secrets/cloudflare.enc.yaml
\`\`\`
## Decrypt to stdout (careful)
\`\`\`bash
sops -d secrets/cloudflare.enc.yaml
\`\`\`
## Policy
See \`.sops.yaml\`. Only files matching \`secrets/*.enc.(yaml|json|env)\` are covered.
## Key location
- age identity: \`$kf\` (0600)
- public recipient: stored in \`outputs/recipients.txt\` by the skill
EOF
echo "$vr" > "$SKILL_ROOT/outputs/vault_root.txt"
log_info "Vault forged at: $vr"
log_info "Recipient: $recipient"
}
main "$@"