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.

Bluetooth Management on macOS

Control and manage Bluetooth settings across your MacFleet devices using advanced command-line tools. This tutorial covers Bluetooth status monitoring, power state management, and enterprise-grade fleet control with comprehensive logging and security features.

Understanding macOS Bluetooth Management

macOS provides comprehensive Bluetooth control through several mechanisms:

  • defaults - Direct manipulation of Bluetooth preferences via plist files
  • bluetoothd - The core Bluetooth daemon that handles all Bluetooth operations
  • launchctl - Service management for starting/stopping Bluetooth services
  • blued - Legacy Bluetooth daemon name used in older macOS versions

The primary configuration file is located at /Library/Preferences/com.apple.Bluetooth with the ControllerPowerState key controlling the power state.

Basic Bluetooth Status Management

Check Bluetooth Status

#!/bin/bash

# Check current Bluetooth power state
check_bluetooth_status() {
    local status
    status=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    if [[ "$status" == "1" ]]; then
        echo "Bluetooth is ON"
        return 0
    elif [[ "$status" == "0" ]]; then
        echo "Bluetooth is OFF"
        return 1
    else
        echo "Bluetooth status unknown or not configured"
        return 2
    fi
}

# Execute status check
check_bluetooth_status

Turn Bluetooth ON

#!/bin/bash

# Turn Bluetooth ON using defaults and daemon restart
turn_bluetooth_on() {
    echo "Turning Bluetooth ON..."
    
    # Set Bluetooth power state to ON
    sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 1
    
    # Restart Bluetooth daemon (try both modern and legacy daemon names)
    if pgrep bluetoothd >/dev/null 2>&1; then
        sudo killall -HUP bluetoothd
        echo "Bluetooth daemon (bluetoothd) restarted"
    elif pgrep blued >/dev/null 2>&1; then
        sudo killall -HUP blued
        echo "Bluetooth daemon (blued) restarted"
    else
        echo "Warning: Bluetooth daemon not found"
    fi
    
    # Wait for changes to take effect
    sleep 3
    
    # Verify the change
    if check_bluetooth_status >/dev/null; then
        echo "✅ Bluetooth successfully turned ON"
        return 0
    else
        echo "❌ Failed to turn Bluetooth ON"
        return 1
    fi
}

# Helper function for status checking
check_bluetooth_status() {
    local status
    status=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    [[ "$status" == "1" ]]
}

# Execute
turn_bluetooth_on

Turn Bluetooth OFF

#!/bin/bash

# Turn Bluetooth OFF using defaults and daemon restart
turn_bluetooth_off() {
    echo "Turning Bluetooth OFF..."
    
    # Set Bluetooth power state to OFF
    sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 0
    
    # Restart Bluetooth daemon
    if pgrep bluetoothd >/dev/null 2>&1; then
        sudo killall -HUP bluetoothd
        echo "Bluetooth daemon (bluetoothd) restarted"
    elif pgrep blued >/dev/null 2>&1; then
        sudo killall -HUP blued
        echo "Bluetooth daemon (blued) restarted"
    else
        echo "Warning: Bluetooth daemon not found"
    fi
    
    # Wait for changes to take effect
    sleep 3
    
    # Verify the change
    if ! check_bluetooth_status >/dev/null; then
        echo "✅ Bluetooth successfully turned OFF"
        return 0
    else
        echo "❌ Failed to turn Bluetooth OFF"
        return 1
    fi
}

# Helper function for status checking
check_bluetooth_status() {
    local status
    status=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    [[ "$status" == "1" ]]
}

# Execute
turn_bluetooth_off

Advanced Bluetooth Management with launchctl

Using launchctl for Service Management

#!/bin/bash

