#!/usr/bin/env bash # =========================================================================== # Stage 06: Custom Scripts (~/.local/bin/) # Deploys Julian's custom scripts: Bitwarden SSH loader, Zoom wrapper, # idle battery suspend, env PATH helper, and more. # =========================================================================== # These are the "glue" scripts that make the desktop work the way Julian # expects. They were found in ~/.local/bin/ on the Pop machine. # # Config templates are in config/scripts/ # =========================================================================== CONFIG_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}/config" SCRIPTS_DIR="${CONFIG_DIR}/scripts" TARGET_DIR="$HOME/.local/bin" mkdir -p "$TARGET_DIR" info "Deploying custom scripts to $TARGET_DIR..." # ---- 1. env.sh — PATH helper (sourced by .profile / .bashrc) ---- # Ensures ~/.local/bin is in PATH without duplicate entries. if [ -f "$SCRIPTS_DIR/env.sh" ]; then cp "$SCRIPTS_DIR/env.sh" "$TARGET_DIR/env" chmod +x "$TARGET_DIR/env" ok "env deployed." fi # ---- 2. bw-load-ssh.sh — Load SSH keys from Bitwarden ---- # Script that fetches SSH keys from Bitwarden vault and loads into ssh-agent. # Depends on: bw (Bitwarden CLI), jq, ssh-agent running. if [ -f "$SCRIPTS_DIR/bw-load-ssh.sh" ]; then cp "$SCRIPTS_DIR/bw-load-ssh.sh" "$TARGET_DIR/bw-load-ssh.sh" chmod +x "$TARGET_DIR/bw-load-ssh.sh" ok "bw-load-ssh.sh deployed." fi # ---- 3. zoom.sh — Zoom wrapper for Wayland + AMD GPU ---- # Forces Wayland native mode and VAAPI hardware video decoding on AMD Radeon. # Without this, Zoom would use XWayland and software decoding (bad perf). if [ -f "$SCRIPTS_DIR/zoom.sh" ]; then cp "$SCRIPTS_DIR/zoom.sh" "$TARGET_DIR/zoom" chmod +x "$TARGET_DIR/zoom" ok "zoom wrapper deployed." else # Create default Zoom wrapper cat > "$TARGET_DIR/zoom" << 'SCRIPT' #!/bin/bash # Zoom wrapper — forces Wayland + HW acceleration on AMD GPU export QT_QPA_PLATFORM=wayland export LIBVA_DRIVER_NAME=radeonsi export LIBVA_DRI3_DISABLE=0 exec /usr/bin/zoom "$@" SCRIPT chmod +x "$TARGET_DIR/zoom" ok "zoom wrapper created (default)." fi # ---- 4. idle-battery-suspend.sh — Suspend on battery after idle ---- # Checks if AC is disconnected before suspending. Prevents suspend on desktop. # Used by systemd user service or GNOME autostart. if [ -f "$SCRIPTS_DIR/idle-battery-suspend.sh" ]; then cp "$SCRIPTS_DIR/idle-battery-suspend.sh" "$TARGET_DIR/idle-battery-suspend.sh" chmod +x "$TARGET_DIR/idle-battery-suspend.sh" ok "idle-battery-suspend.sh deployed." fi # ---- 5. Bitwarden CLI (bw) ---- # On Pop: ~/.local/bin/bw (138 MB standalone binary) if ! command -v bw &>/dev/null; then info "Installing Bitwarden CLI..." # bw is a standalone binary — download it BW_LATEST=$(curl -fsSL "https://api.github.com/repos/bitwarden/clients/releases?per_page=1" | grep -oP '"tag_name":\s*"cli-v\K[^"]+' | head -1) || BW_LATEST="2025.1.0" curl -fsSL "https://github.com/bitwarden/clients/releases/download/cli-v${BW_LATEST}/bw-linux-${BW_LATEST}.zip" -o /tmp/bw.zip 2>/dev/null && { unzip -o /tmp/bw.zip -d /tmp/bw-extract 2>/dev/null cp /tmp/bw-extract/bw "$TARGET_DIR/bw" chmod +x "$TARGET_DIR/bw" rm -rf /tmp/bw.zip /tmp/bw-extract ok "Bitwarden CLI installed." } || warn "Bitwarden CLI download failed. Install manually: https://bitwarden.com/help/cli/" fi # Ensure permissions chmod -R 755 "$TARGET_DIR" 2>/dev/null || true # =========================================================================== # 6. Bitwarden Login & Session Setup # Interactive step: logs into Bitwarden and saves session key for later use. # Run bw-load-ssh.sh afterwards to load SSH keys from the vault. # =========================================================================== echo "" info "============================================" info " Bitwarden CLI Setup" info "============================================" info "" info "Julian stores SSH keys and API tokens in Bitwarden." info "This step will log you into Bitwarden and save your session." info "" BW_SESSION_DIR="$HOME/.config/Bitwarden CLI" BW_SESSION_FILE="${BW_SESSION_DIR}/.session" mkdir -p "$BW_SESSION_DIR" # ---- Skip if session already exists and is valid ---- if [ -f "$BW_SESSION_FILE" ]; then BW_SESSION=$(cat "$BW_SESSION_FILE") export BW_SESSION BW_STATUS=$(bw status 2>/dev/null | jq -r '.status // "unauthenticated"' 2>/dev/null || echo "unauthenticated") if [ "$BW_STATUS" = "unlocked" ]; then ok "Bitwarden session already valid (skipping login)." # Skip to SSH key loading else # Session file exists but expired — need to re-authenticate warn "Session file exists but vault is $BW_STATUS. Re-authenticating..." _do_bw_setup=true fi else _do_bw_setup=true fi if [ "${_do_bw_setup:-false}" = true ]; then # ---- Self-hosted server configuration ---- CURRENT_SERVER=$(bw config server 2>/dev/null || echo "https://bitwarden.com") if [ "$CURRENT_SERVER" = "https://bitwarden.com" ] || [ "$CURRENT_SERVER" = "null" ]; then echo "----------------------------------------" info "Server: Bitwarden cloud (default)" echo "----------------------------------------" echo "" if [ -t 0 ]; then read -r -p "Use a self-hosted Bitwarden server instead? [y/N] " use_selfhosted if [[ "$use_selfhosted" =~ ^[Yy]$ ]]; then echo "" read -r -p "Enter your self-hosted server URL (e.g. https://vault.example.com): " server_url if [ -n "$server_url" ]; then bw config server "$server_url" 2>/dev/null && ok "Server set to $server_url" || warn "Failed to set server URL." echo "" fi fi else info "Non-interactive mode: using default Bitwarden cloud." info "To use a self-hosted server, run: bw config server " fi else info "Server: $CURRENT_SERVER (self-hosted)" fi # Check current bw status BW_STATUS=$(bw status 2>/dev/null | jq -r '.status // "unauthenticated"' 2>/dev/null || echo "unauthenticated") if [ "$BW_STATUS" = "unauthenticated" ]; then echo "----------------------------------------" info "Step 1: Log in to Bitwarden" info "You will be prompted for your email and master password." info "If you have 2FA enabled, you'll be prompted for that too." echo "----------------------------------------" echo "" bw login hi@julianprester.com || { warn "Bitwarden login failed or was cancelled." warn "You can run 'bw login' manually later." } echo "" elif [ "$BW_STATUS" = "locked" ]; then info "Bitwarden vault is locked (already logged in)." elif [ "$BW_STATUS" = "unlocked" ]; then info "Bitwarden vault is already unlocked." fi echo "----------------------------------------" info "Step 2: Unlock vault and save session key" info "You will be prompted for your master password again." info "The session key will be saved to ${BW_SESSION_FILE}" echo "----------------------------------------" echo "" bw unlock --raw > "$BW_SESSION_FILE" 2>/dev/null && { chmod 600 "$BW_SESSION_FILE" ok "Session key saved to ${BW_SESSION_FILE}" } || warn "Failed to save session key. Run 'bw unlock --raw > ${BW_SESSION_FILE}' manually." echo "" fi # ---- Load SSH keys from Bitwarden ---- if [ -x "$TARGET_DIR/bw-load-ssh.sh" ]; then echo "----------------------------------------" info "Step 3: Load SSH keys from Bitwarden" echo "----------------------------------------" echo "" # Export session so bw-load-ssh can use it if [ -f "$BW_SESSION_FILE" ]; then BW_SESSION=$(cat "$BW_SESSION_FILE") export BW_SESSION fi if bw status 2>/dev/null | jq -e '.status == "unlocked"' >/dev/null 2>&1; then info "Running bw-load-ssh.sh..." bash "$TARGET_DIR/bw-load-ssh.sh" && ok "SSH keys loaded." || warn "SSH key loading had issues." else warn "Vault is not unlocked. Skipping SSH key loading." warn "Run 'bw-load-ssh.sh' manually after unlocking." fi echo "" fi ok "Stage 06 complete: custom scripts and Bitwarden configured."