#!/usr/bin/env bash # run_once_setup-ssh-keys.sh.tmpl # Pulls SSH PRIVATE keys from Bitwarden and writes them to ~/.ssh/. # # Public keys (.pub files) are committed directly to the repo in dot_ssh/ # and are applied automatically by chezmoi — no Bitwarden needed for those. # # Requires: bw (Bitwarden CLI) to be logged in and unlocked. # To unlock Bitwarden before running chezmoi: # export BW_SESSION=$(bw unlock --raw) # chezmoi apply set -euo pipefail echo "==> Setting up SSH keys from Bitwarden..." SSH_DIR="$HOME/.ssh" mkdir -p "$SSH_DIR" chmod 700 "$SSH_DIR" # Verify Bitwarden is unlocked before fetching keys echo " Checking Bitwarden vault status..." BW_STATUS=$(bw status 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unauthenticated'))" 2>/dev/null || echo "unauthenticated") if [ "$BW_STATUS" != "unlocked" ]; then if [ -n "${BW_SESSION:-}" ]; then echo " Session locked — unlocking with BW_SESSION..." export BW_SESSION BW_SESSION=$(bw unlock --raw 2>/dev/null) BW_STATUS=$(bw status 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unauthenticated'))" 2>/dev/null || echo "unauthenticated") fi if [ "$BW_STATUS" != "unlocked" ]; then echo " WARNING: Bitwarden vault is not unlocked. Skipping SSH key setup." echo " Run: export BW_SESSION=\$(bw unlock --raw) && chezmoi apply" exit 0 fi fi # Pre-sync to avoid sequential sync delays per key fetch echo " Syncing vault..." bw sync 2>/dev/null || true write_key() { local name="$1" local bw_item_name="$2" local key_path="$SSH_DIR/$name" if [ -f "$key_path" ]; then echo " Key already exists: $name (skipping)" return fi echo " Fetching key: $bw_item_name -> $name" bw get notes --session "$BW_SESSION" "$bw_item_name" 2>/dev/null > "$key_path" || { echo " WARNING: Could not fetch '$bw_item_name' from Bitwarden. Skipping." rm -f "$key_path" return } if [ ! -s "$key_path" ]; then echo " WARNING: Key content was empty for '$bw_item_name'. Removing." rm -f "$key_path" return fi chmod 600 "$key_path" echo " Wrote: $key_path" } # Derive private key names from the public key files in dot_ssh/ CHEZMOI_SOURCE_DIR="{{ .chezmoi.sourceDir }}" for pub_file in "$CHEZMOI_SOURCE_DIR/dot_ssh"/*.pub; do [ -f "$pub_file" ] || continue key_name=$(basename "$pub_file" .pub) write_key "$key_name" "SSH Key - $key_name" done echo "==> SSH key setup complete!"