diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75e97a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +install/Install macOS*.app +install/packages/*.pkg +install*.dmg diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..1d52fe3 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,11 @@ +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this source code except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..81cf92d --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +## installr + +A bare-bones tool to install macOS and a set of packages on a target volume. +Typically these would be packages that "enroll" the machine into your management system; upon completion of the macOS install these tools would take over and continue the setup and configuration of the machine. + +installr is designed to run in Recovery boot (and also possibly Internet Recovery), allowing you to reinstall a machine for redeployment + +### macOS Installer + +Copy an Install macOS application into the install/ directory. This must be a "full" installer, containing the Contents/Resources/startosinstall tool. + +### Packages + +Add desired packages to the `install/packages` directory. Ensure all packages you add can be properly installed to volumes other than the current boot volume. + +If your packages just have payloads, they should work fine. Pre- and postinstall scripts need to be checked to not use absolute paths to the current startup volume. The installer system passes the target volume in the third argument `$3` to installation scripts. + +### Order + +The startosinstall tool will work through the packages in alphanumerical order. To control the order, you can prefix filenames with numbers. + +#### T2 Macs + +installr is particularly useful with Macs with T2 chips, which do not support NetBoot, and are tricky to get to boot from external media. To use installr to install macOS and additional packages on a T2 Mac, you'd boot into Recovery (Command-R at start up), and mount the installr disk and run installr. + +### Usage scenarios + +#### Scenario #1: USB Thumb drive + +* Preparation: + * Copy the contents of the install directory to a USB Thumb drive. +* Running installr: + * Start up in Recovery mode. + * Connect USB Thumbdrive. + * Open Terminal (from the Utilities menu if in Recovery). + * `/Volumes/VOLUME_NAME/run` (use `sudo` if not in Recovery) + +#### Scenario #2: Disk image via HTTP + +* Preparation: + * Create a disk image using the `make_dmg.sh` script. + * Copy the disk image to a web server. +* Running installr: + * Start up in Recovery mode. + * Open Terminal (from the Utilities menu if in Recovery). + * `hdiutil mount ` + * `/Volumes/install/run` (use `sudo` if not in Recovery) + diff --git a/install/installr.sh b/install/installr.sh new file mode 100755 index 0000000..aa6f517 --- /dev/null +++ b/install/installr.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# installr.sh +# A script to (optionally) erase a volume and install macos and +# additional packagesfound in a packages folder in the same directory +# as this script + +if [[ $EUID != 0 ]] ; then + echo "installr: Please run this as root, or via sudo." + exit -1 +fi + +INDEX=0 +OLDIFS=$IFS +IFS=$'\n' + +# dirname and basename not available in Recovery boot +# so we get to use Bash pattern matching +BASENAME=${0##*/} +THISDIR=${0%$BASENAME} +PACKAGESDIR="${THISDIR}packages" +INSTALLMACOSAPP=$(echo "${THISDIR}Install macOS"*.app) +STARTOSINSTALL=$(echo "${THISDIR}Install macOS"*.app/Contents/Resources/startosinstall) + +if [ ! -e "$STARTOSINSTALL" ]; then + echo "Can't find an Install macOS app containing startosinstall in this script's directory!" + exit -1 +fi + +echo "****** Welcome to installr! ******" +echo "macOS will be installed from:" +echo " ${INSTALLMACOSAPP}" +echo "these additional packages will also be installed:" +for PKG in $(/bin/ls -1 "${PACKAGESDIR}"/*.pkg); do + echo " ${PKG}" +done +echo +echo "Available volumes:" +for VOL in $(/bin/ls -1 /Volumes) ; do + if [[ "${VOL}" != "OS X Base System" ]] ; then + let INDEX=${INDEX}+1 + VOLUMES[${INDEX}]=${VOL} + echo " ${INDEX} ${VOL}" + fi +done +read -p "Install to volume # (1-${INDEX}): " SELECTEDINDEX + +SELECTEDVOLUME=${VOLUMES[${SELECTEDINDEX}]} + +if [[ "${SELECTEDVOLUME}" == "" ]]; then + exit 0 +fi + +read -p "Erase target volume before install (y/N)? " ERASETARGET + +case ${ERASETARGET:0:1} in + [yY] ) /usr/sbin/diskutil reformat "/Volumes/${SELECTEDVOLUME}" ;; + * ) echo ;; +esac + +echo +echo "Installing macOS to /Volumes/${SELECTEDVOLUME}..." + +# build our startosinstall command +CMD="\"${STARTOSINSTALL}\" --agreetolicense --volume \"/Volumes/${SELECTEDVOLUME}\"" + +for ITEM in "${PACKAGESDIR}"/* ; do + FILENAME="${ITEM##*/}" + EXTENSION="${FILENAME##*.}" + if [[ -e ${ITEM} ]]; then + case ${EXTENSION} in + pkg ) CMD="${CMD} --installpackage \"${ITEM}\"" ;; + * ) echo " ignoring non-package ${ITEM}..." ;; + esac + fi +done + +# kick off the OS install +eval $CMD + diff --git a/install/packages/README.txt b/install/packages/README.txt new file mode 100644 index 0000000..050154e --- /dev/null +++ b/install/packages/README.txt @@ -0,0 +1 @@ +Put packages in this directory. Names must end in ".pkg". \ No newline at end of file diff --git a/install/run b/install/run new file mode 120000 index 0000000..7a2bc8b --- /dev/null +++ b/install/run @@ -0,0 +1 @@ +installr.sh \ No newline at end of file diff --git a/make_dmg.sh b/make_dmg.sh new file mode 100755 index 0000000..757212a --- /dev/null +++ b/make_dmg.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Builds a disk image containing installr and packages. + +THISDIR=$(/usr/bin/dirname ${0}) +DMGNAME="${THISDIR}/installr.dmg" +if [[ -e "${DMGNAME}" ]] ; then + /bin/rm "${DMGNAME}" +fi +/usr/bin/hdiutil create -fs HFS+ -srcfolder "${THISDIR}/install" "${DMGNAME}" \ No newline at end of file