Skip to content

Instantly share code, notes, and snippets.

@darkn3rd
Last active January 12, 2023 05:25
Show Gist options
  • Save darkn3rd/608449fe760e855e4d0c9715c74bcf7b to your computer and use it in GitHub Desktop.
Save darkn3rd/608449fe760e855e4d0c9715c74bcf7b to your computer and use it in GitHub Desktop.
Mac OS X Prepare ISO

Prepare ISO Notes

These are notes on this process to prepare an install CD so that you can create a virtual Mac OS X. This is useful for testing scripts.

Prepare ISO Script

#!/bin/sh -e
#
# Preparation script for an OS X automated installation for use with VeeWee/Packer/Vagrant
# 
# What the script does, in more detail:
# 
# 1. Mounts the InstallESD.dmg using a shadow file, so the original DMG is left
#    unchanged.
# 2. Modifies the BaseSystem.dmg within in order to add an additional 'rc.cdrom.local'
#    file in /etc, which is a supported local configuration sourced in at boot time
#    by the installer environment. This file contains instructions to erase and format
#    'disk0', presumably the hard disk attached to the VM.
# 3. A 'veewee-config.pkg' installer package is built, which is added to the OS X
#    install by way of the OSInstall.collection file. This package creates the
#    'vagrant' user, configures sshd and sudoers, and disables setup assistants.
# 4. veewee-config.pkg and the various support utilities are copied, and the disk
#    image is saved to the output path.
#
# Thanks:
# Idea and much of the implementation thanks to Pepijn Bruienne, who's also provided
# some process notes here: https://gist.github.com/4542016. The sample minstallconfig.xml,
# use of OSInstall.collection and readme documentation provided with Greg Neagle's
# createOSXInstallPkg tool also proved very helpful. (http://code.google.com/p/munki/wiki/InstallingOSX)
#
# User creation via package install method also credited to Greg, and made easy with Per
# Olofsson's CreateUserPkg (http://magervalp.github.io/CreateUserPkg)
#
# Antony Blakey for updates to support OS X 10.11:
# https://github.com/timsutton/osx-vm-templates/issues/40

usage() {
	cat <<EOF
Usage:
$(basename "$0") [-upiD] "/path/to/InstallESD.dmg" /path/to/output/directory
$(basename "$0") [-upiD] "/path/to/Install OS X [Name].app" /path/to/output/directory

Description:
Converts an OS X installer to a new image that contains components
used to perform an automated installation. The new image will be named
'OSX_InstallESD_[osversion].dmg.'

Optional switches:
  -u <user>
    Sets the username of the root user, defaults to 'vagrant'.

  -p <password>
    Sets the password of the root user, defaults to 'vagrant'.

  -i <path to image>
    Sets the path of the avatar image for the root user, defaulting to the vagrant icon.

  -D <flag>
    Sets the specified flag. Valid flags are:
      DISABLE_REMOTE_MANAGEMENT
      DISABLE_SCREEN_SHARING
      DISABLE_SIP

EOF
}

cleanup() {
    hdiutil detach -quiet -force "$MNT_ESD" || echo > /dev/null
    hdiutil detach -quiet -force "$MNT_BASE_SYSTEM" || echo > /dev/null
    rm -rf "$MNT_ESD" "$MNT_BASE_SYSTEM" "$BASE_SYSTEM_DMG_RW" "$SHADOW_FILE"
}

trap cleanup EXIT INT TERM


msg_status() {
	echo "\033[0;32m-- $1\033[0m"
}
msg_error() {
	echo "\033[0;31m-- $1\033[0m"
}

render_template() {
  eval "echo \"$(cat "$1")\""
}

if [ $# -eq 0 ]; then
	usage
	exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
SUPPORT_DIR="$SCRIPT_DIR/support"

# Parse the optional command line switches
USER="vagrant"
PASSWORD="vagrant"
IMAGE_PATH="$SUPPORT_DIR/vagrant.jpg"

# Flags
DISABLE_REMOTE_MANAGEMENT=0
DISABLE_SCREEN_SHARING=0
DISABLE_SIP=0

while getopts u:p:i:D: OPT; do
  case "$OPT" in
    u)
      USER="$OPTARG"
      ;;
    p)
      PASSWORD="$OPTARG"
      ;;
    i)
      IMAGE_PATH="$OPTARG"
      ;;
    D)
      if [ x${!OPTARG} = x0 ]; then
        eval $OPTARG=1
      elif [ x${!OPTARG} != x1 ]; then
        msg_error "Unknown flag: ${OPTARG}"
        usage
        exit 1
      fi
      ;;
    \?)
      usage
      exit 1
      ;;
  esac
done

# Remove the switches we parsed above.
shift $(expr $OPTIND - 1)

if [ $(id -u) -ne 0 ]; then
	msg_error "This script must be run as root, as it saves a disk image with ownerships enabled."
	exit 1
fi

ESD="$1"
if [ ! -e "$ESD" ]; then
	msg_error "Input installer image $ESD could not be found! Exiting.."
	exit 1
fi

if [ -d "$ESD" ]; then
	# we might be an install .app
	if [ -e "$ESD/Contents/SharedSupport/InstallESD.dmg" ]; then
		ESD="$ESD/Contents/SharedSupport/InstallESD.dmg"
	else
		msg_error "Can't locate an InstallESD.dmg in this source location $ESD!"
	fi
fi

VEEWEE_DIR="$(cd "$SCRIPT_DIR/../../../"; pwd)"
VEEWEE_UID=$(/usr/bin/stat -f %u "$VEEWEE_DIR")
VEEWEE_GID=$(/usr/bin/stat -f %g "$VEEWEE_DIR")
DEFINITION_DIR="$(cd "$SCRIPT_DIR/.."; pwd)"

if [ "$2" = "" ]; then
    msg_error "Currently an explicit output directory is required as the second argument."
	exit 1
	# The rest is left over from the old prepare_veewee_iso.sh script. Not sure if we
    # should leave in this functionality to automatically locate the veewee directory.
	DEFAULT_ISO_DIR=1
	OLDPWD=$(pwd)
	cd "$SCRIPT_DIR"
	# default to the veewee/iso directory
	if [ ! -d "../../../iso" ]; then
		mkdir "../../../iso"
		chown $VEEWEE_UID:$VEEWEE_GID "../../../iso"
	fi
	OUT_DIR="$(cd "$SCRIPT_DIR"; cd ../../../iso; pwd)"
	cd "$OLDPWD" # Rest of script depends on being in the working directory if we were passed relative paths
else
	OUT_DIR="$2"
fi

if [ ! -d "$OUT_DIR" ]; then
	msg_status "Destination dir $OUT_DIR doesn't exist, creating.."
	mkdir -p "$OUT_DIR"
fi

if [ -e "$ESD.shadow" ]; then
	msg_status "Removing old shadow file.."
	rm "$ESD.shadow"
fi

MNT_ESD=$(/usr/bin/mktemp -d /tmp/veewee-osx-esd.XXXX)
SHADOW_FILE=$(/usr/bin/mktemp /tmp/veewee-osx-shadow.XXXX)
rm "$SHADOW_FILE"
msg_status "Attaching input OS X installer image with shadow file.."
hdiutil attach "$ESD" -mountpoint "$MNT_ESD" -shadow "$SHADOW_FILE" -nobrowse -owners on 
if [ $? -ne 0 ]; then
	[ ! -e "$ESD" ] && msg_error "Could not find $ESD in $(pwd)"
	msg_error "Could not mount $ESD on $MNT_ESD"
	exit 1
fi

msg_status "Mounting BaseSystem.."
BASE_SYSTEM_DMG="$MNT_ESD/BaseSystem.dmg"
MNT_BASE_SYSTEM=$(/usr/bin/mktemp -d /tmp/veewee-osx-basesystem.XXXX)
[ ! -e "$BASE_SYSTEM_DMG" ] && msg_error "Could not find BaseSystem.dmg in $MNT_ESD"
hdiutil attach "$BASE_SYSTEM_DMG" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on
if [ $? -ne 0 ]; then
	msg_error "Could not mount $BASE_SYSTEM_DMG on $MNT_BASE_SYSTEM"
	exit 1
fi
SYSVER_PLIST_PATH="$MNT_BASE_SYSTEM/System/Library/CoreServices/SystemVersion.plist"

DMG_OS_VERS=$(/usr/libexec/PlistBuddy -c 'Print :ProductVersion' "$SYSVER_PLIST_PATH")
DMG_OS_VERS_MAJOR=$(echo $DMG_OS_VERS | awk -F "." '{print $2}')
DMG_OS_VERS_MINOR=$(echo $DMG_OS_VERS | awk -F "." '{print $3}')
DMG_OS_BUILD=$(/usr/libexec/PlistBuddy -c 'Print :ProductBuildVersion' "$SYSVER_PLIST_PATH")
msg_status "OS X version detected: 10.$DMG_OS_VERS_MAJOR.$DMG_OS_VERS_MINOR, build $DMG_OS_BUILD"

OUTPUT_DMG="$OUT_DIR/OSX_InstallESD_${DMG_OS_VERS}_${DMG_OS_BUILD}.dmg"
if [ -e "$OUTPUT_DMG" ]; then
	msg_error "Output file $OUTPUT_DMG already exists! We're not going to overwrite it, exiting.."
	hdiutil detach -force "$MNT_ESD"
	exit 1
fi

# Build our post-installation pkg that will create a user and enable ssh
msg_status "Making firstboot installer pkg.."

# payload items
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users"
mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash"
BASE64_IMAGE=$(openssl base64 -in "$IMAGE_PATH")
# Replace USER and BASE64_IMAGE in the user.plist file with the actual user and image
render_template "$SUPPORT_DIR/user.plist" > "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users/$USER.plist"
USER_GUID=$(/usr/libexec/PlistBuddy -c 'Print :generateduid:0' "$SUPPORT_DIR/user.plist")
# Generate a shadowhash from the supplied password
"$SUPPORT_DIR/generate_shadowhash" "$PASSWORD" > "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash/$USER_GUID"

# postinstall script
mkdir -p "$SUPPORT_DIR/tmp/Scripts"
cat "$SUPPORT_DIR/pkg-postinstall" \
    | sed -e "s/__USER__PLACEHOLDER__/${USER}/" \
    | sed -e "s/__DISABLE_REMOTE_MANAGEMENT__/${DISABLE_REMOTE_MANAGEMENT}/" \
    | sed -e "s/__DISABLE_SCREEN_SHARING__/${DISABLE_SCREEN_SHARING}/" \
    | sed -e "s/__DISABLE_SIP__/${DISABLE_SIP}/" \
    > "$SUPPORT_DIR/tmp/Scripts/postinstall"
chmod a+x "$SUPPORT_DIR/tmp/Scripts/postinstall"

# build it
BUILT_COMPONENT_PKG="$SUPPORT_DIR/tmp/veewee-config-component.pkg"
BUILT_PKG="$SUPPORT_DIR/tmp/veewee-config.pkg"
pkgbuild --quiet \
	--root "$SUPPORT_DIR/pkgroot" \
	--scripts "$SUPPORT_DIR/tmp/Scripts" \
	--identifier com.vagrantup.veewee-config \
	--version 0.1 \
	"$BUILT_COMPONENT_PKG"
productbuild \
	--package "$BUILT_COMPONENT_PKG" \
	"$BUILT_PKG"
rm -rf "$SUPPORT_DIR/pkgroot"

# We'd previously mounted this to check versions
hdiutil detach "$MNT_BASE_SYSTEM"

BASE_SYSTEM_DMG_RW="$(/usr/bin/mktemp /tmp/veewee-osx-basesystem-rw.XXXX).dmg"

msg_status "Creating empty read-write DMG located at $BASE_SYSTEM_DMG_RW.."
hdiutil create -o "$BASE_SYSTEM_DMG_RW" -size 10g -layout SPUD -fs HFS+J
hdiutil attach "$BASE_SYSTEM_DMG_RW" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on

msg_status "Restoring ('asr restore') the BaseSystem to the read-write DMG.."
# This asr restore was needed as of 10.11 DP7 and up. See
# https://github.com/timsutton/osx-vm-templates/issues/40
#
# Note that when the restore completes, the volume is automatically re-mounted
# and not with the '-nobrowse' option. It's an annoyance we could possibly fix
# in the future..
asr restore --source "$BASE_SYSTEM_DMG" --target "$MNT_BASE_SYSTEM" --noprompt --noverify --erase
rm -r "$MNT_BASE_SYSTEM"

if [ $DMG_OS_VERS_MAJOR -ge 9 ]; then
    MNT_BASE_SYSTEM="/Volumes/OS X Base System"
    BASESYSTEM_OUTPUT_IMAGE="$OUTPUT_DMG"
    PACKAGES_DIR="$MNT_BASE_SYSTEM/System/Installation/Packages"

    rm "$PACKAGES_DIR"
	msg_status "Moving 'Packages' directory from the ESD to BaseSystem.."
	mv -v "$MNT_ESD/Packages" "$MNT_BASE_SYSTEM/System/Installation/"

	# This isn't strictly required for Mavericks, but Yosemite will consider the
	# installer corrupt if this isn't included, because it cannot verify BaseSystem's
	# consistency and perform a recovery partition verification
	msg_status "Copying in original BaseSystem dmg and chunklist.."
	cp "$MNT_ESD/BaseSystem.dmg" "$MNT_BASE_SYSTEM/"
	cp "$MNT_ESD/BaseSystem.chunklist" "$MNT_BASE_SYSTEM/"
else
    MNT_BASE_SYSTEM="/Volumes/Mac OS X Base System"
    BASESYSTEM_OUTPUT_IMAGE="$MNT_ESD/BaseSystem.dmg"
    rm "$BASESYSTEM_OUTPUT_IMAGE"
	PACKAGES_DIR="$MNT_ESD/Packages"
fi

msg_status "Adding automated components.."
CDROM_LOCAL="$MNT_BASE_SYSTEM/private/etc/rc.cdrom.local"
cat > $CDROM_LOCAL << EOF
diskutil eraseDisk jhfs+ "Macintosh HD" GPTFormat disk0
if [ "\$?" == "1" ]; then
    diskutil eraseDisk jhfs+ "Macintosh HD" GPTFormat disk1
fi
EOF
chmod a+x "$CDROM_LOCAL"
mkdir "$PACKAGES_DIR/Extras"
cp "$SUPPORT_DIR/minstallconfig.xml" "$PACKAGES_DIR/Extras/"
cp "$SUPPORT_DIR/OSInstall.collection" "$PACKAGES_DIR/"
cp "$BUILT_PKG" "$PACKAGES_DIR/"
rm -rf "$SUPPORT_DIR/tmp"

msg_status "Unmounting BaseSystem.."
hdiutil detach "$MNT_BASE_SYSTEM"

if [ $DMG_OS_VERS_MAJOR -lt 9 ]; then
	msg_status "Pre-Mavericks we save back the modified BaseSystem to the root of the ESD."
	hdiutil convert -format UDZO -o "$MNT_ESD/BaseSystem.dmg" "$BASE_SYSTEM_DMG_RW"
fi

msg_status "Unmounting ESD.."
hdiutil detach "$MNT_ESD"

if [ $DMG_OS_VERS_MAJOR -ge 9 ]; then
	msg_status "On Mavericks and later, the entire modified BaseSystem is our output dmg."
	hdiutil convert -format UDZO -o "$OUTPUT_DMG" "$BASE_SYSTEM_DMG_RW"
else
	msg_status "Pre-Mavericks we're modifying the original ESD file."
	hdiutil convert -format UDZO -o "$OUTPUT_DMG" -shadow "$SHADOW_FILE" "$ESD"
fi
rm -rf "$MNT_ESD" "$SHADOW_FILE"

if [ -n "$SUDO_UID" ] && [ -n "$SUDO_GID" ]; then
	msg_status "Fixing permissions.."
	chown -R $SUDO_UID:$SUDO_GID \
		"$OUT_DIR"
fi

if [ -n "$DEFAULT_ISO_DIR" ]; then
	DEFINITION_FILE="$DEFINITION_DIR/definition.rb"
	msg_status "Setting ISO file in definition $DEFINITION_FILE.."
	ISO_FILE=$(basename "$OUTPUT_DMG")
	# Explicitly use -e in order to use double quotes around sed command
	sed -i -e "s/%OSX_ISO%/${ISO_FILE}/" "$DEFINITION_FILE"
