Created
April 1, 2026 03:11
-
-
Save jordandm/f1ddeb0a6b8d024e89c274d69dc07bc1 to your computer and use it in GitHub Desktop.
Mycroft fleet — physical recovery (FileVault, screen lock, SSH keys)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # ============================================================================= | |
| # recovery-physical.sh — Physical recovery + SSH key generation | |
| # ============================================================================= | |
| # | |
| # Run at the physical console of each Mac Mini after login. | |
| # Disables FileVault, disables screen lock, generates SSH keypair, | |
| # and authorizes the laptop's public key. | |
| # | |
| # Usage (at physical console): | |
| # curl -sL <raw-url> | bash -s -- --machine mycroft --admin-user mycroft | |
| # curl -sL <raw-url> | bash -s -- --machine claude-code-01 --admin-user admin | |
| # | |
| # Or locally: | |
| # bash recovery-physical.sh --machine mycroft --admin-user mycroft | |
| # bash recovery-physical.sh --machine claude-code-01 --admin-user admin | |
| # | |
| # ============================================================================= | |
| set -euo pipefail | |
| # ============================================================================= | |
| # Constants | |
| # ============================================================================= | |
| # Laptop public key — authorized on all fleet machines | |
| readonly LAPTOP_PUBKEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHo5WrblOAaJRbZVq0Z9OjhFilcEUQfE6yLtmagP27j6 jordan@laptop" | |
| readonly RED='\033[0;31m' | |
| readonly GREEN='\033[0;32m' | |
| readonly YELLOW='\033[0;33m' | |
| readonly BLUE='\033[0;34m' | |
| readonly NC='\033[0m' | |
| log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } | |
| log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } | |
| log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } | |
| log_success() { echo -e "${GREEN}[DONE]${NC} $*"; } | |
| log_skip() { echo -e "${GREEN}[SKIP]${NC} $*"; } | |
| # ============================================================================= | |
| # Argument parsing | |
| # ============================================================================= | |
| MACHINE="" | |
| ADMIN_USER="admin" | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --machine) MACHINE="$2"; shift 2 ;; | |
| --admin-user) ADMIN_USER="$2"; shift 2 ;; | |
| -h|--help) | |
| echo "Usage: bash recovery-physical.sh --machine <name> --admin-user <user>" | |
| echo " --machine mycroft | claude-code-01" | |
| echo " --admin-user admin username on this machine (default: admin)" | |
| exit 0 | |
| ;; | |
| *) log_error "Unknown arg: $1"; exit 1 ;; | |
| esac | |
| done | |
| if [[ -z "${MACHINE}" ]]; then | |
| log_error "--machine is required (mycroft or claude-code-01)" | |
| exit 1 | |
| fi | |
| # ============================================================================= | |
| # Preflight | |
| # ============================================================================= | |
| echo "=============================================================================" | |
| echo " Mycroft Fleet — Physical Recovery" | |
| echo " Machine: ${MACHINE} | Admin user: ${ADMIN_USER}" | |
| echo "=============================================================================" | |
| echo "" | |
| # Check we're on macOS | |
| if [[ "$(uname)" != "Darwin" ]]; then | |
| log_error "This script is for macOS only" | |
| exit 1 | |
| fi | |
| # ============================================================================= | |
| # Step 1: Disable FileVault | |
| # ============================================================================= | |
| echo "" | |
| log_info "Step 1: Disable FileVault" | |
| fv_status="$(fdesetup status 2>/dev/null || echo "unknown")" | |
| if echo "${fv_status}" | grep -qi "off"; then | |
| log_skip "FileVault is already off" | |
| elif echo "${fv_status}" | grep -qi "on"; then | |
| log_warn "FileVault is ON — disabling requires sudo" | |
| log_info "Running: sudo fdesetup disable" | |
| sudo fdesetup disable | |
| log_success "FileVault disabled (will complete after next reboot)" | |
| else | |
| log_warn "Could not determine FileVault status: ${fv_status}" | |
| log_warn "Try manually: sudo fdesetup disable" | |
| fi | |
| # ============================================================================= | |
| # Step 2: Disable screen lock | |
| # ============================================================================= | |
| echo "" | |
| log_info "Step 2: Disable screen lock and display sleep" | |
| # Disable screen saver lock (requires password after screen saver) | |
| # askForPassword = 0 means no password required to wake | |
| defaults write com.apple.screensaver askForPassword -int 0 | |
| log_success "Screen saver password requirement disabled" | |
| # Prevent display from sleeping (set to 0 = never) | |
| sudo pmset -a displaysleep 0 | |
| log_success "Display sleep disabled" | |
| # Prevent system sleep | |
| sudo pmset -a sleep 0 | |
| log_success "System sleep disabled" | |
| # Disable screen saver activation | |
| defaults -currentHost write com.apple.screensaver idleTime -int 0 | |
| log_success "Screen saver idle activation disabled" | |
| # ============================================================================= | |
| # Step 3: Generate SSH keypair for this machine | |
| # ============================================================================= | |
| echo "" | |
| log_info "Step 3: Generate SSH keypair for ${MACHINE}" | |
| ADMIN_HOME="$(eval echo ~"${ADMIN_USER}")" | |
| SSH_DIR="${ADMIN_HOME}/.ssh" | |
| KEY_FILE="${SSH_DIR}/id_ed25519" | |
| # Ensure .ssh directory exists with correct permissions | |
| if [[ ! -d "${SSH_DIR}" ]]; then | |
| mkdir -p "${SSH_DIR}" | |
| chmod 700 "${SSH_DIR}" | |
| chown "${ADMIN_USER}" "${SSH_DIR}" | |
| log_info "Created ${SSH_DIR}" | |
| fi | |
| if [[ -f "${KEY_FILE}" ]]; then | |
| log_skip "SSH keypair already exists at ${KEY_FILE}" | |
| echo "" | |
| log_info "Existing public key:" | |
| cat "${KEY_FILE}.pub" | |
| else | |
| ssh-keygen -t ed25519 -C "${ADMIN_USER}@${MACHINE}" -f "${KEY_FILE}" -N "" | |
| chown "${ADMIN_USER}" "${KEY_FILE}" "${KEY_FILE}.pub" | |
| chmod 600 "${KEY_FILE}" | |
| chmod 644 "${KEY_FILE}.pub" | |
| log_success "SSH keypair generated at ${KEY_FILE}" | |
| fi | |
| echo "" | |
| log_info "Public key for ${MACHINE}:" | |
| echo "---" | |
| cat "${KEY_FILE}.pub" | |
| echo "---" | |
| # ============================================================================= | |
| # Step 4: Authorize laptop key | |
| # ============================================================================= | |
| echo "" | |
| log_info "Step 4: Authorize laptop key for SSH access" | |
| AUTH_KEYS="${SSH_DIR}/authorized_keys" | |
| if [[ -f "${AUTH_KEYS}" ]] && grep -qF "${LAPTOP_PUBKEY}" "${AUTH_KEYS}"; then | |
| log_skip "Laptop key already authorized" | |
| else | |
| echo "${LAPTOP_PUBKEY}" >> "${AUTH_KEYS}" | |
| chmod 600 "${AUTH_KEYS}" | |
| chown "${ADMIN_USER}" "${AUTH_KEYS}" | |
| log_success "Laptop key added to authorized_keys" | |
| fi | |
| # ============================================================================= | |
| # Step 5: Verify SSH is enabled | |
| # ============================================================================= | |
| echo "" | |
| log_info "Step 5: Verify Remote Login (SSH) is enabled" | |
| ssh_status="$(sudo systemsetup -getremotelogin 2>/dev/null || echo "unknown")" | |
| if echo "${ssh_status}" | grep -qi "on"; then | |
| log_skip "Remote Login is already enabled" | |
| else | |
| log_warn "Remote Login appears to be off — enabling" | |
| sudo systemsetup -setremotelogin on | |
| log_success "Remote Login enabled" | |
| fi | |
| # ============================================================================= | |
| # Summary | |
| # ============================================================================= | |
| echo "" | |
| echo "=============================================================================" | |
| echo " Recovery Complete — ${MACHINE}" | |
| echo "=============================================================================" | |
| echo "" | |
| echo " FileVault: Disabled" | |
| echo " Screen lock: Disabled" | |
| echo " Display sleep: Never" | |
| echo " SSH keypair: ${KEY_FILE}" | |
| echo " Laptop key: Authorized" | |
| echo " Remote Login: Enabled" | |
| echo "" | |
| echo " PUBLIC KEY (save this — give to agent for cross-machine auth + Doppler):" | |
| echo "" | |
| cat "${KEY_FILE}.pub" | |
| echo "" | |
| echo "=============================================================================" | |
| echo "" | |
| echo " Next: verify SSH from laptop:" | |
| echo " ssh ${ADMIN_USER}@<ip-address>" | |
| echo "" | |
| echo "=============================================================================" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment