Now, all MacAdmins are waiting for Monday, when macOS Mojave will be released. Well, most will alredy have the last version from the beta program installed. But, as with every other major release, it will be ‘interesting’ to see how well the beta testing holds up to ‘real world’ deployment.
Arek Dreyer:
“If you have two different versions of macOS installed on your Mac, guess which version of macOS Recovery you get when you shut down, power on, then press and hold Command-R? The version you set in Startup Disk (regardless of Startup Manager choice).”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
iOS 12 release week. With all new releases for the entire iOS family there is a boatload of new features, support articles, user guides and references.
Even most of the features and guides are focussed on the end user and not admins, it is often also the job of a MacAdmin or consultant to be the most knowledgeable person on the OS, so these should be useful. And, admit it, while new OSes can be a pain for admins, but are still fun as an end user.
If you have any links that I missed that should be part of this list, then let me know and I will update this post.
Reviews
There is obviously a neverending stream of reviews out there. I like the excellent reviews from MacStories.
Many organisations like to set or pre-set the Desktop Picture of managed Macs. There are a few options for Mac Admins.
One of the commonly used methods may break in macOS Mojave because of the new security and privacy controls for AppleEvents, also known as TCC.
Getting the Image File to the Mac
Unless you want to use one of the default macOS Desktop Picture images, you will first need to get the image file on to the client. The best way of doing that is with an installer package.
Note: installing a single image file to /Library/Desktop Pictures is actually the first exercise/example in my book “Packaging for Apple Administrators.” Get that for a more detailed description.
I will use the same example desktop picture as in the book. You can use your own desktop picture or download BoringBlueDesktop.png from the book’s resources.
Note: Desktop pictures on macOS can be many file formats. PNG and JPEG are most commonly used. The new dynamic desktop pictures of macOS Mojave have the heic file extension.
First create a project folder, with a payload folder inside:
$ mkdir -p BoringDesktop/payload
$ cd BoringDesktop
The resulting pkg file will install the image file in /Library/Desktop Picture.
Note: the pkgbuild command has many options and arguments. If you get one of them slightly wrong it can lead to unexpected behavior or even break the installation. I recommend using a script to run the pkgbuild command to avoid errors. You can find a sample build script here. Read the book for a more detailed explanation of pkgbuild and the build script. If you prefer, you can use munkipkg, which also simplifies and automates the process of building pkg installers.
This will provide the image in a location that the user might look for. However, for better management you want to set the desktop picture as well.
Lock Down the Desktop Picture
Once the image file is in place. You can set the desktop picture with a configuration profile. Many management systems will have an option in the ‘Restrictions’ payload where you can set the path to the desktop picture.
With this configuration profile in place, the desktop picture is locked. The user can still open the Desktop preference pane but the selection will be ignored. You would need to be able to remove the profile to change the desktop picture again.
This is very useful in education and other strictly managed environments.
Suggesting a Desktop Picture
In other, less tightly managed environments, you might prefer to set an initial desktop picture, but allow the user to change it later.
The common means to do this has been to use an AppleScript command:
tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/BoringBlueDesktop.png"
If you want to run this from a shell script you would execute it with osascript:
osascript -e 'tell application "Finder" to set desktop picture to POSIX file "/Library/Desktop Pictures/Sierra.jpg"'
Note that this sets a user preference so it should be run as the user. See this post for details.
However, with macOS Mojave, Apple is introducing new Privacy and Security measures which require user approval for processes to send AppleEvents. This will put a severe limit on the use of osascript for admin scripts.
One solution would be to whitelist your management system’s agent which allows it to send Apple Events to the Finder. This requires managing the client with a user-approved MDM.
Another solution is to avoid AppleScript and Apple Events entirely.
Here comes the desktoppr!
To do this, I wrote a simple command line tool which can read and set the desktop picture. Neil Martin had the brilliant idea to call it desktoppr.
Since the desktoppr tool also sets user preferences, you still need to pay attention that it runs as the user.
For example, you could run desktoppr from a LaunchAgent (deployed in /Library/LaunchAgents so it affects all users:
This LaunchAgent will reset the Desktop Picture at every login.
If you want to set the Desktop Picture just once from a management or postinstall script (probably running as root) you can use the following to be safe:
When you find yourself building LaunchAgents or LaunchDaemons often (i.e. more than once) you should really consider using outset.
If you wanted to build an installer package that drops both the picture file and the LaunchAgent, you can do the following:
We got new iPhones and Apple Watches this week. You can read all about them in all the usual places. More importantly for admins, we also got release dates for iOS 12 (September 17) and macOS 10.14 Mojave (September 24). Are you ready?
The developer releases for the iOS family (iOS, tvOS, watchOS) are now labeled GM. macOS Mojave is beta 11.
Other than the Mojave release date, there was no Mac news at the iPhone event. This shouldn’t surprise or dismay anyone. The September iPhone event has been fully focussed on iPhone and Apple Watch for the last few years. This year, there wasn’t even room for the iPad. There may be some ‘silent’ Mac hardware releases over the next few weeks or Apple may even do a second event. While Apple has had November and December releases in the past, they are rare.
Keep in mind, that any new Macs that are released after the Mojave release date will likely require Mojave. The release window for new Macs that can still run High Sierra is very, very short indeed. Next week should be interesting.
William Smith: “TOMORROW (Tuesday, September 11) Office for Mac transitions from the 2016 to the 2019 generation. Office 365 customers: Nothing to do. Volume License customers: AutoUpdate will hold apps back until the new Serializer is available September 24. Don’t push 16.17.”
Erik Gomez: “Apple: we don’t understand why you built umad, but okay… Me: because there’s so many MDM enrollment bugs!”
mikeymikey: “hey fruitco peeps Why isn’t 18A389 released on MAS? SUS feeds were updated and delta updates published – but no full installer app exists via “approved” download methods. MAS is still offering the prior product build. Kind of an important time for testing beta 11”
William Smith: “For #MacAdmins using MAUCacheAdmin to cache Microsoft Office for Mac updates to a local server for distribution, be sure to download v2.0 to get support for Office 2019 (16.17+) for Mac. GitHub”
Felix Schwarz: “AppleScript support still hasn’t returned to Mojave’s rewritten DVD Player app as of beta 10. It was super-useful for remote apps to determine when a menu is shown, to eject DVDs, etc. Would make me sad if that change was permanent & something I’m working on couldn’t use it.”
Carl Ashley: “Updated tccprofile.py to fix an issue where a bad codesign output would trip up the script. GitHub”
To Watch
William Smith: “Streamlined Microsoft Office for Mac Activation with Automatic Outlook Setup for Office 365 Thanks to @jeffreykalvass and his team for listening to #MacAdmins and making Outlook for Mac manageable with configuration profiles. Now in Insider Fast v16.18.”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
This week most of the Mac Admin news was about the imminent “AEpocalypse” or the effect of the new privacy and security controls in macOS Mojave on scripts and applications that send Apple Events.
Also Microsoft changed the OS requirements for Office after they got much feedback from the community, including many admins. (So, yes, talking to your reps and filing bugs, does sometimes help!)
Howard Oakley: “As fas as I can test in ß10, AppleEvents aside, the system now works as explained at WWDC, from a user POV. Corrections welcomed – full article on blog tomorrow…” (Click for diagram)
Erik Gomez: “Most #macadmins have considered homebrew harmful for many reasons.… ” (Thread)
Uluroo: “Mac users: With the release of macOS Mojave on the horizon, let’s talk about the bits of macOS that haven’t changed in a while, that we’re surprised still exist, and that are fun little Easter eggs.” (Thread)
Caleb Coy: “#macadmins Slack team just hit the milestone of 20,000 registered members. Some will nit pick and argue that register != active. Frankly, I don’t care. This is pretty amazing.”
Jeremy Reichman: “User approval is definitely at the intersection between liberal arts and technology.”
Graham R Pugh: “‘erase-install’ has new automation options: 1. Auto-download your current system version’s macOS installer, or the latest prod version. 2. Move the installer to /Applications for later use. 3. Use, or overwrite, an existing installer at /Applications”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
This article is not quite the bombshell that the infamous HT208020 for High Sierra is. However, in contains a few firecrackers which will affect many Mac deployments. You can test deployments with the public beta or developer release of Mojave right away.
The piece of information I want to focus on for this post affects Apple Remote Desktop client configuration (called ‘Remote Management’ in the ‘Sharing’ preference pane). Mac Admins have been using the command line tool kickstart to enable and configure Apple Remote Desktop access on clients with scripts through a management system.
In macOS Mojave, Apple will restrict the functionality of kickstart:
For increased security, using the kickstart command to enable remote management on a Mac will only allow you to observe it when sharing its screen. If you wish to control the Mac while sharing its screen, enable remote management in System Preferences.
This continues Apple’s effort to require user interaction for every configuration that can provide on going access to sensitive data or the system a Mac, like User-Approved MDM and the new privacy controls.
What this means for Admins
If you rely on Apple Remote Desktop for remote control and remote assistance, this will disrupt your installation workflow. The kickstart tool will enable ARD access and configure the users but not enable any access privileges.
You get a nice (red) warning in the shell and when you go into the Remote Management preference pane, no active access is enabled. You can only manually enable the access privileges in the ‘Sharing’ preference pane, which requires administrator privileges to unlock.
You can still use kickstart to disable Remote Management access.
This limitation extends to Screen Sharing. You can enable Screen Sharing (when ARD/Remote Management is disabled) from the command line with:
You have to restart System Preferences to pick up the change in the UI. This command will enable Screen Sharing access, but it will be observe only. (Note: you can use launchctl unload ... to disable.)
When you enable Screen Sharing manually in the ‘Sharing’ preference pane, it will grant full access.
Workarounds
I have (so far) been unsuccessful in determining where the restricted access setting is stored. My suspicion is that the TCC database is involved. If the setting is controlled from a protected settings file or database, then you can at least read that to determine the state and use that information to trigger a notification to the user that action is required. So far, however, I cannot get this information yet.
If you find any means of determining the state, please let me know and I will update this post.
Unfortunately, Apple has provided no alternative means of controlling screen sharing or ARD with configuration profiles from a UAMDM, leaving admins stranded without an automated solution.
Admins that require ARD or Screen Sharing will have to rely on users actively enabling the settings. To make things worse, unlike the approval of an MDM profile or a kernel extension, the ‘Sharing’ preference pane is locked for standard (non-admin) users.
You can either provide a way for users to be temporarily promoted to admin or modify the Authorization database to allow standard users to unlock the ‘Sharing’ pane. However, unlocking the Sharing pane allows access to many more critical services, which is untenable from a security perspective.
It will have to be seen how this affects third party remote access applications. I have tried setting up Edovia Screens Connect on my Mojave virtual machine, but that currently uses the native Screen Sharing/Remote Management client, so it will encounter the same limitations. Other third party tools may have their own clients.
As usual, please, provide your feedback to Apple through the usual channels (macOS beta Feedback app, bugreport, your Apple representative, SE or technical support).
Things are heating up in the iOS 12 and macOS Mojave beta cycle. Apple has announced an event on September 12, which will presumably present the new iPhones and Apple Watch. There may or may not be new Macs at that event, though in the past Apple would often have a second event later in the fall.
From the September 12 date and the schedule of past years, you can extrapolate the release dates and you will realize that we merely have weeks and not months left.
Even more concerning is that Apple has just recently released working versions of the profile payload to control the new privacy settings, especially for Apple Events. You can learn the details in this excellent post by Felix Schwarz. I need to highlight this piece from his summary:
I feel, though, that the most responsible way for Apple to handle this situation would follow the playbooks for Group FaceTime and 32 Bit deprecation: postpone the feature until it has matured – and make it available to developers behind a feature toggle until then.
Also, minor milestone: this newsletter has passed 300 subscribers! Thank you all for reading and recommending! (and don’t stop spreading the news!)
Aron Griffis: “Working on a new Bash book. So far: Intro: You chose the wrong tool. Ch 1: Have you considered Python? Ch 2: Try calling Python from your Bash script. Ch 3: If you’re still here, try adding quotes.”
Jason Broccardo: “Tea leave reading: Once Apple is shipping Macs with their own A-series ARM chips, VMware Fusion will still works”
MacDevOpsYVR: “The next MacDevOps:YVR conference will be in Vancouver, Canada, June 12–14, 2019”
Zack McCauley: “Per @Contains_ENG recommendation to post this #MacAdmins please @Apple give us documentation, give us feedback, and for the love all that is left please don’t give us a feature that makes this so much worse on users” (Video)
Jason Broccardo: “Sys Admin’s idea of winning the lotto: You automatically get elevated past tier 1 on any support call because you’ve already covered all those steps in your troubleshooting before you filed a ticket.”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
Thomas Reed: “There appears to be an issue in macOS where removing the ‘restricted’ flag from /Library/StagedExtensions/ causes installation of kernel extensions to always fail.”
Guillaume: “If you’re part of a IT or security team managing Mac, make sure you watch at least one of these talks before every Mac out there has a T2 Chip! https://t.co/1MGo5zqPk1 by @gregneagle And https://t.co/kIdpnP5xwh by @grahamgilbert”
Laurent Guigo:
“after .local now .dev extension not enable for localhost develop built in server (no ssl)”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!
As MacAdmins our goal is to automate workflows when ever possible. The advantages of automation are great. You immediately reduce the workload, but also reduce the potential for someone to make a mistake, which would mean even more work later.
In nearly all cases, we want the automation to happen “magically” in the background, without any user interaction. User interaction slows down the process as the script is waiting for the user to confirm or enter data. User input also requires validating and checking user entered data.
In most cases, when you believe you need to prompt the user for, well, anything, you should take that moment to re-think your workflow. Maybe you can come up with a different workflow that can provide the data from a source that can be automated without user interaction.
If, however, you really are convinced that user interaction is necessary, then you need be aware there are many potential pitfalls in writing shell scripts with user interaction.
macOS Mojave will introduce even more pitfalls with its increased security features.
Do you really need UI?
A common example for user interaction is to get and set the Computer Name or Asset Tag/ID/Number from manual input.
This is a task that can be fully automated in many situations. As an admin you could provide a text file mapping serial numbers to a name and/or asset tag on a server, that a script can download (curl) and parse. If you have a management system or asset database, there is probably an XML or JSON API, you can use to retrieve this information from a script. You could read or scan the serial numbers from the labels of the Mac’s boxes or even get the list with the purchase order from most vendors. With that data you can pre-fill your text files or databases.
However, in some cases, especially DEP workflows it may be difficult or impossible to predict which computer will end up on which desk, especially with zero-touch deployment workflows, where a device can be sent to a user directly.
In this case, you have to question whether you need a unique, specific computer name or asset tag. Maybe the data which your management system already gathers, such as the user who enrolled the device and its serial number will (have to) be sufficient?
In many cases, however, the reasons to prompt for and set a computer name will not be technical but stem from other, external factors that the IT department may or may not have influence on.
AppleScript’s Moment of Glory
bash was built to run in a text based terminal on many different operating systems. It has (and should have) no concept of a graphical user interface. bash alone is not useful to interact with the user, unless you want to open a terminal window.
However, AppleScript does have some (basic) commands to present dialogs and notifications to the user. We can call AppleScript command from the shell with the osascript command (OSA = open scripting architecture, the underlying framework that AppleScript uses)
There are other tools that allow to display user interface from a shell script. However, they all require an additional installation. AppleScript/osascript is simpler and built-in to the OS, so it is my first choice. That doesn’t mean it is always the appropriate choice, though.
You can go to Terminal and make a dialog appear with
$ osascript -e 'display dialog "Hello from bash!"'
The display dialog AppleScript command is documented in the “StandardAdditions” dictionary. You can see it when you choose ‘Open Dictionary…’ from the File Menu in Script Editor. Then select the “Scripting Additions.osax” dictionary and choose the “User Interaction” category.
This command has a lot of options that allow us to configure the dialog. You can experiment and test with these commands in the Script Editor application. For example, you can change the names of the buttons:
display dialog "Are you sure!?" buttons {"No", "Yes"}
display dialog "The answer is C" buttons {"A", "B", "C"} default button 3
button returned:C
The script will return which button the user clicked. However, instead of parsing the output with shell tools, you should let AppleScript do the work:
button returned of (display dialog "Are you sure!?" buttons {"No", "Yes"})
The choice variable will be No or Yes.
Adding icons
You can also add an icon to the dialog:
display dialog "Hello" with icon note
Will show the current application’s icon. You can also use stop or caution for different icons.
You can also add a path to an icns file:
display dialog "Hello!" with icon POSIX file "/Applications/Notes.app/Contents/Resources/AppIcon.icns"
Asking for Input
In some cases you want to get information back from the user. You can add a text field to the dialog with the default answer argument. The default answer can be an empty string:
display dialog "Who are you?" default answer "nobody"
display dialog "Who are you?" default answer ""
You can get the result of the dialog with the text returned property:
text returned of (display dialog "Who are you?" default answer "nobody")
You can combine the default answer argument with all the above arguments as well.
Notifications
In some case you just want to notify the user that something happened, and not stall everything while the script waits for confirmation. You can use display notification for these situations:
display notification "Hello, again" with title "Hello"
Running from Shell
You can execute AppleScript from the shell with the osascript command.
osascript -e 'display dialog "Hello!" with icon note'
This works well enough. You also use shell variable substitution:
title='Hey, there!'
osascript -e "display dialog \"What's up?\" with title \"$title\""
When you use variable substitution, you have to use double quotes for the command strings. And then you have to escape any additional double quotes in the AppleScript command. With more complex commands and arguments this will get unwieldy very quickly.
In a bash script you can use a here document instead:
title='Hey, there!'
osascript <<-EndOfScript
display dialog "What's Up?" with title "$title"
EndOfScript
You start a here document with the <<- characters followed by a limit string of your choice (I chose EndOfScript). Then all the text until the limit string is repeated will be fed into the osascript command.
Bash variables will be substituted in the here document, so $title will be substituted with its contents.
Note: I prefer the <<- syntax over the << syntax with osascript. The <<- syntax will ignore leading white space in the following lines, allowing me to properly indent the AppleScript code, making the entire script more legible.
The Trouble with root
Management scripts will run with root privileges. They may also be run in situations where no user is logged in. AppleScript requires a user to be logged in (and a window server to be present) to display the alert.
In many situations all of this will ‘just work’ even when the script is executed from a root process, in others, the script will fail. It is generally safer to always check the current user and run the osascript command as the currently logged in user. You can learn about how and why to do this in this article on ‘Root and Scripting’.
This also gives your script an option to continue silently or fail when no user is logged in.
user=$(python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");')
if [[ $user != "" ]]; then
uid=$(id -u "$user")
launchctl asuser $uid /usr/bin/osascript -e "button returned of (display dialog \"Hello\")"
fi
Putting it all Together
While all of these examples are simple enough, you can already see that, once you consider all the possible combinations, everything will get fairly complex.
Over time I have put together a few bash functions that I use in my scripts. Even they only cover quite simple workflows, but can be useful as a sample for more complex needs:
System Events, Privacy and macOS Mojave
In many scripts the author wraps the display dialog command wrapped in a tell statement:
osascript -e 'tell app "System Events" to display dialog "Hello"'
The reason for this is that it will ensure that the dialog is displayed on top of all other windows. The activate command will push the targeted process to the front. Both “System Events” and “Finder” are used frequently.
In most cases this is not necessary, as the dialog will properly display on top of all other windows, even as a standalone command. There may be some weird conditions when other applications are launched in the same time frame, though. In other cases it may be better to use display notification, anyway.
In macOS Mojave, Apple Events (AppleScript Commands) can only be sent to another application with user permission.
When you try this command in macOS Mojave, the user will be prompted to allow the Terminal application to control the System Events application
If the user denies this request, the osascript command will fail with an error:
$ osascript -e 'tell app "System Events" to display dialog "Hello"'
28:50: execution error: Not authorized to send Apple events to System Events. (-1743)
Once a user has denied access, they will not be prompted again. They will have to go to the ‘Privacy’ tab in the ‘Security & Privacy’ pane in System Preferences, search for ‘Automation’ and allow access for Terminal.
However, management scripts will usually not be executed from Terminal, but from within the context of an installation script or management agent. It may be possible to pre-approve configurations with a UAMDM configuration profile, but it will be impossible to anticipate all contexts in which your scripts may run.
For macOS Mojave it will be better to either modify your script to not wrap the command in a tell statement. Alternatively, you can use a different solution for the UI altogether. (e.g. jamfHelper, Yo, Pashua or CocoaDialog)
All of these wrapped commands in scripts will break in macOS Mojave!
MacAdmins need to go through all their management scripts and check for AppleScript UI commands wrapped in tell statements.
When you use the standalone display dialog it will be the AppleScript process itself that displays the dialog. This requires no specific permission.
Even if your dialogs may not appear on top of all the windows, this is a preferable solution.
This will also affect scripts using osascript to control or receive data from other applications.
Summary
question and revisit every use of user interaction in your workflow
when you really have to, you can use osascript with the display AppleScript commands
to be safe, run the commands as the current user
increased macOS Mojave security will require you to verify all your scripts using osascript
Days are getting shorter, summer is starting to wane, and the Apple System release date is getting closer and closer.
Apple released new betas and finally updated the MDM and Configuration Profile References, leaving MacAdmins little time to test and file bugs to be fixed. MacAdmins took to Twitter to complain.
Also Twitter finally turned off many API features, thus crippling third party Twitter apps TweetBot and Twitteriffic.
If you are considering moving away from Twitter – there certainly enough reasons, technical and non-technical – Scripting OS X and this newsletter are available on many other channels, including Micro.blog, Mastodon.social, and Apple News. You can find all ways to follow at the end of this post.
Objective-See: “Announcing ”Objective by the Sea“ a new Mac Security Conference: Nov 3rd/4th in Maui Hawaii @ the stunning Wailea Beach Resort Talks by @thomasareed @iamevltwin @patrickwardle @rrcyrus @jbradley89 & more! …and free for Objective-See patrons”
Erik Gomez: “Apple releases MDM changes on beta 7 and asks for feedback/regression testing. The reports wont be fixed in 10.14.0. Remember when you warned people to get tickets in before beta 2 to ensure they make it into the GM? These changes should be delayed to the Spring Release”
Erik Gomez:
“#macadmin #macadmins – if you’re interested in testing some important changes coming to Mojave, please join the #tcc channel on macadmin’s slack Also here is a google doc for tracking this, much like we did with kexts/32-bit apps https://docs.google.com/spreadsheets/d/1sai3Q8qj9HdyDJfcSAchRELD0mOpik1NPYxr0F9AJRc/edit#gid=0”
Tim Sutton: “If you would ever like the automated creation of a macOS Mojave system image to be possible – (asr imaging or creation of VMs via vfuse or similar).. you may want to dupe Mike’s rdar quoted below, and/or mine: http://www.openradar.me/radar?id=5004136198176768”
Per Olofsson:
“I posted a new beta of AutoDMG with a couple of Mojave workarounds”
mikeymikey: “Honestly – between you and me – with what this bug does and what beta 7 just added, 10.14 feels like it’s shaping up to be “10.13 Part 2” / “The Revenge of 10.13” for #macadmins”
William Smith: “New installs of Office for Mac 16.16 (this month’s release) and higher will install Microsoft AutoUpdate 4.2. Going forward, it will default to Automatically Download and Install. #MacAdmins, if you need to manage this, the best method is use a configuration profile.…”
There are no ads on my webpage or this newsletter. If you are enjoying what you are reading here, please spread the word and recommend it to another Mac Admin!
If you want to support me and this website even further, then consider buying one (or all) of my books. It’s like a subscription fee, but you also get a useful book or two extra!