# Advanced Bluetooth control using launchctl service management
bluetooth_service_control() {
    local action="$1"  # on, off, restart, status
    local daemon_name
    
    # Determine the correct daemon name based on macOS version
    if launchctl list | grep -q "com.apple.bluetoothd"; then
        daemon_name="com.apple.bluetoothd"
    elif launchctl list | grep -q "com.apple.blued"; then
        daemon_name="com.apple.blued"
    else
        echo "❌ Bluetooth daemon not found in launchctl"
        return 1
    fi
    
    case "$action" in
        "on")
            echo "Enabling Bluetooth..."
            sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 1
            sudo launchctl stop "$daemon_name"
            sleep 2
            sudo launchctl start "$daemon_name"
            sleep 3
            echo "✅ Bluetooth enabled using launchctl"
            ;;
        "off")
            echo "Disabling Bluetooth..."
            sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 0
            sudo launchctl stop "$daemon_name"
            sleep 2
            sudo launchctl start "$daemon_name"
            sleep 3
            echo "✅ Bluetooth disabled using launchctl"
            ;;
        "restart")
            echo "Restarting Bluetooth service..."
            sudo launchctl stop "$daemon_name"
            sleep 2
            sudo launchctl start "$daemon_name"
            sleep 3
            echo "✅ Bluetooth service restarted"
            ;;
        "status")
            echo "Bluetooth daemon status: $daemon_name"
            if launchctl list | grep -q "$daemon_name"; then
                echo "✅ Bluetooth service is running"
                
                # Check power state
                local power_state
                power_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
                echo "Power state: $([[ "$power_state" == "1" ]] && echo "ON" || echo "OFF")"
            else
                echo "❌ Bluetooth service is not running"
            fi
            ;;
        *)
            echo "Usage: bluetooth_service_control {on|off|restart|status}"
            return 1
            ;;
    esac
}

# Examples
bluetooth_service_control "status"
# bluetooth_service_control "on"
# bluetooth_service_control "off"
# bluetooth_service_control "restart"

Enterprise Bluetooth Management System

#!/bin/bash

# MacFleet Enterprise Bluetooth Management System
# Comprehensive Bluetooth control with logging, monitoring, and fleet management

# Configuration
LOG_FILE="/var/log/macfleet_bluetooth.log"
CONFIG_FILE="/etc/macfleet/bluetooth_config.conf"
BACKUP_DIR="/var/backups/macfleet/bluetooth"
API_ENDPOINT="https://api.macfleet.com/v1/bluetooth"

# Create directory structure
setup_directories() {
    mkdir -p "$(dirname "$LOG_FILE")" "$BACKUP_DIR" "$(dirname "$CONFIG_FILE")"
    touch "$LOG_FILE"
}

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

# Get detailed Bluetooth information
get_bluetooth_info() {
    local info_json="{"
    
    # Power state
    local power_state
    power_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null || echo "unknown")
    info_json+="\"power_state\": \"$power_state\","
    
    # Daemon status
    local daemon_running=false
    if pgrep bluetoothd >/dev/null 2>&1 || pgrep blued >/dev/null 2>&1; then
        daemon_running=true
    fi
    info_json+="\"daemon_running\": $daemon_running,"
    
    # macOS version
    local macos_version
    macos_version=$(sw_vers -productVersion)
    info_json+="\"macos_version\": \"$macos_version\","
    
    # System hardware
    local hardware_model
    hardware_model=$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F': ' '{print $2}' | xargs)
    info_json+="\"hardware_model\": \"$hardware_model\","
    
    # Bluetooth controller info
    local bt_controller=""
    if system_profiler SPBluetoothDataType >/dev/null 2>&1; then
        bt_controller=$(system_profiler SPBluetoothDataType | grep -A5 "Apple Bluetooth Software" | grep "Version" | awk -F': ' '{print $2}' | xargs)
    fi
    info_json+="\"bluetooth_version\": \"$bt_controller\","
    
    # Timestamp
    info_json+="\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\""
    info_json+="}"
    
    echo "$info_json"
}