fi

msg_status "Checksumming output image.."
MD5=$(md5 -q "$OUTPUT_DMG")
msg_status "MD5: $MD5"

msg_status "Done. Built image is located at $OUTPUT_DMG. Add this iso and its checksum to your template."

Generate Shadow Hash

#!/usr/bin/php
<?php

#
# shadowHash - script to automate creating MacOS 10.4/10.5 shadow hash files
# 
#
#  usage: shadowHash password
#
#  in most cases you'll want to redirect this to a file with the GUID of the user whose password you 
#   wish to set. i.e. ./shadowHash mypassword>C78F3A60-FC1D-4377-AD7D-DBAD5A6B8B2C
#
#  2008 Pete Akins, Cincinnati, OH . pete.akins@uc.edu

/********************* 

FORMAT OF SHADOW FILE

Offsets and length (hex values)
0-63 NTLM Password (64)
64-103 SHA1 Digest (40)
104-167 CRAM-MD5 (64)
168-215 Salted SHA1 (48, 8+40)
216-1239 Recoverable (1024)

*********************/

if (!isset($argv[1])) {
	fprintf(STDERR, "Enter password: ");
	$password = trim(fgets(STDIN));
} else {
	// get the password as an arg
	$password = $argv[1];
}

if (empty($password)) {
	die("Invalid password");
}

do {
	
/* make sure we get a big random number, but not too big */
$randmax = getrandmax();
$max = pow(2, 31)-1;
if ($max>$randmax) {
	$max = $randmax;
}

/* get our salt integer, and it's hex value */
$salt = rand(1, $max);
$saltHex = decHex($salt);

/* get string representation of bytes */
$saltStr = pack("N", $salt);

/* compute salted hash. get uppercase values */
$sha1_salt = sprintf("%08s%s", strtoupper($saltHex), strtoupper(sha1($saltStr . $password)));

} while (strlen($sha1_salt)!=48); //just in case we have odd ball integers that result in non standard hex.

/* blank out other hashes */
$NTLM = str_repeat("0", 64);
$sha1 = str_repeat("0", 40);
$cram_md5 = str_repeat("0", 64);
$recoverable = str_repeat("0", 1024);

/* put it all together */
$string = $NTLM . $sha1 . $cram_md5 . $sha1_salt . $recoverable;

echo $string;
exit(0);

?>

Package Post-Install

#!/bin/sh
USER="__USER__PLACEHOLDER__"
OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')
PlistBuddy="/usr/libexec/PlistBuddy"

target_ds_node="${3}/private/var/db/dslocal/nodes/Default"
# Override the default behavior of sshd on the target volume to be not disabled
if [ "$OSX_VERS" -ge 10 ]; then
    OVERRIDES_PLIST="$3/private/var/db/com.apple.xpc.launchd/disabled.plist"
    $PlistBuddy -c 'Delete :com.openssh.sshd' "$OVERRIDES_PLIST"
    $PlistBuddy -c 'Add :com.openssh.sshd bool False' "$OVERRIDES_PLIST"
    if [ __DISABLE_SCREEN_SHARING__ = 0 ]; then
        $PlistBuddy -c 'Delete :com.apple.screensharing' "$OVERRIDES_PLIST"
        $PlistBuddy -c 'Add :com.apple.screensharing bool False' "$OVERRIDES_PLIST"
    fi
else
    OVERRIDES_PLIST="$3/private/var/db/launchd.db/com.apple.launchd/overrides.plist"
    $PlistBuddy -c 'Delete :com.openssh.sshd' "$OVERRIDES_PLIST"
    $PlistBuddy -c 'Add :com.openssh.sshd:Disabled bool False' "$OVERRIDES_PLIST"
    if [ __DISABLE_SCREEN_SHARING__ = 0 ]; then
        $PlistBuddy -c 'Delete :com.apple.screensharing' "$OVERRIDES_PLIST"
        $PlistBuddy -c 'Add :com.apple.screensharing:Disabled bool False' "$OVERRIDES_PLIST"
    fi
fi

# Add user to sudoers
cp "$3/etc/sudoers" "$3/etc/sudoers.orig"
echo "$USER ALL=(ALL) NOPASSWD: ALL" >> "$3/etc/sudoers"

