This script checks for the availability of new macOS releases currently supported by Apple, using mist-cli (not included in this project’s installer). It also requires a munki repo to be already set up. Please see the System Requirements section below for links.
misty can be used with a local repository or with SMB or Samba shares.
See the Changelog for details on version history and updates.
If a new update for any major version is found, it will be imported into the munki repo, creating the following installers:
- Apple Silicon: stage_os_installer and preloader for the installer
- Intel: startosinstall with precache key set to true
- Both architectures: Place installer in the
/Applications
directory for a later deployment
The item’s name keys will not include a major version. Scoping is done using board_id and device_id in the plists as installable_condition. By using this logic, only the latest available macOS upgrade will be offered to the individual client.
If present, one prior version will be kept in the munki repo (last known good). Older versions will be deleted before importing the new major version into the repo. We will update the script to support each new macOS once it is available to public. Older versions not being supported by Apple anymore (e.g., macOS 12 Monterey) will then not get deleted automatically. You will have to manually remove older items if not needed anymore in your repo.
Although supported by mist-cli, we do not offer beta releases. This workflow aims at production environments serving a larger number of clients with different hardware models needing to upgrade to different major versions.
misty is not intended for updating clients (minor updates within a major macOS version). There are other solutions available for that task.
The script does not have any command line options. You specify them in the configuration files (see Folder Structure).
Please run the script using sudo misty
. The script will then create a usr/
subfolder in /var/root/misty/
. The subfolder misty
will be created automatically during installation. A configuration file will be created that you should customize to suit your needs. You need root privileges to access the folder /var/root/misty/
and any subfolders or files in it. The script will also ask if you require localizations. If you do, localization templates for the relevant plist files will be copied to the usr/
subfolder, which you should adjust to your language(s).
You can also place a script called postinstall.sh
into your usr
folder that will be executed after each new import of at least one major version. Make sure it is executable by running chmod +x /var/root/misty/usr/postinstall.sh
in the terminal. The script will run after the misty run has finished, so you may find it useful for sed
ing plists or altering anything else that is not covered by misty itself.
During the first run, a LaunchDaemon (/Library/LaunchDaemons/de.wycomco.misty.plist
) will be enabled if not running yet. You will be asked at what time misty should run.
RepoPath
: This is theRepo URL
configured in munki. Runmunkiimport --configure
to see what is set there if unsure.Is_SMB
: Set toyes
if yourRepoPath
lives on anSMB
share.RepoUser
: Only applicable ifIs_SMB
is set toyes
. Must contain the munki user login name for the repo share.RepoPass
: Only applicable ifIs_SMB
is set toyes
. Must contain the munki user password for the repo share.RepoName
: Only applicable ifIs_SMB
is set toyes
. DNS name or IP address of the server holding the repo’s share. Not both.munki_path
: Folder path below thepkgsinfo
folder inside the munki repo. Can contain slashes for structured repos.munki_name
: Item name for the Apple Silicon and Intel munki items. The Apple Silicon preloader is handled as described in the Additional info section of the munki wiki and is suffixed by_arm
.deploy_name
: Set a custom name for deployment scenarios. Noforce_install_after_date
is set by intention. If you plan to use this key, please set it manually.munki_catalog_[major_version]
: In the first 90 days, major updates (upgrades) to a new macOS version can be omitted using MDM. To allow scoping of different staging groups, each major version can be set to a different munki catalog.munki_category
: Sets the category for all resulting munki items.localization
: Set toyes
if you support different languages other than English in your munki repository.time_input
: Enter the desired start time for automated runs.
A note on SMB shares: On an Almalinux Samba share, credentials were not needed (misty invoked by launchd was able to access the repo that was already mounted in user context). On a Windows SMB share, the share had to be mounted no matter if the share was already mounted in user context or not. So you may or may not have to enter RepoUser
, RepoPass
and RepoName
values.
During each run, the values specified in /var/root/misty/usr/config.txt
will be used. Note: When changing the start time for the LaunchDaemon in the configuration file, the value will be changed during the next run of misty.
Each run of misty compares the full versions of each major version in the Logs/
subdirectory. If no new updates are available, the script will terminate without downloading or packaging any items.
As mentioned above, mist-cli is required for running this script. Its installer creates a folder Mist
inside /Users/Shared
. New macOS versions are downloaded to that folder and munkiimport
ed from that location. After successful import, the installers will be deleted.
We also create a folder misty
under /var/root/
. Inside that folder, we have several subfolders:
skel/
: These are the template files. Do not edit files in here. misty may not work properly if the files in this directory are edited, and updates may overwrite some files too. Don’t change anything in there.usr/
: This is your place to edit configuration files to suit your needs.Logs/
: A changelog will be created and updated each time updates get imported. Also, there are files for each major version calledprevious_state_[major_version].txt
. These are looked up by misty on each run. If you want to recreate installers for a major version previously imported into the repo, please look at the Testing Methods section below.
When run as a launchd job, the log files /var/log/misty.log
(for stdout) and /var/log/misty_error.log
(for stderr) will be created.
The script misty itself is located in /usr/local/wycomo
and has an alias in /usr/local/bin/
.
The resulting payloads expect png files in the icon
subfolder of the munki repo following the naming conventions %munki_name%_version.png
with %munki_name%
being the name you have specified in the /Users/Shared/Mist/usr/config.txt
file (standard = macos) and version
being the major macOS version like ventura, sonoma or sequoia. Example: macos_seqouia.png
.
This script was tested on macOS 15 Sequoia and macOS 14 Sonoma. It should also work with earlier versions of macOS, but this has not been tested.
You should have at least 60 GB of free disk space available during the first run in order to package all three major versions.
You need to install the following dependencies:
The munki repo needs to be set up by you. In a vanilla repo, you first need to munkiimport
any item and do a makecatalogs
to initialize the all
catalog.
If you are running misty via its LaunchDaemon (advised workflow) and the munki repository is being accessed via SMB
, you need to give full disk access (FDA) to several programs, for example Zsh. This is due to restrictions in macOS. You can do so by first using the Finder’s Go To … command and enter /bin
. Scroll down to zsh
and leave the window open. Then, go to System Settings => Privacy & Security => Full Disk Access and drag and drop the zsh
binary into the System Settings window.
After that, also grant FDA using the same way described for /bin/zsh
to
/usr/bin/hdiutil
/usr/local/munki/munkiimport
/usr/local/munki/Python.framework/Versions/3.12/Resources/Python.app
If you are still facing issues, also grant Terminal.app
(located in /Applications/Utlities
) Full Disk Access. You will probably have to grant newer versions of munki-python also FDA, since you cannot use the symlink located in /usr/local/munki/Python.framework/Versions/Current
.
This is still a pre-release, mainly because of the limited set of munki repos that have been tested. Being said that, you are highly encouraged to test it in your environment and provide feedback using issues or pull requests. misty has produced installers that worked out of the box since the updates released on July 29, 2024 for us.
misty makes use of git-flow. Branch name for production releases is main, branch name for "next release" development is dev. The version tag prefix is v. All other values are the default ones. You can install git-flow using homebrew by entering brew install git-flow
in the terminal.
misty will do nothing if it thinks all is up to date. If you are up to date with all three major versions in the repo, you can do the following:
- In the repo, rename the dmg file of the macOS installer to an earlier version. Then, rename all plist files of that version, too. Edit each plist file so the
item_installer_location
is updated to the name of the renamed dmg file. Don’t forget to also adjust theversion
string at the bottom of the files. This will ensure that the removal of older versions (at least two) will get tested. - Alternatively, just delete all plists and the corresponding dmg. If you followed step 1, ignore this step.
- Do a
makecatalogs
on the repo. - For each major version that you altered or deleted, you need to edit the file
/Users/Shared/Mist/previous_state_[major_version].txt
. Just change the current version key to another number. You need root permissions for that. - Then you can run misty manually or wait for the LaunchDaemon to do its job.
- The reload of the launchdaemon does not work if misty was invoked by its launchdaemon. Please run misty in Terminal using
sudo misty
if you have changed the start time in the config file. This will trigger a proper reload of the daemon (and do nothing else unless a new macOS version is found).
This is a pre-release. It is working, but we have some tasks on our to-do list:
- Testing in different environments.
- Ensure all items that require FDA are mentioned.
- Function
rm_previous_files
states one previous version when no previous version is available. - Improve message and log output.
- Harmonize variable names.
- Improve code readability in general.