# Backup current Bluetooth configuration
backup_bluetooth_config() {
    local backup_file="$BACKUP_DIR/bluetooth_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    if [[ -f "/Library/Preferences/com.apple.Bluetooth.plist" ]]; then
        cp "/Library/Preferences/com.apple.Bluetooth.plist" "$backup_file"
        log_action "Bluetooth configuration backed up to: $backup_file"
        echo "$backup_file"
    else
        log_action "WARNING: Bluetooth preference file not found for backup"
        return 1
    fi
}

# Set Bluetooth state with comprehensive validation
set_bluetooth_state() {
    local desired_state="$1"  # "on" or "off"
    local force_restart="${2:-false}"
    
    # Validate input
    if [[ "$desired_state" != "on" && "$desired_state" != "off" ]]; then
        log_action "ERROR: Invalid state specified. Use 'on' or 'off'"
        return 1
    fi
    
    # Get current state
    local current_state
    current_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    local target_value
    if [[ "$desired_state" == "on" ]]; then
        target_value=1
    else
        target_value=0
    fi
    
    # Check if change is needed
    if [[ "$current_state" == "$target_value" && "$force_restart" == "false" ]]; then
        log_action "Bluetooth already in desired state: $desired_state"
        return 0
    fi
    
    # Create backup before changes
    backup_bluetooth_config
    
    # Set new state
    log_action "Setting Bluetooth state to: $desired_state"
    sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int "$target_value"
    
    # Restart Bluetooth daemon
    restart_bluetooth_daemon
    
    # Wait for changes to propagate
    sleep 5
    
    # Verify the change
    local new_state
    new_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    if [[ "$new_state" == "$target_value" ]]; then
        log_action "✅ Bluetooth successfully set to: $desired_state"
        return 0
    else
        log_action "❌ Failed to set Bluetooth to: $desired_state"
        return 1
    fi
}

# Restart Bluetooth daemon with error handling
restart_bluetooth_daemon() {
    log_action "Restarting Bluetooth daemon..."
    
    # Try modern bluetoothd first
    if pgrep bluetoothd >/dev/null 2>&1; then
        if sudo killall -HUP bluetoothd 2>/dev/null; then
            log_action "Bluetooth daemon (bluetoothd) restarted successfully"
            return 0
        else
            log_action "WARNING: Failed to restart bluetoothd with HUP signal"
        fi
    fi
    
    # Try legacy blued
    if pgrep blued >/dev/null 2>&1; then
        if sudo killall -HUP blued 2>/dev/null; then
            log_action "Bluetooth daemon (blued) restarted successfully"
            return 0
        else
            log_action "WARNING: Failed to restart blued with HUP signal"
        fi
    fi
    
    # Try launchctl approach
    local daemon_service=""
    if launchctl list | grep -q "com.apple.bluetoothd"; then
        daemon_service="com.apple.bluetoothd"
    elif launchctl list | grep -q "com.apple.blued"; then
        daemon_service="com.apple.blued"
    fi
    
    if [[ -n "$daemon_service" ]]; then
        log_action "Attempting launchctl restart for: $daemon_service"
        sudo launchctl stop "$daemon_service" 2>/dev/null
        sleep 2
        sudo launchctl start "$daemon_service" 2>/dev/null
        log_action "Bluetooth service restarted via launchctl"
        return 0
    fi
    
    log_action "ERROR: Could not restart Bluetooth daemon"
    return 1
}

# Monitor Bluetooth connectivity and paired devices
monitor_bluetooth_devices() {
    log_action "Starting Bluetooth device monitoring..."
    
    # Get current power state
    local power_state
    power_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    if [[ "$power_state" != "1" ]]; then
        log_action "Bluetooth is OFF - no devices to monitor"
        return 0
    fi
    
    # Check for system_profiler availability
    if ! command -v system_profiler >/dev/null 2>&1; then
        log_action "WARNING: system_profiler not available for device monitoring"
        return 1
    fi
    
    # Get Bluetooth device information
    local bt_devices
    bt_devices=$(system_profiler SPBluetoothDataType 2>/dev/null | grep -A10 "Devices:" || echo "No devices found")
    
    log_action "Bluetooth devices status:"
    echo "$bt_devices" | while IFS= read -r line; do
        log_action "  $line"
    done
    
    # Count connected devices
    local connected_count
    connected_count=$(echo "$bt_devices" | grep -c "Connected: Yes" || echo "0")
    log_action "Total connected Bluetooth devices: $connected_count"
    
    return 0
}

# Generate comprehensive Bluetooth report
generate_bluetooth_report() {
    local report_file="/tmp/bluetooth_report_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Generating Bluetooth report: $report_file"
    
    {
        echo "{"
        echo "  \"report_type\": \"bluetooth_status\","
        echo "  \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
        echo "  \"hostname\": \"$(hostname)\","
        echo "  \"device_info\": $(get_bluetooth_info),"
        
        # System information
        echo "  \"system_info\": {"
        echo "    \"macos_version\": \"$(sw_vers -productVersion)\","
        echo "    \"build_version\": \"$(sw_vers -buildVersion)\","
        echo "    \"hardware_uuid\": \"$(system_profiler SPHardwareDataType | grep 'Hardware UUID' | awk -F': ' '{print $2}' | xargs)\""
        echo "  },"
        
        # Bluetooth preferences
        echo "  \"bluetooth_preferences\": {"
        if [[ -f "/Library/Preferences/com.apple.Bluetooth.plist" ]]; then
            echo "    \"preferences_file_exists\": true,"
            echo "    \"file_size\": $(stat -f%z "/Library/Preferences/com.apple.Bluetooth.plist"),"
            echo "    \"last_modified\": \"$(stat -f%Sm -t%Y-%m-%dT%H:%M:%SZ "/Library/Preferences/com.apple.Bluetooth.plist")\""
        else
            echo "    \"preferences_file_exists\": false"
        fi
        echo "  }"
        echo "}"
    } > "$report_file"
    
    log_action "Bluetooth report generated successfully"
    echo "$report_file"
}

# Security compliance check
check_bluetooth_security() {
    log_action "Performing Bluetooth security compliance check..."
    
    local security_issues=()
    
    # Check if Bluetooth is enabled when it should be disabled
    if [[ -f "$CONFIG_FILE" ]] && grep -q "BLUETOOTH_POLICY=disabled" "$CONFIG_FILE"; then
        local current_state
        current_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
        
        if [[ "$current_state" == "1" ]]; then
            security_issues+=("Bluetooth enabled despite policy requiring disabled state")
        fi
    fi
    
    # Check for Bluetooth discoverability (if system_profiler available)
    if command -v system_profiler >/dev/null 2>&1; then
        local discoverable
        discoverable=$(system_profiler SPBluetoothDataType 2>/dev/null | grep -i "discoverable" || echo "unknown")
        
        if echo "$discoverable" | grep -qi "yes"; then
            security_issues+=("Bluetooth is discoverable - potential security risk")
        fi
    fi
    
    # Report security status
    if [[ ${#security_issues[@]} -eq 0 ]]; then
        log_action "✅ Bluetooth security compliance check passed"
        return 0
    else
        log_action "⚠️  Bluetooth security issues found:"
        for issue in "${security_issues[@]}"; do
            log_action "  - $issue"
        done
        return 1
    fi
}

# Main management function
main() {
    local action="${1:-status}"
    local parameter="$2"
    
    setup_directories
    log_action "MacFleet Bluetooth Management started with action: $action"
    
    case "$action" in
        "on"|"enable")
            set_bluetooth_state "on"
            ;;
        "off"|"disable")
            set_bluetooth_state "off"
            ;;
        "restart"|"reload")
            restart_bluetooth_daemon
            ;;
        "status"|"info")
            get_bluetooth_info | python3 -m json.tool 2>/dev/null || get_bluetooth_info
            ;;
        "monitor")
            monitor_bluetooth_devices
            ;;
        "report")
            generate_bluetooth_report
            ;;
        "security")
            check_bluetooth_security
            ;;
        "backup")
            backup_bluetooth_config
            ;;
        "force-on")
            set_bluetooth_state "on" true
            ;;
        "force-off")
            set_bluetooth_state "off" true
            ;;
        *)
            echo "Usage: $0 {on|off|restart|status|monitor|report|security|backup|force-on|force-off}"
            echo ""
            echo "Commands:"
            echo "  on/enable    - Turn Bluetooth ON"
            echo "  off/disable  - Turn Bluetooth OFF"
            echo "  restart      - Restart Bluetooth daemon"
            echo "  status       - Show detailed Bluetooth status"
            echo "  monitor      - Monitor connected devices"
            echo "  report       - Generate comprehensive report"
            echo "  security     - Run security compliance check"
            echo "  backup       - Backup current configuration"
            echo "  force-on     - Force Bluetooth ON (restart daemon)"
            echo "  force-off    - Force Bluetooth OFF (restart daemon)"
            exit 1
            ;;
    esac
    
    log_action "MacFleet Bluetooth Management completed with action: $action"
}

# Execute main function with all arguments
main "$@"

Quick Management Functions

Simple Status Check

#!/bin/bash

# Quick Bluetooth status check with color output
bluetooth_quick_status() {
    local status
    status=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    case "$status" in
        "1")
            echo "🔵 Bluetooth: ON"
            ;;
        "0")
            echo "⚪ Bluetooth: OFF"
            ;;
        *)
            echo "❓ Bluetooth: UNKNOWN"
            ;;
    esac
}

bluetooth_quick_status

Toggle Bluetooth State

#!/bin/bash

# Toggle Bluetooth between ON and OFF states
toggle_bluetooth() {
    local current_state
    current_state=$(defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState 2>/dev/null)
    
    if [[ "$current_state" == "1" ]]; then
        echo "Bluetooth is ON, turning OFF..."
        sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 0
        sudo killall -HUP bluetoothd 2>/dev/null || sudo killall -HUP blued 2>/dev/null
        echo "✅ Bluetooth turned OFF"
    else
        echo "Bluetooth is OFF, turning ON..."
        sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 1
        sudo killall -HUP bluetoothd 2>/dev/null || sudo killall -HUP blued 2>/dev/null
        echo "✅ Bluetooth turned ON"
    fi
}

toggle_bluetooth

Configuration Templates

Bluetooth Policy Configuration

# /etc/macfleet/bluetooth_config.conf
# MacFleet Bluetooth Management Configuration

# Policy settings
BLUETOOTH_POLICY="enabled"  # enabled, disabled, user_controlled
AUTO_DISABLE_ON_IDLE="false"
IDLE_TIMEOUT_MINUTES="30"

# Security settings
ALLOW_DISCOVERABLE="false"
REQUIRE_PAIRING_CONFIRMATION="true"
LOG_DEVICE_CONNECTIONS="true"

# Monitoring settings
MONITOR_INTERVAL_SECONDS="300"
ALERT_ON_NEW_DEVICES="true"
COMPLIANCE_CHECK_ENABLED="true"

# Backup settings
AUTO_BACKUP_ENABLED="true"
BACKUP_RETENTION_DAYS="30"

Troubleshooting Common Issues

Bluetooth Daemon Not Responding

#!/bin/bash