# Add user to admin group memberships (even though GID 80 is enough for most things)
USER_GUID=$($PlistBuddy -c 'Print :generateduid:0' "$target_ds_node/users/$USER.plist")
USER_UID=$($PlistBuddy -c 'Print :uid:0' "$target_ds_node/users/$USER.plist")
$PlistBuddy -c 'Add :groupmembers: string '"$USER_GUID" "$target_ds_node/groups/admin.plist"

# Add user to SSH SACL group membership
ssh_group="${target_ds_node}/groups/com.apple.access_ssh.plist"
$PlistBuddy -c 'Add :groupmembers array' "${ssh_group}"
$PlistBuddy -c 'Add :groupmembers:0 string '"$USER_GUID"'' "${ssh_group}"
$PlistBuddy -c 'Add :users array' "${ssh_group}"
$PlistBuddy -c 'Add :users:0 string '$USER'' "${ssh_group}"

# Enable Remote Desktop and configure user with full privileges
if [ __DISABLE_REMOTE_MANAGEMENT__ = 0 ]; then
    echo "enabled" > "$3/private/etc/RemoteManagement.launchd"
    $PlistBuddy -c 'Add :naprivs array' "$target_ds_node/users/$USER.plist"
    $PlistBuddy -c 'Add :naprivs:0 string -1073741569' "$target_ds_node/users/$USER.plist"
fi

if [ __DISABLE_SIP__ = 1 ]; then
    csrutil disable
fi

# Pre-create user folder so veewee will have somewhere to scp configinfo to
mkdir -p "$3/Users/$USER/Library/Preferences"

# Suppress annoying iCloud welcome on a GUI login
$PlistBuddy -c 'Add :DidSeeCloudSetup bool true' "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"
$PlistBuddy -c 'Add :LastSeenCloudProductVersion string 10.'"$OSX_VERS" "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"
$PlistBuddy -c 'Add :DidSeeSiriSetup bool true' "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"

# Fix ownership now that the above has made a Library folder as root
chown -R "$USER_UID":20 "$3/Users/$USER"

# Disable Diagnostics submissions prompt if 10.10
# http://macops.ca/diagnostics-prompt-yosemite
if [ "$OSX_VERS" -ge 10 ]; then
    # Apple's defaults
    SUBMIT_TO_APPLE=YES
    SUBMIT_TO_APP_DEVELOPERS=NO

    CRASHREPORTER_SUPPORT="$3/Library/Application Support/CrashReporter"
    CRASHREPORTER_DIAG_PLIST="${CRASHREPORTER_SUPPORT}/DiagnosticMessagesHistory.plist"
    if [ ! -d "${CRASHREPORTER_SUPPORT}" ]; then
        mkdir "${CRASHREPORTER_SUPPORT}"
        chmod 775 "${CRASHREPORTER_SUPPORT}"
        chown root:admin "${CRASHREPORTER_SUPPORT}"
    fi
    for key in AutoSubmit AutoSubmitVersion ThirdPartyDataSubmit ThirdPartyDataSubmitVersion; do
        $PlistBuddy -c "Delete :$key" "${CRASHREPORTER_DIAG_PLIST}" 2> /dev/null
    done
    $PlistBuddy -c "Add :AutoSubmit bool ${SUBMIT_TO_APPLE}" "${CRASHREPORTER_DIAG_PLIST}"
    $PlistBuddy -c "Add :AutoSubmitVersion integer 4" "${CRASHREPORTER_DIAG_PLIST}"
    $PlistBuddy -c "Add :ThirdPartyDataSubmit bool ${SUBMIT_TO_APP_DEVELOPERS}" "${CRASHREPORTER_DIAG_PLIST}"
    $PlistBuddy -c "Add :ThirdPartyDataSubmitVersion integer 4" "${CRASHREPORTER_DIAG_PLIST}"
fi

# Disable loginwindow screensaver to save CPU cycles
$PlistBuddy -c 'Add :loginWindowIdleTime integer 0' "$3/Library/Preferences/com.apple.screensaver.plist"

# Disable the welcome screen
touch "$3/private/var/db/.AppleSetupDone"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment