├── .gitignore
├── prepare_iso
├── support
│ ├── vagrant.jpg
│ ├── OSInstall.collection
│ ├── minstallconfig.xml
│ ├── user.plist
│ ├── generate_shadowhash
│ └── pkg-postinstall
└── prepare_iso.sh
├── scripts
├── system-update.sh
├── autologin.sh
├── chef-omnibus.sh
├── shrink.sh
├── parallels.sh
├── vagrant.sh
├── add-network-interface-detection.sh
├── vmware.sh
├── support
│ └── set_kcpassword.py
├── post-install.sh
├── xcode-cli-tools.sh
└── puppet.sh
├── LICENSE.md
├── README.md
├── vagrant.json
└── standalone.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | packer_cache
3 | *.dmg
4 | *.box
5 | AutoPartition-*
6 | packer/output-*
7 | *.pvm
8 |
--------------------------------------------------------------------------------
/prepare_iso/support/vagrant.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nickcharlton/packer-macos/HEAD/prepare_iso/support/vagrant.jpg
--------------------------------------------------------------------------------
/scripts/system-update.sh:
--------------------------------------------------------------------------------
1 | if [ "$UPDATE_SYSTEM" != "true" ] && [ "$UPDATE_SYSTEM" != "1" ]; then
2 | exit
3 | fi
4 |
5 | echo "Downloading and installing system updates..."
6 | softwareupdate -i -a
7 |
--------------------------------------------------------------------------------
/scripts/autologin.sh:
--------------------------------------------------------------------------------
1 | if [ "$AUTOLOGIN" != "true" ] && [ "$AUTOLOGIN" != "1" ]; then
2 | exit
3 | fi
4 |
5 | echo "Enabling automatic GUI login for the '$USERNAME' user.."
6 |
7 | python /private/tmp/set_kcpassword.py "$PASSWORD"
8 |
9 | /usr/bin/defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser "$USERNAME"
10 |
--------------------------------------------------------------------------------
/scripts/chef-omnibus.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ "${CHEF_VERSION}" == "none" ]; then
4 | exit
5 | fi
6 |
7 | INSTALL_ARGS=""
8 |
9 | if [ "${CHEF_VERSION}" != "latest" ]; then
10 | INSTALL_ARGS="-v ${CHEF_VERSION}"
11 | fi
12 |
13 | curl -LO https://www.chef.io/chef/install.sh
14 | chmod +x ./install.sh
15 | ./install.sh "${INSTALL_ARGS}"
16 | rm install.sh
17 |
--------------------------------------------------------------------------------
/prepare_iso/support/OSInstall.collection:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | /System/Installation/Packages/OSInstall.mpkg
6 | /System/Installation/Packages/OSInstall.mpkg
7 | /System/Installation/Packages/veewee-config.pkg
8 |
9 |
10 |
--------------------------------------------------------------------------------
/prepare_iso/support/minstallconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | InstallType
6 | automated
7 | Language
8 | en
9 | Package
10 | /System/Installation/Packages/OSInstall.collection
11 | Target
12 | /Volumes/Macintosh HD
13 | TargetName
14 | Macintosh HD
15 |
16 |
17 |
--------------------------------------------------------------------------------
/scripts/shrink.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')
4 |
5 | # Turn off hibernation and get rid of the sleepimage
6 | pmset hibernatemode 0
7 | rm -f /var/vm/sleepimage
8 |
9 | # Stop the pager process and drop swap files. These will be re-created on boot.
10 | # Starting with El Cap we can only stop the dynamic pager if SIP is disabled.
11 | if [ "$OSX_VERS" -lt 11 ] || $(csrutil status | grep -q disabled); then
12 | launchctl unload /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist
13 | sleep 5
14 | fi
15 | rm -rf /private/var/vm/swap*
16 |
17 | # VMware Fusion specific items
18 | if [ -e .vmfusion_version ] || [[ "$PACKER_BUILDER_TYPE" == vmware* ]]; then
19 | # Shrink the disk
20 | /Library/Application\ Support/VMware\ Tools/vmware-tools-cli disk shrink /
21 | fi
22 |
--------------------------------------------------------------------------------
/scripts/parallels.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -eo pipefail
4 |
5 | TOOLS_PATH="/Users/$USERNAME/prl-tools-mac.iso"
6 | # Parallels Tools specific items
7 | if [ -e .PACKER_BUILDER_TYPE ] || [[ "$PACKER_BUILDER_TYPE" == parallels* ]]; then
8 | if [ ! -e "$TOOLS_PATH" ]; then
9 | echo "Couldn't locate uploaded tools iso at $TOOLS_PATH!"
10 | exit 1
11 | fi
12 |
13 | TMPMOUNT=`/usr/bin/mktemp -d /tmp/parallels-tools.XXXX`
14 | hdiutil attach "$TOOLS_PATH" -mountpoint "$TMPMOUNT"
15 |
16 | INSTALLER_PKG="$TMPMOUNT/Install.app/Contents/Resources/Install.mpkg"
17 | if [ ! -e "$INSTALLER_PKG" ]; then
18 | echo "Couldn't locate Parallels Tools installer pkg at $INSTALLER_PKG!"
19 | exit 1
20 | fi
21 |
22 | echo "Installing Parallels Tools..."
23 | installer -pkg "$INSTALLER_PKG" -target /
24 |
25 | # This usually fails
26 | hdiutil detach "$TMPMOUNT"
27 | rm -rf "$TMPMOUNT"
28 | rm -f "$TOOLS_PATH"
29 | fi
30 |
--------------------------------------------------------------------------------
/scripts/vagrant.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | date > /etc/box_build_time
3 | OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')
4 |
5 | # Set computer/hostname
6 | COMPNAME=osx-10_${OSX_VERS}
7 | scutil --set ComputerName ${COMPNAME}
8 | scutil --set HostName ${COMPNAME}.vagrantup.com
9 |
10 | # Packer passes boolean user variables through as '1', but this might change in
11 | # the future, so also check for 'true'.
12 | if [ "$INSTALL_VAGRANT_KEYS" = "true" ] || [ "$INSTALL_VAGRANT_KEYS" = "1" ]; then
13 | echo "Installing vagrant keys for $USERNAME user"
14 | mkdir "/Users/$USERNAME/.ssh"
15 | chmod 700 "/Users/$USERNAME/.ssh"
16 | curl -L 'https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub' > "/Users/$USERNAME/.ssh/authorized_keys"
17 | chmod 600 "/Users/$USERNAME/.ssh/authorized_keys"
18 | chown -R "$USERNAME" "/Users/$USERNAME/.ssh"
19 | fi
20 |
21 | # Create a group and assign the user to it
22 | dseditgroup -o create "$USERNAME"
23 | dseditgroup -o edit -a "$USERNAME" "$USERNAME"
24 |
--------------------------------------------------------------------------------
/prepare_iso/support/user.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | authentication_authority
6 |
7 | ;ShadowHash;
8 |
9 | generateduid
10 |
11 | 11112222-3333-4444-AAAA-BBBBCCCCDDDD
12 |
13 | gid
14 |
15 | 20
16 |
17 | home
18 |
19 | /Users/${USER}
20 |
21 | jpegphoto
22 |
23 |
24 | ${BASE64_IMAGE}
25 |
26 |
27 | name
28 |
29 | ${USER}
30 |
31 | passwd
32 |
33 | ********
34 |
35 | realname
36 |
37 | ${USER}
38 |
39 | shell
40 |
41 | /bin/bash
42 |
43 | uid
44 |
45 | 501
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/scripts/add-network-interface-detection.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This script adds a Mac OS Launch Daemon, which runs every time the
4 | # machine is booted. The daemon will re-detect the attached network
5 | # interfaces. If this is not done, network devices may not work.
6 | PLIST=/Library/LaunchDaemons/com.github.timsutton.osx-vm-templates.detectnewhardware.plist
7 | cat < "${PLIST}"
8 |
9 |
10 |
11 |
12 | Label
13 | com.github.timsutton.osx-vm-templates.detectnewhardware
14 | ProgramArguments
15 |
16 | /usr/sbin/networksetup
17 | -detectnewhardware
18 |
19 | RunAtLoad
20 |
21 |
22 |
23 | EOF
24 |
25 | # These should be already set as follows, but since they're required
26 | # in order to load properly, we set them explicitly.
27 | /bin/chmod 644 "${PLIST}"
28 | /usr/sbin/chown root:wheel "${PLIST}"
29 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-2015 Timothy Sutton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/scripts/vmware.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | TOOLS_PATH="/Users/$USERNAME/darwin.iso"
4 | # VMware Fusion specific items
5 | if [ -e .vmfusion_version ] || [[ "$PACKER_BUILDER_TYPE" == vmware* ]]; then
6 | if [ ! -e "$TOOLS_PATH" ]; then
7 | echo "Couldn't locate uploaded tools iso at $TOOLS_PATH!"
8 | exit 1
9 | fi
10 |
11 | TMPMOUNT=`/usr/bin/mktemp -d /tmp/vmware-tools.XXXX`
12 | hdiutil attach "$TOOLS_PATH" -mountpoint "$TMPMOUNT"
13 |
14 | INSTALLER_PKG="$TMPMOUNT/Install VMware Tools.app/Contents/Resources/VMware Tools.pkg"
15 | if [ ! -e "$INSTALLER_PKG" ]; then
16 | echo "Couldn't locate VMware installer pkg at $INSTALLER_PKG!"
17 | exit 1
18 | fi
19 |
20 | echo "Installing VMware tools.."
21 | installer -pkg "$TMPMOUNT/Install VMware Tools.app/Contents/Resources/VMware Tools.pkg" -target /
22 |
23 | # This usually fails
24 | hdiutil detach "$TMPMOUNT"
25 | rm -rf "$TMPMOUNT"
26 | rm -f "$TOOLS_PATH"
27 |
28 | # Point Linux shared folder root to that used by OS X guests,
29 | # useful for the Hashicorp vmware_fusion Vagrant provider plugin
30 | mkdir /mnt
31 | ln -sf /Volumes/VMware\ Shared\ Folders /mnt/hgfs
32 | fi
33 |
--------------------------------------------------------------------------------
/scripts/support/set_kcpassword.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Port of Gavin Brock's Perl kcpassword generator to Python, by Tom Taylor
4 | # .
5 | # Perl version: http://www.brock-family.org/gavin/perl/kcpassword.html
6 |
7 | import sys
8 | import os
9 |
10 |
11 | def kcpassword(passwd):
12 | # The magic 11 bytes - these are just repeated
13 | # 0x7D 0x89 0x52 0x23 0xD2 0xBC 0xDD 0xEA 0xA3 0xB9 0x1F
14 | key = [125, 137, 82, 35, 210, 188, 221, 234, 163, 185, 31]
15 | key_len = len(key)
16 |
17 | passwd = [ord(x) for x in list(passwd)]
18 | # pad passwd length out to an even multiple of key length
19 | r = len(passwd) % key_len
20 | if (r > 0):
21 | passwd = passwd + [0] * (key_len - r)
22 |
23 | for n in range(0, len(passwd), len(key)):
24 | ki = 0
25 | for j in range(n, min(n+len(key), len(passwd))):
26 | passwd[j] = passwd[j] ^ key[ki]
27 | ki += 1
28 |
29 | passwd = [chr(x) for x in passwd]
30 | return "".join(passwd)
31 |
32 | if __name__ == "__main__":
33 | passwd = kcpassword(sys.argv[1])
34 | fd = os.open('/etc/kcpassword', os.O_WRONLY | os.O_CREAT, 0o600)
35 | file = os.fdopen(fd, 'w')
36 | file.write(passwd)
37 | file.close()
38 |
--------------------------------------------------------------------------------
/scripts/post-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "Adding default SSH key for $USERNAME user.."
4 | mkdir -p "/Users/$USERNAME/.ssh"
5 |
6 | cat << EOF > "/Users/$USERNAME/.ssh/authorized_keys"
7 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDY/apwGMmA6ZBnN7ezuNlpEhCmET1bkuyy1oKNo4/xDCyE2i8KAKBrSzKOGnjNNCtcQmVcslfJBizY0atX2o19WauZtgbNSsT8qCqqHZ3ha9riJW7ypxLh2wpTtFMfc78Sna+yA/ErWuQNMgKOFW7KU5S+sXtls1IfXloDSRm+q7GhmuwjLlN4Mk8y43mhyFe0ZO+NY09Xmc1yyy5w1urJuykFs6zcUkjQ5l3H5ZBPGJjDJ6KHXYsEcE6zDaa+4lZiWb7MaamU37W0Zm/ntIQUzDEP/XPOAC0NTdAsXI1dSltVX6NCLFUO9qHSSv9N9wPECuimJUt4wyYU4P1e//o5Gq0EIpNpiswEaJtlc9f0AEyzuQLdWYwtLW+ncIdK2Bm2nVCBYvBqQ2bB9cMdShVTEvTAlnSb3tavETxPTjXBefQaugsPeV67eEQhmeWValnQIcLtjd2JnktVHLw3bdH4cIUKsauE07TQzdkTyWRs9eyygz0kNMTtCq/wcMMuTGDv0Yhrc4lFNZ9OeHPmuMpx5CbnPhexaUXjqJq+KjLkBJ3DeWkS3anbYoK7UJrEQYYWPQjZcPj3vLHu4n1preO3uZ0fcrgtlwato20n83+sn0ieOgBz6t+jqekRyUFLCe/A401vUUlflGAm3N4UvbZfiLKq3qk2EPkKL+p4cC2ZPw==
8 | EOF
9 |
10 | chmod 700 "/Users/$USERNAME/.ssh"
11 | chmod 600 "/Users/$USERNAME/.ssh/authorized_keys"
12 | chown -R "$USERNAME" "/Users/$USERNAME/.ssh"
13 |
14 | echo "Enabling password-less sudo..."
15 | mkdir -p /etc/sudoers.d
16 |
17 | cat << EOF > /etc/sudoers.d/password_less
18 | ALL ALL = (ALL) NOPASSWD: ALL
19 | EOF
20 |
21 | chmod 440 /etc/sudoers.d/password_less
22 |
23 | echo "Creating a group for the user..."
24 | dseditgroup -o create "$USERNAME"
25 | dseditgroup -o edit -a "$USERNAME" "$USERNAME"
26 |
--------------------------------------------------------------------------------
/prepare_iso/support/generate_shadowhash:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | C78F3A60-FC1D-4377-AD7D-DBAD5A6B8B2C
12 | #
13 | # 2008 Pete Akins, Cincinnati, OH . pete.akins@uc.edu
14 |
15 | /*********************
16 |
17 | FORMAT OF SHADOW FILE
18 |
19 | Offsets and length (hex values)
20 | 0-63 NTLM Password (64)
21 | 64-103 SHA1 Digest (40)
22 | 104-167 CRAM-MD5 (64)
23 | 168-215 Salted SHA1 (48, 8+40)
24 | 216-1239 Recoverable (1024)
25 |
26 | *********************/
27 |
28 | if (!isset($argv[1])) {
29 | fprintf(STDERR, "Enter password: ");
30 | $password = trim(fgets(STDIN));
31 | } else {
32 | // get the password as an arg
33 | $password = $argv[1];
34 | }
35 |
36 | if (empty($password)) {
37 | die("Invalid password");
38 | }
39 |
40 | do {
41 |
42 | /* make sure we get a big random number, but not too big */
43 | $randmax = getrandmax();
44 | $max = pow(2, 31)-1;
45 | if ($max>$randmax) {
46 | $max = $randmax;
47 | }
48 |
49 | /* get our salt integer, and it's hex value */
50 | $salt = rand(1, $max);
51 | $saltHex = decHex($salt);
52 |
53 | /* get string representation of bytes */
54 | $saltStr = pack("N", $salt);
55 |
56 | /* compute salted hash. get uppercase values */
57 | $sha1_salt = sprintf("%08s%s", strtoupper($saltHex), strtoupper(sha1($saltStr . $password)));
58 |
59 | } while (strlen($sha1_salt)!=48); //just in case we have odd ball integers that result in non standard hex.
60 |
61 | /* blank out other hashes */
62 | $NTLM = str_repeat("0", 64);
63 | $sha1 = str_repeat("0", 40);
64 | $cram_md5 = str_repeat("0", 64);
65 | $recoverable = str_repeat("0", 1024);
66 |
67 | /* put it all together */
68 | $string = $NTLM . $sha1 . $cram_md5 . $sha1_salt . $recoverable;
69 |
70 | echo $string;
71 | exit(0);
72 |
73 | ?>
--------------------------------------------------------------------------------
/scripts/xcode-cli-tools.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if [[ ! "$INSTALL_XCODE_CLI_TOOLS" =~ ^(true|yes|on|1|TRUE|YES|ON])$ ]]; then
4 | exit
5 | fi
6 |
7 | # Get and install Xcode CLI tools
8 | OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')
9 |
10 | # on 10.9+, we can leverage SUS to get the latest CLI tools
11 | if [ "$OSX_VERS" -ge 9 ]; then
12 | # create the placeholder file that's checked by CLI updates' .dist code
13 | # in Apple's SUS catalog
14 | touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
15 | # find the CLI Tools update
16 | PROD=$(softwareupdate -l | grep "\*.*Command Line" | head -n 1 | awk -F"*" '{print $2}' | sed -e 's/^ *//' | tr -d '\n')
17 | # install it
18 | softwareupdate -i "$PROD" --verbose
19 | rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
20 |
21 | # on 10.7/10.8, we instead download from public download URLs, which can be found in
22 | # the dvtdownloadableindex:
23 | # https://devimages.apple.com.edgekey.net/downloads/xcode/simulators/index-3905972D-B609-49CE-8D06-51ADC78E07BC.dvtdownloadableindex
24 | else
25 | [ "$OSX_VERS" -eq 7 ] && DMGURL=http://devimages.apple.com.edgekey.net/downloads/xcode/command_line_tools_for_xcode_os_x_lion_april_2013.dmg
26 | [ "$OSX_VERS" -eq 8 ] && DMGURL=http://devimages.apple.com.edgekey.net/downloads/xcode/command_line_tools_for_osx_mountain_lion_april_2014.dmg
27 |
28 | TOOLS=clitools.dmg
29 | curl "$DMGURL" -o "$TOOLS"
30 | TMPMOUNT=`/usr/bin/mktemp -d /tmp/clitools.XXXX`
31 | hdiutil attach "$TOOLS" -mountpoint "$TMPMOUNT"
32 | if [ "$OSX_VERS" -eq 7 ]; then
33 | # using '-allowUntrusted' because Lion CLI tools are so old Apple never built another
34 | # package that doesn't have an expired CA cert. (Expired February 15, 2015)
35 | installer -pkg "$(find $TMPMOUNT -name '*.mpkg')" -allowUntrusted -target /
36 | else
37 | installer -pkg "$(find $TMPMOUNT -name '*.mpkg')" -target /
38 | fi
39 | hdiutil detach "$TMPMOUNT"
40 | rm -rf "$TMPMOUNT"
41 | rm "$TOOLS"
42 | exit
43 | fi
44 |
--------------------------------------------------------------------------------
/scripts/puppet.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Install the specified version of Puppet and tools
4 | #
5 | # PUPPET_VERSION, FACTER_VERSION and HIERA_VERSION are set to either
6 | # 'latest' or specific versions via the Packer template
7 | #
8 | # install function mostly borrowed dmg function from hashicorp/puppet-bootstrap,
9 | # except we just take an already-downloaded dmg
10 |
11 | if [[ "${PUPPET_VERSION}" == "none" && \
12 | "${FACTER_VERSION}" == "none" && \
13 | "${HIERA_VERSION}" == "none" && \
14 | "${PUPPET_AGENT_VERSION}" == "none" ]]; then
15 | exit
16 | fi
17 |
18 | install_dmg() {
19 | local name="$1"
20 | local dmg_path="$2"
21 |
22 | echo "Installing: ${name}"
23 |
24 | # Mount the DMG
25 | echo "-- Mounting DMG..."
26 | tmpmount=$(/usr/bin/mktemp -d /tmp/puppet-dmg.XXXX)
27 | hdiutil attach "${dmg_path}" -mountpoint "${tmpmount}"
28 |
29 | echo "-- Installing pkg..."
30 | pkg_path=$(find "${tmpmount}" -name '*.pkg' -mindepth 1 -maxdepth 1)
31 | installer -pkg "${pkg_path}" -tgt /
32 |
33 | # Unmount
34 | echo "-- Unmounting and ejecting DMG..."
35 | hdiutil eject "${tmpmount}"
36 | }
37 |
38 | get_dmg() {
39 | local recipe_name="$1"
40 | local version="$2"
41 | local report_path=$(mktemp /tmp/autopkg-report-XXXX)
42 |
43 | # Run AutoPkg setting VERSION, and saving the results as a plist
44 | "${AUTOPKG}" run --report-plist "${report_path}" -k VERSION="${version}" "${recipe_name}" > \
45 | "$(mktemp "/tmp/autopkg-runlog-${recipe_name}")"
46 | /usr/libexec/PlistBuddy -c \
47 | 'Print :summary_results:url_downloader_summary_result:data_rows:0:download_path' \
48 | "${report_path}"
49 | }
50 |
51 | # Default to installing the current version of Puppet - it's not 2013 anymore.
52 | PUPPET_VERSION=${PUPPET_VERSION:-none}
53 | FACTER_VERSION=${FACTER_VERSION:-none}
54 | HIERA_VERSION=${HIERA_VERSION:-none}
55 | PUPPET_AGENT_VERSION=${PUPPET_AGENT_VERSION:-latest}
56 |
57 | # Get AutoPkg
58 | AUTOPKG_DIR=$(mktemp -d /tmp/autopkg-XXXX)
59 | git clone https://github.com/autopkg/autopkg "$AUTOPKG_DIR"
60 | AUTOPKG="$AUTOPKG_DIR/Code/autopkg"
61 |
62 | # Add the recipes repo containing Puppet/Facter
63 | "${AUTOPKG}" repo-add recipes
64 |
65 | # Redirect AutoPkg cache to a temp location
66 | defaults write com.github.autopkg CACHE_DIR -string "$(mktemp -d /tmp/autopkg-cache-XXX)"
67 |
68 | if [ "${PUPPET_VERSION}" != "none" ]; then
69 | # Hide all users from the loginwindow with uid below 500, which will include the puppet user
70 | defaults write /Library/Preferences/com.apple.loginwindow Hide500Users -bool YES
71 | PUPPET_DMG=$(get_dmg Puppet.download "${PUPPET_VERSION}")
72 | install_dmg "Puppet" "${PUPPET_DMG}"
73 | fi
74 |
75 | if [ "${PUPPET_AGENT_VERSION}" != "none" ]; then
76 | # Hide all users from the loginwindow with uid below 500, which will include the puppet user
77 | defaults write /Library/Preferences/com.apple.loginwindow Hide500Users -bool YES
78 | PUPPET_AGENT_DMG=$(get_dmg Puppet-Agent.download "${PUPPET_AGENT_VERSION}")
79 | install_dmg "Puppet Agent" "${PUPPET_AGENT_DMG}"
80 | fi
81 |
82 | if [ "${FACTER_VERSION}" != "none" ]; then
83 | FACTER_DMG=$(get_dmg Facter.download "${FACTER_VERSION}")
84 | install_dmg "Facter" "${FACTER_DMG}"
85 | fi
86 |
87 | if [ "${HIERA_VERSION}" != "none" ]; then
88 | HIERA_DMG=$(get_dmg Hiera.download "${HIERA_VERSION}")
89 | install_dmg "Hiera" "${HIERA_DMG}"
90 | fi
91 |
92 |
93 | # Clean up
94 | rm -rf "${PUPPET_DMG}" "${FACTER_DMG}" "${HIERA_DMG}" "${PUPPET_AGENT_DMG}" "${AUTOPKG_DIR}" "~/Library/AutoPkg"
95 |
96 | defaults delete com.github.autopkg
97 |
--------------------------------------------------------------------------------
/prepare_iso/support/pkg-postinstall:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | USER="__USER__PLACEHOLDER__"
3 | OSX_VERS=$(sw_vers -productVersion | awk -F "." '{print $2}')
4 | PlistBuddy="/usr/libexec/PlistBuddy"
5 |
6 | target_ds_node="${3}/private/var/db/dslocal/nodes/Default"
7 | # Override the default behavior of sshd on the target volume to be not disabled
8 | if [ "$OSX_VERS" -ge 10 ]; then
9 | OVERRIDES_PLIST="$3/private/var/db/com.apple.xpc.launchd/disabled.plist"
10 | $PlistBuddy -c 'Delete :com.openssh.sshd' "$OVERRIDES_PLIST"
11 | $PlistBuddy -c 'Add :com.openssh.sshd bool False' "$OVERRIDES_PLIST"
12 | if [ __DISABLE_SCREEN_SHARING__ = 0 ]; then
13 | $PlistBuddy -c 'Delete :com.apple.screensharing' "$OVERRIDES_PLIST"
14 | $PlistBuddy -c 'Add :com.apple.screensharing bool False' "$OVERRIDES_PLIST"
15 | fi
16 | else
17 | OVERRIDES_PLIST="$3/private/var/db/launchd.db/com.apple.launchd/overrides.plist"
18 | $PlistBuddy -c 'Delete :com.openssh.sshd' "$OVERRIDES_PLIST"
19 | $PlistBuddy -c 'Add :com.openssh.sshd:Disabled bool False' "$OVERRIDES_PLIST"
20 | if [ __DISABLE_SCREEN_SHARING__ = 0 ]; then
21 | $PlistBuddy -c 'Delete :com.apple.screensharing' "$OVERRIDES_PLIST"
22 | $PlistBuddy -c 'Add :com.apple.screensharing:Disabled bool False' "$OVERRIDES_PLIST"
23 | fi
24 | fi
25 |
26 | # Add user to sudoers
27 | cp "$3/etc/sudoers" "$3/etc/sudoers.orig"
28 | echo "$USER ALL=(ALL) NOPASSWD: ALL" >> "$3/etc/sudoers"
29 |
30 | # Add user to admin group memberships (even though GID 80 is enough for most things)
31 | USER_GUID=$($PlistBuddy -c 'Print :generateduid:0' "$target_ds_node/users/$USER.plist")
32 | USER_UID=$($PlistBuddy -c 'Print :uid:0' "$target_ds_node/users/$USER.plist")
33 | $PlistBuddy -c 'Add :groupmembers: string '"$USER_GUID" "$target_ds_node/groups/admin.plist"
34 |
35 | # Add user to SSH SACL group membership
36 | ssh_group="${target_ds_node}/groups/com.apple.access_ssh.plist"
37 | $PlistBuddy -c 'Add :groupmembers array' "${ssh_group}"
38 | $PlistBuddy -c 'Add :groupmembers:0 string '"$USER_GUID"'' "${ssh_group}"
39 | $PlistBuddy -c 'Add :users array' "${ssh_group}"
40 | $PlistBuddy -c 'Add :users:0 string '$USER'' "${ssh_group}"
41 |
42 | # Enable Remote Desktop and configure user with full privileges
43 | if [ __DISABLE_REMOTE_MANAGEMENT__ = 0 ]; then
44 | echo "enabled" > "$3/private/etc/RemoteManagement.launchd"
45 | $PlistBuddy -c 'Add :naprivs array' "$target_ds_node/users/$USER.plist"
46 | $PlistBuddy -c 'Add :naprivs:0 string -1073741569' "$target_ds_node/users/$USER.plist"
47 | fi
48 |
49 | if [ __DISABLE_SIP__ = 1 ]; then
50 | csrutil disable
51 | fi
52 |
53 | # Pre-create user folder so veewee will have somewhere to scp configinfo to
54 | mkdir -p "$3/Users/$USER/Library/Preferences"
55 |
56 | # Suppress annoying iCloud welcome on a GUI login
57 | $PlistBuddy -c 'Add :DidSeeCloudSetup bool true' "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"
58 | $PlistBuddy -c 'Add :LastSeenCloudProductVersion string 10.'"$OSX_VERS" "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"
59 | $PlistBuddy -c 'Add :DidSeeSiriSetup bool true' "$3/Users/$USER/Library/Preferences/com.apple.SetupAssistant.plist"
60 |
61 | # Fix ownership now that the above has made a Library folder as root
62 | chown -R "$USER_UID":20 "$3/Users/$USER"
63 |
64 | # Disable Diagnostics submissions prompt if 10.10
65 | # http://macops.ca/diagnostics-prompt-yosemite
66 | if [ "$OSX_VERS" -ge 10 ]; then
67 | # Apple's defaults
68 | SUBMIT_TO_APPLE=YES
69 | SUBMIT_TO_APP_DEVELOPERS=NO
70 |
71 | CRASHREPORTER_SUPPORT="$3/Library/Application Support/CrashReporter"
72 | CRASHREPORTER_DIAG_PLIST="${CRASHREPORTER_SUPPORT}/DiagnosticMessagesHistory.plist"
73 | if [ ! -d "${CRASHREPORTER_SUPPORT}" ]; then
74 | mkdir "${CRASHREPORTER_SUPPORT}"
75 | chmod 775 "${CRASHREPORTER_SUPPORT}"
76 | chown root:admin "${CRASHREPORTER_SUPPORT}"
77 | fi
78 | for key in AutoSubmit AutoSubmitVersion ThirdPartyDataSubmit ThirdPartyDataSubmitVersion; do
79 | $PlistBuddy -c "Delete :$key" "${CRASHREPORTER_DIAG_PLIST}" 2> /dev/null
80 | done
81 | $PlistBuddy -c "Add :AutoSubmit bool ${SUBMIT_TO_APPLE}" "${CRASHREPORTER_DIAG_PLIST}"
82 | $PlistBuddy -c "Add :AutoSubmitVersion integer 4" "${CRASHREPORTER_DIAG_PLIST}"
83 | $PlistBuddy -c "Add :ThirdPartyDataSubmit bool ${SUBMIT_TO_APP_DEVELOPERS}" "${CRASHREPORTER_DIAG_PLIST}"
84 | $PlistBuddy -c "Add :ThirdPartyDataSubmitVersion integer 4" "${CRASHREPORTER_DIAG_PLIST}"
85 | fi
86 |
87 | # Disable loginwindow screensaver to save CPU cycles
88 | $PlistBuddy -c 'Add :loginWindowIdleTime integer 0' "$3/Library/Preferences/com.apple.screensaver.plist"
89 |
90 | # Disable the welcome screen
91 | touch "$3/private/var/db/.AppleSetupDone"
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # packer-osx
2 |
3 | This is a set of [Packer][] templates and scripts to help automate the
4 | installation of OS X. It's based off of [timsutton/osx-vm-templates][].
5 |
6 | ## Usage
7 |
8 | This set of scripts supports all versions of OS X that are distributed through
9 | the App Store: OS X Lion (10.7) through El Capitan (10.11), and macOS Sierra
10 | (10.12).
11 |
12 | This fork has a few templates to support different use cases:
13 |
14 | * `vagrant.json`
15 | * `standalone.json`
16 |
17 | ### Preparing the ISO
18 |
19 | `prepare_iso.sh` builds a custom ISO image which has been modified to automate
20 | the install.
21 |
22 | Run the `prepare_iso.sh` script with two arguments: the path to an `Install OS
23 | X.app` or the `InstallESD.dmg` contained within, and an output directory. Root
24 | privileges are required in order to write a new DMG with the correct file
25 | ownerships. For example, with a 10.8.4 Mountain Lion installer:
26 |
27 | ```
28 | sudo prepare_iso/prepare_iso.sh "/Applications/Install OS X El Capitan.app" iso
29 | ```
30 |
31 | ...should output progress information ending in something this:
32 |
33 | ```
34 | -- MD5: dc93ded64396574897a5f41d6dd7066c
35 | -- Done. Built image is located at iso/OSX_InstallESD_10.11.6_15G31.dmg.
36 | ```
37 |
38 | `prepare_iso.sh` accepts command line switches to modify the details of the
39 | admin user installed by the script.
40 |
41 | * `-u` modifies the name of the admin account, defaults to `vagrant`
42 | * `-p` modifies the password of the same account, defaults to `vagrant`
43 | * `-i` sets the path of the account's avatar image, defaults to
44 | `prepare_iso/support/vagrant.jpg`
45 |
46 | For example:
47 |
48 | ```
49 | sudo prepare_iso/prepare_iso.sh -u admin -p password -i /path/to/image.jpg \
50 | "/Applications/Install OS X El Capitan.app" iso
51 | ```
52 |
53 | Additionally, flags can be set to disable certain default configuration options.
54 |
55 | * `-D DISABLE_REMOTE_MANAGEMENT` disables the Remote Management service.
56 | * `-D DISABLE_SCREEN_SHARING` disables the Screen Sharing service.
57 |
58 | ### Building with Packer
59 |
60 | The templates include a set of additional VM options that are needed for OS X
61 | guests. The output ISO can be passed to Packer in a user variable.
62 |
63 | ```sh
64 | packer build \
65 | -var iso_url=iso/OSX_InstallESD_10.11.6_15G31.dmg \
66 | template.json
67 | ```
68 |
69 | You might also use the `-only` option to restrict to either the `vmware-iso` or
70 | `virtualbox-iso` builders.
71 |
72 | #### Configuration Options
73 |
74 | The installation is automated inside the disk image, so there is little inside
75 | the Packer template itself. However, the provisioning scripts have a few
76 | options:
77 |
78 | ##### Username & Password
79 |
80 | ```
81 | -var username=youruser \
82 | -var password=yourpassword \
83 | ```
84 |
85 | ##### Automated GUI logins
86 |
87 | If you need to attach to a login session, this will cause the user to
88 | automatically login:
89 |
90 | `packer build -var autologin=true template.json`
91 |
92 | ##### Vagrant
93 |
94 | ```
95 | packer build -var install_vagrant_keys=false template.json
96 | ```
97 |
98 | ##### Chef & Puppet
99 |
100 | By default, the template doesn't install Chef or Puppet. To enable this, set
101 | the version to `latest`, or to a specific version:
102 |
103 | ```
104 | packer build -var chef_version=latest template.json
105 | ```
106 |
107 | ```
108 | packer build -var puppet_version=latest template.json
109 | ```
110 |
111 | ##### Xcode CLI Tools
112 |
113 | The Xcode CLI tools are installed by the packer template by default. To disable
114 | the installation, set the `install_xcode_cli_tools` variable to `false`:
115 |
116 | ```
117 | packer build -var install_xcode_cli_tools=false template.json
118 | ```
119 |
120 | ##### System updates
121 |
122 | Packer will instruct the system to download and install all available OS X
123 | updates, if you want to disable this default behaviour, use `update_system`
124 | variable:
125 |
126 | ```
127 | packer build -var update_system=0 template.json
128 | ```
129 |
130 | ##### Provisioning delay
131 |
132 | In some cases, it may be helpful to insert a delay into the beginning of the
133 | provisioning process. Adding a delay of about 30 seconds may help subsequent
134 | provisioning steps that install software from the internet complete
135 | successfully. By default, the delay is set to `0`, but you can change the delay
136 | by setting the `provisioning_delay` variable:
137 |
138 | ```
139 | packer build -var provisioning_delay=30 template.json`
140 | ```
141 |
142 | [Packer]: https://packer.io
143 | [timsutton/osx-vm-templates]: https://github.com/timsutton/osx-vm-templates
144 |
--------------------------------------------------------------------------------
/vagrant.json:
--------------------------------------------------------------------------------
1 | {
2 | "builders": [
3 | {
4 | "boot_wait": "5s",
5 | "disk_size": 40960,
6 | "guest_os_type": "win-8",
7 | "iso_checksum_type": "none",
8 | "iso_url": "{{user `iso_url`}}",
9 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
10 | "ssh_port": 22,
11 | "ssh_username": "{{user `username`}}",
12 | "ssh_password": "{{user `password`}}",
13 | "ssh_wait_timeout": "10000s",
14 | "parallels_tools_flavor": "mac",
15 | "type": "parallels-iso",
16 | "prlctl": [
17 | ["set", "{{.Name}}", "--memsize", "4096"],
18 | ["set", "{{.Name}}", "--cpus", "2"],
19 | ["set", "{{.Name}}", "--distribution", "macosx"],
20 | ["set", "{{.Name}}", "--3d-accelerate", "highest"],
21 | ["set", "{{.Name}}", "--high-resolution", "off"],
22 | ["set", "{{.Name}}", "--auto-share-camera", "off"],
23 | ["set", "{{.Name}}", "--auto-share-bluetooth", "off"],
24 | ["set", "{{.Name}}", "--on-window-close", "keep-running"],
25 | ["set", "{{.Name}}", "--shf-host", "off"]
26 | ]
27 | },
28 | {
29 | "boot_wait": "2s",
30 | "disk_size": 40960,
31 | "guest_os_type": "darwin12-64",
32 | "iso_checksum_type": "none",
33 | "iso_url": "{{user `iso_url`}}",
34 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
35 | "skip_compaction": true,
36 | "ssh_port": 22,
37 | "ssh_username": "{{user `username`}}",
38 | "ssh_password": "{{user `password`}}",
39 | "ssh_wait_timeout": "10000s",
40 | "tools_upload_flavor": "darwin",
41 | "type": "vmware-iso",
42 | "vmx_data": {
43 | "cpuid.coresPerSocket": "1",
44 | "memsize": "4096",
45 | "numvcpus": "2",
46 | "firmware": "efi",
47 | "keyboardAndMouseProfile": "macProfile",
48 | "smc.present": "TRUE",
49 | "hpet0.present": "TRUE",
50 | "ich7m.present": "TRUE",
51 | "ehci.present": "TRUE",
52 | "usb.present": "TRUE"
53 | }
54 | },
55 | {
56 | "boot_wait": "2s",
57 | "disk_size": 40960,
58 | "guest_additions_mode": "disable",
59 | "guest_os_type": "MacOS1011_64",
60 | "hard_drive_interface": "sata",
61 | "iso_checksum_type": "none",
62 | "iso_interface": "sata",
63 | "iso_url": "{{user `iso_url`}}",
64 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
65 | "ssh_port": 22,
66 | "ssh_username": "{{user `username`}}",
67 | "ssh_password": "{{user `password`}}",
68 | "ssh_wait_timeout": "10000s",
69 | "type": "virtualbox-iso",
70 | "vboxmanage": [
71 | ["modifyvm", "{{.Name}}", "--audiocontroller", "hda"],
72 | ["modifyvm", "{{.Name}}", "--boot1", "dvd"],
73 | ["modifyvm", "{{.Name}}", "--boot2", "disk"],
74 | ["modifyvm", "{{.Name}}", "--chipset", "ich9"],
75 | ["modifyvm", "{{.Name}}", "--firmware", "efi"],
76 | ["modifyvm", "{{.Name}}", "--hpet", "on"],
77 | ["modifyvm", "{{.Name}}", "--keyboard", "usb"],
78 | ["modifyvm", "{{.Name}}", "--memory", "4096"],
79 | ["modifyvm", "{{.Name}}", "--cpus", "2"]
80 | ["modifyvm", "{{.Name}}", "--mouse", "usbtablet"],
81 | ["modifyvm", "{{.Name}}", "--usbehci", "on"],
82 | ["modifyvm", "{{.Name}}", "--vram", "128"],
83 | ["storagectl", "{{.Name}}", "--name", "IDE Controller", "--remove"]
84 | ]
85 | }
86 | ],
87 | "min_packer_version": "0.7.0",
88 | "post-processors": [
89 | "vagrant"
90 | ],
91 | "provisioners": [
92 | {
93 | "type": "shell-local",
94 | "command": "sleep {{user `provisioning_delay`}}"
95 | },
96 | {
97 | "destination": "/private/tmp/set_kcpassword.py",
98 | "source": "scripts/support/set_kcpassword.py",
99 | "type": "file"
100 | },
101 | {
102 | "execute_command": "chmod +x {{ .Path }}; sudo {{ .Vars }} {{ .Path }}",
103 | "scripts": [
104 | "scripts/vagrant.sh",
105 | "scripts/vmware.sh",
106 | "scripts/parallels.sh",
107 | "scripts/xcode-cli-tools.sh",
108 | "scripts/chef-omnibus.sh",
109 | "scripts/puppet.sh",
110 | "scripts/add-network-interface-detection.sh",
111 | "scripts/autologin.sh",
112 | "scripts/system-update.sh",
113 | "scripts/shrink.sh"
114 | ],
115 | "environment_vars": [
116 | "AUTOLOGIN={{user `autologin`}}",
117 | "CHEF_VERSION={{user `chef_version`}}",
118 | "FACTER_VERSION={{user `facter_version`}}",
119 | "HIERA_VERSION={{user `hiera_version`}}",
120 | "INSTALL_VAGRANT_KEYS={{user `install_vagrant_keys`}}",
121 | "NOCM={{user `nocm`}}",
122 | "INSTALL_XCODE_CLI_TOOLS={{user `install_xcode_cli_tools`}}",
123 | "PASSWORD={{user `password`}}",
124 | "PUPPET_VERSION={{user `puppet_version`}}",
125 | "PUPPET_AGENT_VERSION={{user `puppet_agent_version`}}",
126 | "UPDATE_SYSTEM={{user `update_system`}}",
127 | "USERNAME={{user `username`}}"
128 | ],
129 | "type": "shell"
130 | }
131 | ],
132 | "variables": {
133 | "autologin": "false",
134 | "chef_version": "none",
135 | "facter_version": "none",
136 | "hiera_version": "none",
137 | "install_vagrant_keys": "true",
138 | "install_xcode_cli_tools": "true",
139 | "iso_url": "OSX_InstallESD_10.11.1_15B42.dmg",
140 | "password": "vagrant",
141 | "provisioning_delay": "0",
142 | "puppet_version": "none",
143 | "puppet_agent_version": "none",
144 | "update_system": "true",
145 | "username": "vagrant"
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/standalone.json:
--------------------------------------------------------------------------------
1 | {
2 | "variables": {
3 | "iso_url": "OSX_InstallESD_10.11.1_15B42.dmg",
4 | "provisioning_delay": "0",
5 | "username": "vagrant",
6 | "password": "vagrant",
7 | "autologin": "false",
8 | "update_system": "true",
9 | "install_xcode_cli_tools": "true",
10 |
11 | "chef_version": "none",
12 | "facter_version": "none",
13 | "hiera_version": "none",
14 | "puppet_version": "none",
15 | "puppet_agent_version": "none"
16 | },
17 |
18 | "builders": [
19 | {
20 | "vm_name": "osx-standalone-parallels",
21 | "type": "parallels-iso",
22 | "guest_os_type": "win-8",
23 | "parallels_tools_flavor": "mac",
24 |
25 | "iso_url": "{{user `iso_url`}}",
26 | "iso_checksum_type": "none",
27 |
28 | "ssh_username": "{{user `username`}}",
29 | "ssh_password": "{{user `password`}}",
30 | "ssh_wait_timeout": "10000s",
31 |
32 | "boot_wait": "5s",
33 | "disk_size": 40960,
34 |
35 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
36 |
37 | "keep_registered": true,
38 |
39 | "prlctl": [
40 | ["set", "{{.Name}}", "--memsize", "4096"],
41 | ["set", "{{.Name}}", "--cpus", "2"],
42 | ["set", "{{.Name}}", "--distribution", "macosx"],
43 | ["set", "{{.Name}}", "--3d-accelerate", "highest"],
44 | ["set", "{{.Name}}", "--high-resolution", "off"],
45 | ["set", "{{.Name}}", "--auto-share-camera", "off"],
46 | ["set", "{{.Name}}", "--auto-share-bluetooth", "off"],
47 | ["set", "{{.Name}}", "--on-window-close", "keep-running"],
48 | ["set", "{{.Name}}", "--shf-host", "off"]
49 | ]
50 | },
51 | {
52 | "vm_name": "osx-standalone-vmware",
53 | "type": "vmware-iso",
54 | "guest_os_type": "darwin12-64",
55 | "tools_upload_flavor": "darwin",
56 |
57 | "iso_url": "{{user `iso_url`}}",
58 | "iso_checksum_type": "none",
59 |
60 | "ssh_username": "{{user `username`}}",
61 | "ssh_password": "{{user `password`}}",
62 | "ssh_wait_timeout": "10000s",
63 |
64 | "boot_wait": "2s",
65 | "disk_size": 40960,
66 |
67 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
68 |
69 | "keep_registered": true,
70 | "skip_compaction": true,
71 |
72 | "vmx_data": {
73 | "cpuid.coresPerSocket": "1",
74 | "memsize": "4096",
75 | "numvcpus": "2",
76 | "firmware": "efi",
77 | "keyboardAndMouseProfile": "macProfile",
78 | "smc.present": "TRUE",
79 | "hpet0.present": "TRUE",
80 | "ich7m.present": "TRUE",
81 | "ehci.present": "TRUE",
82 | "usb.present": "TRUE"
83 | }
84 | },
85 | {
86 | "vm_name": "osx-standalone-virtualbox",
87 | "type": "virtualbox-iso",
88 | "guest_os_type": "MacOS1011_64",
89 | "guest_additions_mode": "disable",
90 |
91 | "iso_url": "{{user `iso_url`}}",
92 | "iso_checksum_type": "none",
93 |
94 | "ssh_username": "{{user `username`}}",
95 | "ssh_password": "{{user `password`}}",
96 |
97 | "ssh_wait_timeout": "10000s",
98 | "boot_wait": "2s",
99 | "disk_size": 40960,
100 | "iso_interface": "sata",
101 | "hard_drive_interface": "sata",
102 |
103 | "shutdown_command": "echo '{{user `username`}}'|sudo -S shutdown -h now",
104 |
105 | "keep_registered": true,
106 |
107 | "vboxmanage": [
108 | ["modifyvm", "{{.Name}}", "--audiocontroller", "hda"],
109 | ["modifyvm", "{{.Name}}", "--boot1", "dvd"],
110 | ["modifyvm", "{{.Name}}", "--boot2", "disk"],
111 | ["modifyvm", "{{.Name}}", "--chipset", "ich9"],
112 | ["modifyvm", "{{.Name}}", "--firmware", "efi"],
113 | ["modifyvm", "{{.Name}}", "--hpet", "on"],
114 | ["modifyvm", "{{.Name}}", "--keyboard", "usb"],
115 | ["modifyvm", "{{.Name}}", "--memory", "4096"],
116 | ["modifyvm", "{{.Name}}", "--cpus", "2"],
117 | ["modifyvm", "{{.Name}}", "--mouse", "usbtablet"],
118 | ["modifyvm", "{{.Name}}", "--usbehci", "on"],
119 | ["modifyvm", "{{.Name}}", "--vram", "128"],
120 | ["storagectl", "{{.Name}}", "--name", "IDE Controller", "--remove"]
121 | ]
122 | }
123 | ],
124 |
125 | "provisioners": [
126 | {
127 | "type": "shell-local",
128 | "command": "sleep {{user `provisioning_delay`}}"
129 | },
130 | {
131 | "destination": "/private/tmp/set_kcpassword.py",
132 | "source": "scripts/support/set_kcpassword.py",
133 | "type": "file"
134 | },
135 | {
136 | "type": "shell",
137 | "environment_vars": [
138 | "USERNAME={{user `username`}}",
139 | "PASSWORD={{user `password`}}",
140 | "AUTOLOGIN={{user `autologin`}}",
141 | "UPDATE_SYSTEM={{user `update_system`}}",
142 | "INSTALL_XCODE_CLI_TOOLS={{user `install_xcode_cli_tools`}}",
143 | "CHEF_VERSION={{user `chef_version`}}",
144 | "FACTER_VERSION={{user `facter_version`}}",
145 | "HIERA_VERSION={{user `hiera_version`}}",
146 | "PUPPET_VERSION={{user `puppet_version`}}",
147 | "PUPPET_AGENT_VERSION={{user `puppet_agent_version`}}"
148 | ],
149 | "scripts": [
150 | "scripts/post-install.sh",
151 | "scripts/vmware.sh",
152 | "scripts/parallels.sh",
153 |
154 | "scripts/xcode-cli-tools.sh",
155 | "scripts/chef-omnibus.sh",
156 | "scripts/puppet.sh",
157 |
158 | "scripts/add-network-interface-detection.sh",
159 | "scripts/autologin.sh",
160 | "scripts/system-update.sh",
161 | "scripts/shrink.sh"
162 | ],
163 |
164 | "execute_command": "chmod +x {{ .Path }}; sudo {{ .Vars }} {{ .Path }}"
165 | }
166 | ]
167 | }
168 |
--------------------------------------------------------------------------------
/prepare_iso/prepare_iso.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 | #
3 | # Preparation script for an OS X automated installation for use with VeeWee/Packer/Vagrant
4 | #
5 | # What the script does, in more detail:
6 | #
7 | # 1. Mounts the InstallESD.dmg using a shadow file, so the original DMG is left
8 | # unchanged.
9 | # 2. Modifies the BaseSystem.dmg within in order to add an additional 'rc.cdrom.local'
10 | # file in /etc, which is a supported local configuration sourced in at boot time
11 | # by the installer environment. This file contains instructions to erase and format
12 | # 'disk0', presumably the hard disk attached to the VM.
13 | # 3. A 'veewee-config.pkg' installer package is built, which is added to the OS X
14 | # install by way of the OSInstall.collection file. This package creates the
15 | # 'vagrant' user, configures sshd and sudoers, and disables setup assistants.
16 | # 4. veewee-config.pkg and the various support utilities are copied, and the disk
17 | # image is saved to the output path.
18 | #
19 | # Thanks:
20 | # Idea and much of the implementation thanks to Pepijn Bruienne, who's also provided
21 | # some process notes here: https://gist.github.com/4542016. The sample minstallconfig.xml,
22 | # use of OSInstall.collection and readme documentation provided with Greg Neagle's
23 | # createOSXInstallPkg tool also proved very helpful. (http://code.google.com/p/munki/wiki/InstallingOSX)
24 | #
25 | # User creation via package install method also credited to Greg, and made easy with Per
26 | # Olofsson's CreateUserPkg (http://magervalp.github.io/CreateUserPkg)
27 | #
28 | # Antony Blakey for updates to support OS X 10.11:
29 | # https://github.com/timsutton/osx-vm-templates/issues/40
30 |
31 | usage() {
32 | cat <
44 | Sets the username of the root user, defaults to 'vagrant'.
45 |
46 | -p
47 | Sets the password of the root user, defaults to 'vagrant'.
48 |
49 | -i
50 | Sets the path of the avatar image for the root user, defaulting to the vagrant icon.
51 |
52 | -D
53 | Sets the specified flag. Valid flags are:
54 | DISABLE_REMOTE_MANAGEMENT
55 | DISABLE_SCREEN_SHARING
56 | DISABLE_SIP
57 |
58 | EOF
59 | }
60 |
61 | cleanup() {
62 | hdiutil detach -quiet -force "$MNT_ESD" || echo > /dev/null
63 | hdiutil detach -quiet -force "$MNT_BASE_SYSTEM" || echo > /dev/null
64 | rm -rf "$MNT_ESD" "$MNT_BASE_SYSTEM" "$BASE_SYSTEM_DMG_RW" "$SHADOW_FILE"
65 | }
66 |
67 | trap cleanup EXIT INT TERM
68 |
69 |
70 | msg_status() {
71 | echo "\033[0;32m-- $1\033[0m"
72 | }
73 | msg_error() {
74 | echo "\033[0;31m-- $1\033[0m"
75 | }
76 |
77 | render_template() {
78 | eval "echo \"$(cat "$1")\""
79 | }
80 |
81 | if [ $# -eq 0 ]; then
82 | usage
83 | exit 1
84 | fi
85 |
86 | SCRIPT_DIR="$(cd "$(dirname "$0")"; pwd)"
87 | SUPPORT_DIR="$SCRIPT_DIR/support"
88 |
89 | # Parse the optional command line switches
90 | USER="vagrant"
91 | PASSWORD="vagrant"
92 | IMAGE_PATH="$SUPPORT_DIR/vagrant.jpg"
93 |
94 | # Flags
95 | DISABLE_REMOTE_MANAGEMENT=0
96 | DISABLE_SCREEN_SHARING=0
97 | DISABLE_SIP=0
98 |
99 | while getopts u:p:i:D: OPT; do
100 | case "$OPT" in
101 | u)
102 | USER="$OPTARG"
103 | ;;
104 | p)
105 | PASSWORD="$OPTARG"
106 | ;;
107 | i)
108 | IMAGE_PATH="$OPTARG"
109 | ;;
110 | D)
111 | if [ x${!OPTARG} = x0 ]; then
112 | eval $OPTARG=1
113 | elif [ x${!OPTARG} != x1 ]; then
114 | msg_error "Unknown flag: ${OPTARG}"
115 | usage
116 | exit 1
117 | fi
118 | ;;
119 | \?)
120 | usage
121 | exit 1
122 | ;;
123 | esac
124 | done
125 |
126 | # Remove the switches we parsed above.
127 | shift $(expr $OPTIND - 1)
128 |
129 | if [ $(id -u) -ne 0 ]; then
130 | msg_error "This script must be run as root, as it saves a disk image with ownerships enabled."
131 | exit 1
132 | fi
133 |
134 | ESD="$1"
135 | if [ ! -e "$ESD" ]; then
136 | msg_error "Input installer image $ESD could not be found! Exiting.."
137 | exit 1
138 | fi
139 |
140 | if [ -d "$ESD" ]; then
141 | # we might be an install .app
142 | if [ -e "$ESD/Contents/SharedSupport/InstallESD.dmg" ]; then
143 | ESD="$ESD/Contents/SharedSupport/InstallESD.dmg"
144 | else
145 | msg_error "Can't locate an InstallESD.dmg in this source location $ESD!"
146 | fi
147 | fi
148 |
149 | VEEWEE_DIR="$(cd "$SCRIPT_DIR/../../../"; pwd)"
150 | VEEWEE_UID=$(/usr/bin/stat -f %u "$VEEWEE_DIR")
151 | VEEWEE_GID=$(/usr/bin/stat -f %g "$VEEWEE_DIR")
152 | DEFINITION_DIR="$(cd "$SCRIPT_DIR/.."; pwd)"
153 |
154 | if [ "$2" = "" ]; then
155 | msg_error "Currently an explicit output directory is required as the second argument."
156 | exit 1
157 | # The rest is left over from the old prepare_veewee_iso.sh script. Not sure if we
158 | # should leave in this functionality to automatically locate the veewee directory.
159 | DEFAULT_ISO_DIR=1
160 | OLDPWD=$(pwd)
161 | cd "$SCRIPT_DIR"
162 | # default to the veewee/iso directory
163 | if [ ! -d "../../../iso" ]; then
164 | mkdir "../../../iso"
165 | chown $VEEWEE_UID:$VEEWEE_GID "../../../iso"
166 | fi
167 | OUT_DIR="$(cd "$SCRIPT_DIR"; cd ../../../iso; pwd)"
168 | cd "$OLDPWD" # Rest of script depends on being in the working directory if we were passed relative paths
169 | else
170 | OUT_DIR="$2"
171 | fi
172 |
173 | if [ ! -d "$OUT_DIR" ]; then
174 | msg_status "Destination dir $OUT_DIR doesn't exist, creating.."
175 | mkdir -p "$OUT_DIR"
176 | fi
177 |
178 | if [ -e "$ESD.shadow" ]; then
179 | msg_status "Removing old shadow file.."
180 | rm "$ESD.shadow"
181 | fi
182 |
183 | MNT_ESD=$(/usr/bin/mktemp -d /tmp/veewee-osx-esd.XXXX)
184 | SHADOW_FILE=$(/usr/bin/mktemp /tmp/veewee-osx-shadow.XXXX)
185 | rm "$SHADOW_FILE"
186 | msg_status "Attaching input OS X installer image with shadow file.."
187 | hdiutil attach "$ESD" -mountpoint "$MNT_ESD" -shadow "$SHADOW_FILE" -nobrowse -owners on
188 | if [ $? -ne 0 ]; then
189 | [ ! -e "$ESD" ] && msg_error "Could not find $ESD in $(pwd)"
190 | msg_error "Could not mount $ESD on $MNT_ESD"
191 | exit 1
192 | fi
193 |
194 | msg_status "Mounting BaseSystem.."
195 | BASE_SYSTEM_DMG="$MNT_ESD/BaseSystem.dmg"
196 | MNT_BASE_SYSTEM=$(/usr/bin/mktemp -d /tmp/veewee-osx-basesystem.XXXX)
197 | [ ! -e "$BASE_SYSTEM_DMG" ] && msg_error "Could not find BaseSystem.dmg in $MNT_ESD"
198 | hdiutil attach "$BASE_SYSTEM_DMG" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on
199 | if [ $? -ne 0 ]; then
200 | msg_error "Could not mount $BASE_SYSTEM_DMG on $MNT_BASE_SYSTEM"
201 | exit 1
202 | fi
203 | SYSVER_PLIST_PATH="$MNT_BASE_SYSTEM/System/Library/CoreServices/SystemVersion.plist"
204 |
205 | DMG_OS_VERS=$(/usr/libexec/PlistBuddy -c 'Print :ProductVersion' "$SYSVER_PLIST_PATH")
206 | DMG_OS_VERS_MAJOR=$(echo $DMG_OS_VERS | awk -F "." '{print $2}')
207 | DMG_OS_VERS_MINOR=$(echo $DMG_OS_VERS | awk -F "." '{print $3}')
208 | DMG_OS_BUILD=$(/usr/libexec/PlistBuddy -c 'Print :ProductBuildVersion' "$SYSVER_PLIST_PATH")
209 | msg_status "OS X version detected: 10.$DMG_OS_VERS_MAJOR.$DMG_OS_VERS_MINOR, build $DMG_OS_BUILD"
210 |
211 | OUTPUT_DMG="$OUT_DIR/OSX_InstallESD_${DMG_OS_VERS}_${DMG_OS_BUILD}.dmg"
212 | if [ -e "$OUTPUT_DMG" ]; then
213 | msg_error "Output file $OUTPUT_DMG already exists! We're not going to overwrite it, exiting.."
214 | hdiutil detach -force "$MNT_ESD"
215 | exit 1
216 | fi
217 |
218 | # Build our post-installation pkg that will create a user and enable ssh
219 | msg_status "Making firstboot installer pkg.."
220 |
221 | # payload items
222 | mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users"
223 | mkdir -p "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash"
224 | BASE64_IMAGE=$(openssl base64 -in "$IMAGE_PATH")
225 | # Replace USER and BASE64_IMAGE in the user.plist file with the actual user and image
226 | render_template "$SUPPORT_DIR/user.plist" > "$SUPPORT_DIR/pkgroot/private/var/db/dslocal/nodes/Default/users/$USER.plist"
227 | USER_GUID=$(/usr/libexec/PlistBuddy -c 'Print :generateduid:0' "$SUPPORT_DIR/user.plist")
228 | # Generate a shadowhash from the supplied password
229 | "$SUPPORT_DIR/generate_shadowhash" "$PASSWORD" > "$SUPPORT_DIR/pkgroot/private/var/db/shadow/hash/$USER_GUID"
230 |
231 | # postinstall script
232 | mkdir -p "$SUPPORT_DIR/tmp/Scripts"
233 | cat "$SUPPORT_DIR/pkg-postinstall" \
234 | | sed -e "s/__USER__PLACEHOLDER__/${USER}/" \
235 | | sed -e "s/__DISABLE_REMOTE_MANAGEMENT__/${DISABLE_REMOTE_MANAGEMENT}/" \
236 | | sed -e "s/__DISABLE_SCREEN_SHARING__/${DISABLE_SCREEN_SHARING}/" \
237 | | sed -e "s/__DISABLE_SIP__/${DISABLE_SIP}/" \
238 | > "$SUPPORT_DIR/tmp/Scripts/postinstall"
239 | chmod a+x "$SUPPORT_DIR/tmp/Scripts/postinstall"
240 |
241 | # build it
242 | BUILT_COMPONENT_PKG="$SUPPORT_DIR/tmp/veewee-config-component.pkg"
243 | BUILT_PKG="$SUPPORT_DIR/tmp/veewee-config.pkg"
244 | pkgbuild --quiet \
245 | --root "$SUPPORT_DIR/pkgroot" \
246 | --scripts "$SUPPORT_DIR/tmp/Scripts" \
247 | --identifier com.vagrantup.veewee-config \
248 | --version 0.1 \
249 | "$BUILT_COMPONENT_PKG"
250 | productbuild \
251 | --package "$BUILT_COMPONENT_PKG" \
252 | "$BUILT_PKG"
253 | rm -rf "$SUPPORT_DIR/pkgroot"
254 |
255 | # We'd previously mounted this to check versions
256 | hdiutil detach "$MNT_BASE_SYSTEM"
257 |
258 | BASE_SYSTEM_DMG_RW="$(/usr/bin/mktemp /tmp/veewee-osx-basesystem-rw.XXXX).dmg"
259 |
260 | msg_status "Creating empty read-write DMG located at $BASE_SYSTEM_DMG_RW.."
261 | hdiutil create -o "$BASE_SYSTEM_DMG_RW" -size 10g -layout SPUD -fs HFS+J
262 | hdiutil attach "$BASE_SYSTEM_DMG_RW" -mountpoint "$MNT_BASE_SYSTEM" -nobrowse -owners on
263 |
264 | msg_status "Restoring ('asr restore') the BaseSystem to the read-write DMG.."
265 | # This asr restore was needed as of 10.11 DP7 and up. See
266 | # https://github.com/timsutton/osx-vm-templates/issues/40
267 | #
268 | # Note that when the restore completes, the volume is automatically re-mounted
269 | # and not with the '-nobrowse' option. It's an annoyance we could possibly fix
270 | # in the future..
271 | asr restore --source "$BASE_SYSTEM_DMG" --target "$MNT_BASE_SYSTEM" --noprompt --noverify --erase
272 | rm -r "$MNT_BASE_SYSTEM"
273 |
274 | if [ $DMG_OS_VERS_MAJOR -ge 9 ]; then
275 | MNT_BASE_SYSTEM="/Volumes/OS X Base System"
276 | BASESYSTEM_OUTPUT_IMAGE="$OUTPUT_DMG"
277 | PACKAGES_DIR="$MNT_BASE_SYSTEM/System/Installation/Packages"
278 |
279 | rm "$PACKAGES_DIR"
280 | msg_status "Moving 'Packages' directory from the ESD to BaseSystem.."
281 | mv -v "$MNT_ESD/Packages" "$MNT_BASE_SYSTEM/System/Installation/"
282 |
283 | # This isn't strictly required for Mavericks, but Yosemite will consider the
284 | # installer corrupt if this isn't included, because it cannot verify BaseSystem's
285 | # consistency and perform a recovery partition verification
286 | msg_status "Copying in original BaseSystem dmg and chunklist.."
287 | cp "$MNT_ESD/BaseSystem.dmg" "$MNT_BASE_SYSTEM/"
288 | cp "$MNT_ESD/BaseSystem.chunklist" "$MNT_BASE_SYSTEM/"
289 | else
290 | MNT_BASE_SYSTEM="/Volumes/Mac OS X Base System"
291 | BASESYSTEM_OUTPUT_IMAGE="$MNT_ESD/BaseSystem.dmg"
292 | rm "$BASESYSTEM_OUTPUT_IMAGE"
293 | PACKAGES_DIR="$MNT_ESD/Packages"
294 | fi
295 |
296 | msg_status "Adding automated components.."
297 | CDROM_LOCAL="$MNT_BASE_SYSTEM/private/etc/rc.cdrom.local"
298 | cat > $CDROM_LOCAL << EOF
299 | diskutil eraseDisk jhfs+ "Macintosh HD" GPTFormat disk0
300 | if [ "\$?" == "1" ]; then
301 | diskutil eraseDisk jhfs+ "Macintosh HD" GPTFormat disk1
302 | fi
303 | EOF
304 | chmod a+x "$CDROM_LOCAL"
305 | mkdir "$PACKAGES_DIR/Extras"
306 | cp "$SUPPORT_DIR/minstallconfig.xml" "$PACKAGES_DIR/Extras/"
307 | cp "$SUPPORT_DIR/OSInstall.collection" "$PACKAGES_DIR/"
308 | cp "$BUILT_PKG" "$PACKAGES_DIR/"
309 | rm -rf "$SUPPORT_DIR/tmp"
310 |
311 | msg_status "Unmounting BaseSystem.."
312 | hdiutil detach "$MNT_BASE_SYSTEM"
313 |
314 | if [ $DMG_OS_VERS_MAJOR -lt 9 ]; then
315 | msg_status "Pre-Mavericks we save back the modified BaseSystem to the root of the ESD."
316 | hdiutil convert -format UDZO -o "$MNT_ESD/BaseSystem.dmg" "$BASE_SYSTEM_DMG_RW"
317 | fi
318 |
319 | msg_status "Unmounting ESD.."
320 | hdiutil detach "$MNT_ESD"
321 |
322 | if [ $DMG_OS_VERS_MAJOR -ge 9 ]; then
323 | msg_status "On Mavericks and later, the entire modified BaseSystem is our output dmg."
324 | hdiutil convert -format UDZO -o "$OUTPUT_DMG" "$BASE_SYSTEM_DMG_RW"
325 | else
326 | msg_status "Pre-Mavericks we're modifying the original ESD file."
327 | hdiutil convert -format UDZO -o "$OUTPUT_DMG" -shadow "$SHADOW_FILE" "$ESD"
328 | fi
329 | rm -rf "$MNT_ESD" "$SHADOW_FILE"
330 |
331 | if [ -n "$SUDO_UID" ] && [ -n "$SUDO_GID" ]; then
332 | msg_status "Fixing permissions.."
333 | chown -R $SUDO_UID:$SUDO_GID \
334 | "$OUT_DIR"
335 | fi
336 |
337 | if [ -n "$DEFAULT_ISO_DIR" ]; then
338 | DEFINITION_FILE="$DEFINITION_DIR/definition.rb"
339 | msg_status "Setting ISO file in definition $DEFINITION_FILE.."
340 | ISO_FILE=$(basename "$OUTPUT_DMG")
341 | # Explicitly use -e in order to use double quotes around sed command
342 | sed -i -e "s/%OSX_ISO%/${ISO_FILE}/" "$DEFINITION_FILE"
343 | fi
344 |
345 | msg_status "Checksumming output image.."
346 | MD5=$(md5 -q "$OUTPUT_DMG")
347 | msg_status "MD5: $MD5"
348 |
349 | msg_status "Done. Built image is located at $OUTPUT_DMG. Add this iso and its checksum to your template."
350 |
--------------------------------------------------------------------------------