# Troubleshoot and fix Bluetooth daemon issues
fix_bluetooth_daemon() {
    echo "Diagnosing Bluetooth daemon issues..."
    
    # Check if daemon is running
    if ! pgrep bluetoothd >/dev/null 2>&1 && ! pgrep blued >/dev/null 2>&1; then
        echo "❌ No Bluetooth daemon found running"
        
        # Try to start via launchctl
        if launchctl list | grep -q "com.apple.bluetoothd"; then
            echo "Starting bluetoothd via launchctl..."
            sudo launchctl start com.apple.bluetoothd
        elif launchctl list | grep -q "com.apple.blued"; then
            echo "Starting blued via launchctl..."
            sudo launchctl start com.apple.blued
        else
            echo "❌ Bluetooth service not found in launchctl"
            return 1
        fi
    fi
    
    # Force restart if still having issues
    echo "Force restarting Bluetooth system..."
    sudo pkill -f bluetooth
    sleep 3
    
    # Restart via launchctl
    for service in "com.apple.bluetoothd" "com.apple.blued"; do
        if launchctl list | grep -q "$service"; then
            sudo launchctl stop "$service" 2>/dev/null
            sleep 2
            sudo launchctl start "$service" 2>/dev/null
            echo "Restarted service: $service"
        fi
    done
    
    # Verify recovery
    sleep 5
    if pgrep bluetoothd >/dev/null 2>&1 || pgrep blued >/dev/null 2>&1; then
        echo "✅ Bluetooth daemon recovery successful"
        return 0
    else
        echo "❌ Bluetooth daemon recovery failed"
        return 1
    fi
}

fix_bluetooth_daemon

Reset Bluetooth Configuration

#!/bin/bash

# Reset Bluetooth to factory defaults
reset_bluetooth_config() {
    echo "⚠️  Resetting Bluetooth configuration to defaults..."
    
    # Create backup
    if [[ -f "/Library/Preferences/com.apple.Bluetooth.plist" ]]; then
        cp "/Library/Preferences/com.apple.Bluetooth.plist" "/tmp/bluetooth_backup_$(date +%s).plist"
        echo "Backup created in /tmp/"
    fi
    
    # Stop Bluetooth services
    sudo launchctl stop com.apple.bluetoothd 2>/dev/null
    sudo launchctl stop com.apple.blued 2>/dev/null
    
    # Remove configuration files
    sudo rm -f "/Library/Preferences/com.apple.Bluetooth.plist"
    sudo rm -f "/Library/Preferences/ByHost/com.apple.Bluetooth.*.plist"
    
    # Restart services
    sudo launchctl start com.apple.bluetoothd 2>/dev/null
    sudo launchctl start com.apple.blued 2>/dev/null
    
    # Set default state
    sleep 3
    sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -int 1
    sudo killall -HUP bluetoothd 2>/dev/null || sudo killall -HUP blued 2>/dev/null
    
    echo "✅ Bluetooth configuration reset completed"
}

# Uncomment to execute
# reset_bluetooth_config

Important Technical Notes

Daemon Management

  • bluetoothd: Modern Bluetooth daemon (macOS 10.10+)
  • blued: Legacy Bluetooth daemon (older macOS versions)
  • killall -HUP: Sends hangup signal to restart daemon gracefully
  • launchctl: Preferred method for service management

Configuration Details

  • File Location: /Library/Preferences/com.apple.Bluetooth
  • Power State Key: ControllerPowerState
  • Values: 1 (ON), 0 (OFF)
  • Persistence: Changes persist across reboots

Security Considerations

  1. Administrative Privileges: All Bluetooth modifications require sudo
  2. Daemon Restart: Changes only take effect after daemon restart
  3. User Impact: Turning off Bluetooth disconnects all paired devices
  4. Policy Compliance: Monitor for unauthorized Bluetooth changes

Best Practices

  1. Always backup configurations before making changes
  2. Test daemon restart methods for your macOS version
  3. Monitor for delays - daemon restart can take several seconds
  4. Implement logging for audit trails and troubleshooting
  5. Use launchctl for more reliable service management
  6. Validate changes after applying modifications
  7. Consider user impact when disabling Bluetooth remotely
  8. Test scripts thoroughly before fleet deployment

Remember to validate all scripts on test devices before deploying across your MacFleet environment, and be aware that Bluetooth changes may take a few minutes to fully propagate through the system.

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.