Tutorial

Nuevas actualizaciones y mejoras para Macfleet.

Aviso importante

Los ejemplos de código y scripts proporcionados en estos tutoriales son solo para propósitos educativos. Macfleet no es responsable de ningún problema, daño o vulnerabilidad de seguridad que pueda surgir del uso, modificación o implementación de estos ejemplos. Siempre revisa y prueba el código en un entorno seguro antes de usarlo en sistemas de producción.

macOS Update Management

Implement enterprise-grade macOS update management across your MacFleet deployment with automated patch deployment, compliance monitoring, staged rollouts, and comprehensive update policies. This tutorial provides solutions for maintaining security patches and OS currency while minimizing disruption to business operations.

Understanding macOS Update Management

macOS provides several methods for managing operating system updates programmatically:

  • Software Update utility - Command-line tool for checking and installing updates
  • startosinstall - Direct OS installation from installer applications
  • MDM Update Commands - Mobile Device Management integration
  • Configuration Profiles - Policy-based update control
  • Apple Software Lookup Service - Update availability checking

Basic Update Operations

List Available Updates

#!/bin/bash

# List all available OS versions for installation
softwareupdate --list-full-installers | grep 'macOS' | awk '{print ++count " " $0}'

Download OS Installer

#!/bin/bash

# Fetch specific OS version installer
softwareupdate --fetch-full-installer --full-installer-version 12.1

echo "OS installer downloaded successfully"

Install OS Update

#!/bin/bash

# Basic OS update installation
osVersion="$1"
majorVersion=$(echo $osVersion | cut -d "." -f 1)
minorVersion=$(echo $osVersion | cut -d "." -f 2)

if [ $majorVersion == "12" ]; then
    installerPath="Install macOS Monterey.app"
elif [ $majorVersion == "11" ]; then
    installerPath="Install macOS Big Sur.app"
elif [ $minorVersion == "15"* ]; then
    installerPath="Install macOS Catalina.app"
fi

fullPath="/Applications/$installerPath/Contents/Resources/startosinstall"
softwareupdate --fetch-full-installer --full-installer-version $osVersion
echo <Password> | "$fullPath" --agreetolicense --forcequitapps --nointeraction --user <Username> --stdinpass

Enterprise Update Management System

Comprehensive Update Management Tool

#!/bin/bash

# MacFleet Enterprise macOS Update Management Tool
# Automated patch deployment and compliance monitoring

# Configuration
CONFIG_FILE="/etc/macfleet/update_policy.conf"
LOG_FILE="/var/log/macfleet_updates.log"
CACHE_DIR="/Library/MacFleet/Updates"
REPORT_DIR="/var/log/macfleet_reports"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$CACHE_DIR" "$REPORT_DIR"

# Default update policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# MacFleet macOS Update Management Policy
# Version: 2.0

# Update Enforcement
ENFORCE_SECURITY_UPDATES=true
ALLOW_MAJOR_OS_UPDATES=false
AUTO_INSTALL_SECURITY_PATCHES=true
DEFER_MAJOR_UPDATES_DAYS=30

# Scheduling Configuration
UPDATE_CHECK_INTERVAL=86400  # 24 hours
MAINTENANCE_WINDOW_START="02:00"
MAINTENANCE_WINDOW_END="06:00"
WEEKEND_UPDATES_ALLOWED=true
BUSINESS_HOURS_UPDATES=false

# Deployment Strategy
STAGED_ROLLOUT=true
PILOT_GROUP_PERCENTAGE=10
PRODUCTION_DELAY_DAYS=7
EMERGENCY_PATCH_IMMEDIATE=true

# System Requirements
MIN_BATTERY_PERCENTAGE=50
MIN_FREE_SPACE_GB=20
REQUIRE_AC_POWER=true
MAX_REBOOT_ATTEMPTS=3

# Notification Settings
NOTIFY_USERS_BEFORE_UPDATE=true
NOTIFICATION_LEAD_TIME_HOURS=24
FORCE_UPDATE_AFTER_DEFERRALS=5
SEND_COMPLETION_REPORTS=true

# Compatibility Settings
EXCLUDE_BETA_UPDATES=true
VALIDATE_APP_COMPATIBILITY=true
BACKUP_BEFORE_MAJOR_UPDATE=true
EOF

# Source configuration
source "$CONFIG_FILE" 2>/dev/null || true

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Get current macOS version
get_current_version() {
    sw_vers -productVersion
}

# Get available updates
get_available_updates() {
    echo "=== Available Updates ==="
    
    # Check for software updates
    local updates
    updates=$(softwareupdate --list 2>/dev/null)
    
    if echo "$updates" | grep -q "No new software available"; then
        echo "✅ System is up to date"
        return 0
    else
        echo "Available updates:"
        echo "$updates"
        return 1
    fi
}

# Get available OS installers
get_available_installers() {
    echo "=== Available OS Installers ==="
    
    # List full installers
    local installers
    installers=$(softwareupdate --list-full-installers 2>/dev/null)
    
    if [[ -n "$installers" ]]; then
        echo "$installers" | grep 'macOS' | awk '{print ++count " " $0}'
    else
        echo "No OS installers available"
    fi
}

# Check system readiness for updates
check_update_readiness() {
    echo "=== Update Readiness Check ==="
    local issues=0
    local warnings=0
    
    # Check battery level
    local battery_level
    if command -v pmset >/dev/null; then
        battery_level=$(pmset -g batt | grep -Eo "\d+%" | tr -d '%' | head -1)
        
        if [[ -n "$battery_level" && $battery_level -lt $MIN_BATTERY_PERCENTAGE ]]; then
            echo "❌ Battery level too low: ${battery_level}% (min: ${MIN_BATTERY_PERCENTAGE}%)"
            ((issues++))
        else
            echo "✅ Battery level adequate: ${battery_level:-AC Power}%"
        fi
    fi
    
    # Check AC power if required
    if [[ "$REQUIRE_AC_POWER" == "true" ]]; then
        local ac_power
        ac_power=$(pmset -g ps | grep "AC Power" || echo "")
        
        if [[ -z "$ac_power" ]]; then
            echo "❌ AC power required but not connected"
            ((issues++))
        else
            echo "✅ AC power connected"
        fi
    fi
    
    # Check free disk space
    local free_space_gb
    free_space_gb=$(df / | awk 'NR==2 {print int($4/1024/1024)}')
    
    if [[ $free_space_gb -lt $MIN_FREE_SPACE_GB ]]; then
        echo "❌ Insufficient disk space: ${free_space_gb}GB (min: ${MIN_FREE_SPACE_GB}GB)"
        ((issues++))
    else
        echo "✅ Sufficient disk space: ${free_space_gb}GB"
    fi
    
    # Check if system is in maintenance window
    local current_time
    current_time=$(date '+%H:%M')
    
    if [[ "$current_time" > "$MAINTENANCE_WINDOW_START" && "$current_time" < "$MAINTENANCE_WINDOW_END" ]]; then
        echo "✅ Within maintenance window"
    else
        echo "⚠️  Outside maintenance window (current: $current_time)"
        ((warnings++))
    fi
    
    # Check if weekend updates are allowed
    local day_of_week
    day_of_week=$(date '+%u')  # 1=Monday, 7=Sunday
    
    if [[ $day_of_week -gt 5 ]] && [[ "$WEEKEND_UPDATES_ALLOWED" != "true" ]]; then
        echo "❌ Weekend updates not allowed"
        ((issues++))
    fi
    
    echo "Readiness summary: $issues issues, $warnings warnings"
    return $issues
}

# Install security updates
install_security_updates() {
    echo "=== Installing Security Updates ==="
    
    if [[ "$AUTO_INSTALL_SECURITY_PATCHES" != "true" ]]; then
        echo "Security update auto-installation disabled"
        return 0
    fi
    
    # Check readiness
    if ! check_update_readiness >/dev/null; then
        echo "❌ System not ready for updates"
        return 1
    fi
    
    # Install recommended updates
    echo "Installing security and recommended updates..."
    log_action "Starting security update installation"
    
    # Use softwareupdate to install recommended updates
    if softwareupdate --install --recommended --verbose; then
        echo "✅ Security updates installed successfully"
        log_action "Security updates installed successfully"
        
        # Check if restart is required
        if softwareupdate --list | grep -q "restart"; then
            echo "⚠️  System restart required"
            log_action "System restart required after security updates"
        fi
        
        return 0
    else
        echo "❌ Failed to install security updates"
        log_action "FAILED: Security update installation"
        return 1
    fi
}

# Download OS installer
download_os_installer() {
    local target_version="$1"
    
    echo "=== Downloading OS Installer ==="
    echo "Target version: $target_version"
    
    # Validate version format
    if [[ ! "$target_version" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
        echo "❌ Invalid version format: $target_version"
        return 1
    fi
    
    # Download installer
    echo "Downloading macOS $target_version installer..."
    log_action "Downloading macOS installer: $target_version"
    
    if softwareupdate --fetch-full-installer --full-installer-version "$target_version"; then
        echo "✅ macOS installer downloaded successfully"
        log_action "macOS installer downloaded: $target_version"
        
        # Verify installer exists
        local installer_path
        installer_path=$(find /Applications -name "Install macOS*.app" -path "*$target_version*" 2>/dev/null | head -1)
        
        if [[ -n "$installer_path" && -d "$installer_path" ]]; then
            echo "Installer location: $installer_path"
            return 0
        else
            # Check for installer by major version
            local major_version
            major_version=$(echo "$target_version" | cut -d'.' -f1)
            
            case "$major_version" in
                "15")
                    installer_path="/Applications/Install macOS Sequoia.app"
                    ;;
                "14")
                    installer_path="/Applications/Install macOS Sonoma.app"
                    ;;
                "13")
                    installer_path="/Applications/Install macOS Ventura.app"
                    ;;
                "12")
                    installer_path="/Applications/Install macOS Monterey.app"
                    ;;
                "11")
                    installer_path="/Applications/Install macOS Big Sur.app"
                    ;;
                *)
                    echo "❌ Unknown macOS version: $target_version"
                    return 1
                    ;;
            esac
            
            if [[ -d "$installer_path" ]]; then
                echo "Installer found: $installer_path"
                return 0
            else
                echo "❌ Installer not found after download"
                return 1
            fi
        fi
    else
        echo "❌ Failed to download macOS installer"
        log_action "FAILED: macOS installer download for $target_version"
        return 1
    fi
}

# Install major OS update
install_major_update() {
    local target_version="$1"
    local admin_user="$2"
    local admin_password="$3"
    
    echo "=== Installing Major OS Update ==="
    echo "Target version: $target_version"
    echo "Admin user: $admin_user"
    
    if [[ "$ALLOW_MAJOR_OS_UPDATES" != "true" ]]; then
        echo "❌ Major OS updates not allowed by policy"
        return 1
    fi
    
    # Check readiness
    if ! check_update_readiness; then
        echo "❌ System not ready for major update"
        return 1
    fi
    
    # Find installer
    local installer_path
    local major_version
    major_version=$(echo "$target_version" | cut -d'.' -f1)
    
    case "$major_version" in
        "15")
            installer_path="/Applications/Install macOS Sequoia.app"
            ;;
        "14")
            installer_path="/Applications/Install macOS Sonoma.app"
            ;;
        "13")
            installer_path="/Applications/Install macOS Ventura.app"
            ;;
        "12")
            installer_path="/Applications/Install macOS Monterey.app"
            ;;
        "11")
            installer_path="/Applications/Install macOS Big Sur.app"
            ;;
        *)
            echo "❌ Unsupported macOS version: $target_version"
            return 1
            ;;
    esac
    
    if [[ ! -d "$installer_path" ]]; then
        echo "Installer not found, downloading..."
        if ! download_os_installer "$target_version"; then
            return 1
        fi
    fi
    
    # Prepare installation command
    local install_cmd="$installer_path/Contents/Resources/startosinstall"
    local install_args="--agreetolicense --forcequitapps --nointeraction"
    
    # Check if Apple Silicon Mac (requires credentials)
    if system_profiler SPHardwareDataType | grep -q "Apple M"; then
        if [[ -z "$admin_user" || -z "$admin_password" ]]; then
            echo "❌ Apple Silicon Mac requires admin credentials"
            return 1
        fi
        install_args="$install_args --user $admin_user --stdinpass"
    fi
    
    echo "Starting macOS installation..."
    log_action "Starting major OS update to $target_version"
    
    # Execute installation
    if [[ -n "$admin_password" ]]; then
        echo "$admin_password" | "$install_cmd" $install_args
    else
        "$install_cmd" $install_args
    fi
    
    local result=$?
    
    if [[ $result -eq 0 ]]; then
        echo "✅ macOS update initiated successfully"
        log_action "macOS update initiated successfully to $target_version"
        echo "⚠️  System will restart to complete installation"
    else
        echo "❌ Failed to initiate macOS update (exit code: $result)"
        log_action "FAILED: macOS update initiation to $target_version (exit code: $result)"
    fi
    
    return $result
}

# Generate update compliance report
generate_update_report() {
    local report_file="$REPORT_DIR/update_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Update Compliance Report ==="
    
    # Get current system information
    local current_version
    current_version=$(sw_vers -productVersion)
    local build_version
    build_version=$(sw_vers -buildVersion)
    local hardware_model
    hardware_model=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)
    
    # Check for available updates
    local updates_available="false"
    local security_updates_available="false"
    
    if ! softwareupdate --list 2>/dev/null | grep -q "No new software available"; then
        updates_available="true"
        
        if softwareupdate --list 2>/dev/null | grep -i "security\|recommended"; then
            security_updates_available="true"
        fi
    fi
    
    # Calculate days since last update
    local last_update_date
    last_update_date=$(system_profiler SPInstallHistoryDataType | grep "Install Date" | head -1 | awk -F: '{print $2}' | xargs)
    local days_since_update="unknown"
    
    if [[ -n "$last_update_date" ]]; then
        local last_update_epoch
        last_update_epoch=$(date -j -f "%m/%d/%y" "$last_update_date" "+%s" 2>/dev/null || echo "0")
        local current_epoch
        current_epoch=$(date "+%s")
        days_since_update=$(( (current_epoch - last_update_epoch) / 86400 ))
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "update_compliance",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "hardware_model": "$hardware_model",
    "current_os_version": "$current_version",
    "build_version": "$build_version"
  },
  "update_status": {
    "updates_available": $updates_available,
    "security_updates_available": $security_updates_available,
    "days_since_last_update": $days_since_update,
    "last_update_date": "$last_update_date",
    "auto_update_enabled": $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo false)
  },
  "policy_compliance": {
    "security_updates_enforced": $ENFORCE_SECURITY_UPDATES,
    "major_updates_allowed": $ALLOW_MAJOR_OS_UPDATES,
    "auto_install_enabled": $AUTO_INSTALL_SECURITY_PATCHES,
    "staged_rollout_enabled": $STAGED_ROLLOUT
  },
  "system_readiness": {
    "sufficient_battery": true,
    "ac_power_connected": $(pmset -g ps | grep -q "AC Power" && echo true || echo false),
    "sufficient_disk_space": true,
    "in_maintenance_window": false
  }
}
EOF
    
    echo "Update compliance report saved to: $report_file"
    log_action "Update compliance report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== MacFleet Update Management Tool Started ==="
    
    case "${1:-status}" in
        "check")
            get_available_updates
            ;;
        "security")
            install_security_updates
            ;;
        "download")
            download_os_installer "$2"
            ;;
        "install")
            install_major_update "$2" "$3" "$4"
            ;;
        "readiness")
            check_update_readiness
            ;;
        "installers")
            get_available_installers
            ;;
        "report")
            generate_update_report
            ;;
        "status"|*)
            echo "Current macOS version: $(get_current_version)"
            get_available_updates
            ;;
    esac
    
    log_action "=== Update management operation completed ==="
}

# Execute main function
main "$@"

Advanced Update Management

Staged Rollout Management

#!/bin/bash

# Staged rollout management for enterprise deployments
manage_staged_rollout() {
    local update_version="$1"
    local deployment_stage="${2:-pilot}"
    
    echo "=== Staged Rollout Management ==="
    echo "Update version: $update_version"
    echo "Deployment stage: $deployment_stage"
    
    # Define device groups
    local device_serial
    device_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)
    
    # Calculate hash for consistent group assignment
    local hash_value
    hash_value=$(echo "$device_serial" | md5 | cut -c1-2)
    local numeric_hash
    numeric_hash=$(printf "%d" "0x$hash_value")
    local group_percentage
    group_percentage=$((numeric_hash % 100))
    
    case "$deployment_stage" in
        "pilot")
            if [[ $group_percentage -lt $PILOT_GROUP_PERCENTAGE ]]; then
                echo "✅ Device selected for pilot deployment"
                log_action "Device included in pilot group for $update_version"
                return 0
            else
                echo "⏳ Device not in pilot group, waiting for production rollout"
                return 1
            fi
            ;;
        "production")
            echo "✅ Device eligible for production deployment"
            log_action "Device included in production rollout for $update_version"
            return 0
            ;;
        "emergency")
            echo "🚨 Emergency deployment - bypassing staging"
            log_action "Emergency deployment initiated for $update_version"
            return 0
            ;;
        *)
            echo "❌ Unknown deployment stage: $deployment_stage"
            return 1
            ;;
    esac
}

# Usage example:
# manage_staged_rollout "14.2.1" "pilot"

Update Compatibility Checking

#!/bin/bash

# Check application compatibility before major updates
check_app_compatibility() {
    local target_version="$1"
    
    echo "=== Application Compatibility Check ==="
    
    if [[ "$VALIDATE_APP_COMPATIBILITY" != "true" ]]; then
        echo "App compatibility checking disabled"
        return 0
    fi
    
    local incompatible_apps=()
    
    # Check for 32-bit applications (not supported in macOS 10.15+)
    local target_major
    target_major=$(echo "$target_version" | cut -d'.' -f1)
    
    if [[ $target_major -ge 10 ]]; then
        echo "Checking for 32-bit applications..."
        
        # Use system_profiler to find 32-bit apps
        local bit32_apps
        bit32_apps=$(system_profiler SPApplicationsDataType | grep -B1 -A1 "64-Bit (Intel): No" | grep "Location:" | awk -F: '{print $2}' | xargs)
        
        if [[ -n "$bit32_apps" ]]; then
            echo "⚠️  Found 32-bit applications:"
            echo "$bit32_apps"
            incompatible_apps+=("32-bit applications")
        fi
    fi
    
    # Check for known incompatible applications
    local known_incompatible=(
        "/Applications/Adobe CS6"
        "/Applications/Microsoft Office 2011"
        "/Applications/Final Cut Pro 7"
    )
    
    for app_path in "${known_incompatible[@]}"; do
        if [[ -d "$app_path" ]]; then
            echo "⚠️  Found known incompatible app: $app_path"
            incompatible_apps+=("$(basename "$app_path")")
        fi
    done
    
    # Generate compatibility report
    if [[ ${#incompatible_apps[@]} -eq 0 ]]; then
        echo "✅ No compatibility issues detected"
        return 0
    else
        echo "❌ Compatibility issues found:"
        printf '  - %s\n' "${incompatible_apps[@]}"
        
        # Log compatibility issues
        log_action "App compatibility issues found for $target_version: ${incompatible_apps[*]}"
        return 1
    fi
}

check_app_compatibility "14.0"

Automated Backup Before Updates

#!/bin/bash

# Create system backup before major updates
create_pre_update_backup() {
    local backup_destination="${1:-/Volumes/Backup}"
    
    echo "=== Pre-Update Backup ==="
    
    if [[ "$BACKUP_BEFORE_MAJOR_UPDATE" != "true" ]]; then
        echo "Pre-update backup disabled"
        return 0
    fi
    
    # Check backup destination
    if [[ ! -d "$backup_destination" ]]; then
        echo "❌ Backup destination not available: $backup_destination"
        return 1
    fi
    
    # Create Time Machine backup
    echo "Creating Time Machine backup..."
    if tmutil startbackup --auto --block; then
        echo "✅ Time Machine backup completed"
        log_action "Pre-update Time Machine backup completed"
    else
        echo "⚠️  Time Machine backup failed, continuing with update"
        log_action "WARNING: Pre-update Time Machine backup failed"
    fi
    
    # Create system configuration backup
    local config_backup="$backup_destination/macfleet_config_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    echo "Creating configuration backup..."
    if tar -czf "$config_backup" \
        /etc/macfleet \
        /Library/Preferences \
        /System/Library/LaunchDaemons/com.macfleet.* \
        2>/dev/null; then
        echo "✅ Configuration backup created: $config_backup"
        log_action "Configuration backup created: $config_backup"
    else
        echo "⚠️  Configuration backup failed"
        log_action "WARNING: Configuration backup failed"
    fi
    
    return 0
}

create_pre_update_backup

Monitoring and Compliance

Update Compliance Monitoring

#!/bin/bash

# Monitor update compliance across fleet
monitor_update_compliance() {
    echo "=== Update Compliance Monitoring ==="
    
    local current_version
    current_version=$(sw_vers -productVersion)
    
    # Check against security baselines
    local security_baseline="14.2.1"  # Example baseline
    
    if [[ "$(printf '%s\n' "$security_baseline" "$current_version" | sort -V | head -1)" != "$security_baseline" ]]; then
        echo "❌ Below security baseline (current: $current_version, required: $security_baseline)"
        log_action "COMPLIANCE VIOLATION: Below security baseline $security_baseline"
        
        # Trigger remediation if enabled
        if [[ "$ENFORCE_SECURITY_UPDATES" == "true" ]]; then
            echo "Initiating automatic remediation..."
            install_security_updates
        fi
    else
        echo "✅ Meets security baseline requirements"
    fi
    
    # Check for overdue updates
    local last_check
    last_check=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate LastSuccessfulDate 2>/dev/null || echo "")
    
    if [[ -n "$last_check" ]]; then
        local days_since_check
        days_since_check=$(( ($(date +%s) - $(date -j -f "%Y-%m-%d %H:%M:%S %z" "$last_check" +%s 2>/dev/null || echo 0)) / 86400 ))
        
        if [[ $days_since_check -gt 7 ]]; then
            echo "⚠️  Updates not checked for $days_since_check days"
            log_action "WARNING: Updates not checked for $days_since_check days"
        fi
    fi
}

monitor_update_compliance

Emergency Patch Deployment

#!/bin/bash

# Emergency patch deployment for critical security updates
deploy_emergency_patch() {
    local patch_version="$1"
    local override_policies="${2:-false}"
    
    echo "=== Emergency Patch Deployment ==="
    echo "Patch version: $patch_version"
    echo "Override policies: $override_policies"
    
    log_action "EMERGENCY: Deploying critical patch $patch_version"
    
    # Override normal restrictions for emergency patches
    if [[ "$override_policies" == "true" ]]; then
        # Temporarily modify configuration
        local original_config
        original_config=$(cat "$CONFIG_FILE")
        
        # Emergency configuration
        cat > "$CONFIG_FILE" << 'EOF'
ENFORCE_SECURITY_UPDATES=true
AUTO_INSTALL_SECURITY_PATCHES=true
EMERGENCY_PATCH_IMMEDIATE=true
REQUIRE_AC_POWER=false
MIN_BATTERY_PERCENTAGE=20
BUSINESS_HOURS_UPDATES=true
EOF
        
        # Install emergency patch
        if install_security_updates; then
            echo "✅ Emergency patch deployed successfully"
            log_action "Emergency patch $patch_version deployed successfully"
        else
            echo "❌ Emergency patch deployment failed"
            log_action "CRITICAL: Emergency patch $patch_version deployment FAILED"
        fi
        
        # Restore original configuration
        echo "$original_config" > "$CONFIG_FILE"
    else
        # Standard emergency deployment
        install_security_updates
    fi
}

# Example usage:
# deploy_emergency_patch "14.2.1" "true"

Important Configuration Notes

macOS Update Tools

  • softwareupdate - Command-line Software Update utility
  • startosinstall - Direct OS installation tool
  • system_profiler - System information and update history
  • tmutil - Time Machine backup utility
  • pmset - Power management settings

Apple Silicon Considerations

  • Admin credentials required - Updates need user authentication
  • Secure Boot policies - May affect update installation
  • Recovery mode options - Different from Intel Macs
  • Reduced kernel extensions - System extension model

Best Practices for Enterprise

  1. Staged Deployment Strategy

    • Test updates on pilot group first
    • Monitor for issues before full rollout
    • Maintain rollback capabilities
  2. Compliance Management

    • Define security baselines
    • Monitor update status regularly
    • Automate compliance reporting
  3. Risk Mitigation

    • Backup before major updates
    • Test application compatibility
    • Plan for emergency patches
  4. User Communication

    • Notify users of scheduled updates
    • Provide clear maintenance windows
    • Offer deferral options within policy limits

Troubleshooting Common Issues

  • Insufficient disk space - Clean up before updates or increase storage
  • Power requirements - Ensure AC power for major updates
  • Network connectivity - Verify access to Apple's update servers
  • Authentication failures - Check admin credentials on Apple Silicon
  • Installation failures - Review system logs and compatibility

Remember to test update procedures thoroughly in a non-production environment before deploying across your entire MacFleet.

Tutorial

Nuevas actualizaciones y mejoras para Macfleet.

Configurando un Runner de GitHub Actions en un Mac Mini (Apple Silicon)

Runner de GitHub Actions

GitHub Actions es una plataforma poderosa de CI/CD que te permite automatizar tus flujos de trabajo de desarrollo de software. Aunque GitHub ofrece runners hospedados, los runners auto-hospedados proporcionan mayor control y personalización para tu configuración de CI/CD. Este tutorial te guía a través de la configuración y conexión de un runner auto-hospedado en un Mac mini para ejecutar pipelines de macOS.

Prerrequisitos

Antes de comenzar, asegúrate de tener:

  • Un Mac mini (regístrate en Macfleet)
  • Un repositorio de GitHub con derechos de administrador
  • Un gestor de paquetes instalado (preferiblemente Homebrew)
  • Git instalado en tu sistema

Paso 1: Crear una Cuenta de Usuario Dedicada

Primero, crea una cuenta de usuario dedicada para el runner de GitHub Actions:

# Crear la cuenta de usuario 'gh-runner'
sudo dscl . -create /Users/gh-runner
sudo dscl . -create /Users/gh-runner UserShell /bin/bash
sudo dscl . -create /Users/gh-runner RealName "GitHub runner"
sudo dscl . -create /Users/gh-runner UniqueID "1001"
sudo dscl . -create /Users/gh-runner PrimaryGroupID 20
sudo dscl . -create /Users/gh-runner NFSHomeDirectory /Users/gh-runner

# Establecer la contraseña para el usuario
sudo dscl . -passwd /Users/gh-runner tu_contraseña

# Agregar 'gh-runner' al grupo 'admin'
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Cambia a la nueva cuenta de usuario:

su gh-runner

Paso 2: Instalar Software Requerido

Instala Git y Rosetta 2 (si usas Apple Silicon):

# Instalar Git si no está ya instalado
brew install git

# Instalar Rosetta 2 para Macs Apple Silicon
softwareupdate --install-rosetta

Paso 3: Configurar el Runner de GitHub Actions

  1. Ve a tu repositorio de GitHub
  2. Navega a Configuración > Actions > Runners

Runner de GitHub Actions

  1. Haz clic en "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Selecciona macOS como imagen del runner y ARM64 como arquitectura
  3. Sigue los comandos proporcionados para descargar y configurar el runner

Runner de GitHub Actions

Crea un archivo .env en el directorio _work del runner:

# archivo _work/.env
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Ejecuta el script run.sh en tu directorio del runner para completar la configuración.
  2. Verifica que el runner esté activo y escuchando trabajos en la terminal y revisa la configuración del repositorio de GitHub para la asociación del runner y el estado Idle.

Runner de GitHub Actions

Paso 4: Configurar Sudoers (Opcional)

Si tus acciones requieren privilegios de root, configura el archivo sudoers:

sudo visudo

Agrega la siguiente línea:

gh-runner ALL=(ALL) NOPASSWD: ALL

Paso 5: Usar el Runner en Flujos de Trabajo

Configura tu flujo de trabajo de GitHub Actions para usar el runner auto-hospedado:

name: Flujo de trabajo de muestra

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: [self-hosted, macOS, ARM64]
    steps:
      - name: Instalar NodeJS
        run: brew install node

El runner está autenticado en tu repositorio y etiquetado con self-hosted, macOS, y ARM64. Úsalo en tus flujos de trabajo especificando estas etiquetas en el campo runs-on:

runs-on: [self-hosted, macOS, ARM64]

Mejores Prácticas

  • Mantén tu software del runner actualizado
  • Monitorea regularmente los logs del runner para problemas
  • Usa etiquetas específicas para diferentes tipos de runners
  • Implementa medidas de seguridad apropiadas
  • Considera usar múltiples runners para balanceo de carga

Solución de Problemas

Problemas comunes y soluciones:

  1. Runner no conectando:

    • Verifica conectividad de red
    • Verifica validez del token de GitHub
    • Asegúrate de permisos apropiados
  2. Fallas de construcción:

    • Verifica instalación de Xcode
    • Verifica dependencias requeridas
    • Revisa logs del flujo de trabajo
  3. Problemas de permisos:

    • Verifica permisos de usuario
    • Verifica configuración de sudoers
    • Revisa permisos del sistema de archivos

Conclusión

Ahora tienes un runner auto-hospedado de GitHub Actions configurado en tu Mac mini. Esta configuración te proporciona más control sobre tu entorno de CI/CD y te permite ejecutar flujos de trabajo específicos de macOS de manera eficiente.

Recuerda mantener regularmente tu runner y mantenerlo actualizado con los últimos parches de seguridad y versiones de software.

Aplicación Nativa

Aplicación nativa de Macfleet

Guía de Instalación de Macfleet

Macfleet es una solución poderosa de gestión de flota diseñada específicamente para entornos de Mac Mini alojados en la nube. Como proveedor de hosting en la nube de Mac Mini, puedes usar Macfleet para monitorear, gestionar y optimizar toda tu flota de instancias Mac virtualizadas.

Esta guía de instalación te llevará a través de la configuración del monitoreo de Macfleet en sistemas macOS, Windows y Linux para asegurar una supervisión integral de tu infraestructura en la nube.

🍎 macOS

  • Descarga el archivo .dmg para Mac aquí
  • Haz doble clic en el archivo .dmg descargado
  • Arrastra la aplicación Macfleet a la carpeta Aplicaciones
  • Expulsa el archivo .dmg
  • Abre Preferencias del Sistema > Seguridad y Privacidad
    • Pestaña Privacidad > Accesibilidad
    • Marca Macfleet para permitir el monitoreo
  • Inicia Macfleet desde Aplicaciones
  • El seguimiento comienza automáticamente

🪟 Windows

  • Descarga el archivo .exe para Windows aquí
  • Haz clic derecho en el archivo .exe > "Ejecutar como administrador"
  • Sigue el asistente de instalación
  • Acepta los términos y condiciones
  • Permite en Windows Defender si se solicita
  • Concede permisos de monitoreo de aplicaciones
  • Inicia Macfleet desde el Menú Inicio
  • La aplicación comienza el seguimiento automáticamente

🐧 Linux

  • Descarga el paquete .deb (Ubuntu/Debian) o .rpm (CentOS/RHEL) aquí
  • Instala usando tu gestor de paquetes
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Permite permisos de acceso X11 si se solicita
  • Agrega el usuario a los grupos apropiados si es necesario
  • Inicia Macfleet desde el menú de Aplicaciones
  • La aplicación comienza el seguimiento automáticamente

Nota: Después de la instalación en todos los sistemas, inicia sesión con tus credenciales de Macfleet para sincronizar datos con tu panel de control.