Installomator updated: v0.2

It’s been nearly a month since I introduced Installomator.

Since then, it has gotten lots of feedback from others and many contributions. As the changes, fixes and additional apps have accumulated, I have created a 0.2 release to get a stable new version. If you like living on the edge you can also use the dev branch for the latest update.

Changes in this version:

  • many fixes for broken URLs and other bugs
  • pkgInDmg and pkgInZip now search for the first pkg file in the archive in case the file name varies with the version
  • notification on successful installation can be suppressed with the NOTIFY variable
  • Apple signed installers and apps that don’t have a Team ID are verified correctly now
    improved logging
  • several new applications: count increased from 62 in v0.1 to 87 in v0.2

Thanks to all who contributed!

Also, if you haven’t already, you want to read Mischa’s guest post on using Installomator with Jamf Pro.

Weekly News Summary for Admins — 2020-08-05

“So, do you think one day robots will have human rights?”

“Perhaps,” the robot said, “but first I want to see all humans have human rights.”

“What do you mean? All humans do have human rights. It’s in the name.”

“Then I first want to see all humans considered human.”

“Oh. Yeah.”

(Micro SF/F stories)

📰News and Opinion

🔥MacAdmins 2020 Campfire Sessions

These are the slides and notes for yesterday’s sessions. The recorded videos will be made available soon.

You can still register for the upcoming sessions. You can see the schedule here. (Yes, that is me presenting next week on “Moving to zsh.”)

⚙️macOS Catalina 10.15 and iOS 13 Updates

🦠Coronavirus and Remote Work

🐦MacAdmins on Twitter

  • Arroz: “macOS supplemental update: 1.59 GB. iOS minor update: 77 MB. It almost seems like someone cared enough to implement an efficient incremental update… for just one of the platforms.”
  • Victor (groob): “Apple should remove package scripts. Rather than removing though, I’d love to see a stricter API. Scripts would be great with an embedded language like starlark.”
  • Darren Wallace: “New Apple Business Manager (only) Terms and Conditions incoming on the 16th June 2020. Must be agreed to continue with Automated Enrolments and Volume Distribution. The updated terms should already be viewable here.
  • Tim Sutton: “Whoever at Apple decided that all of system_profiler’s datatypes arguments should redundantly contain SP and DataType, and that they be case-sensitive..”
  • Eric Holtam: “Any developer that wants to know how to provide release notes see BBEdit. This. This is how you provide release notes.

🐞Bugs and Security

🔨Support and HowTos

🤖Scripting and Automation

♻️Updates and Releases

📺To Watch

🎧To Listen

🎈Just for Fun

📚 Support

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!

Using Installomator with Jamf Pro

I introduced the Installomator script a while back. We have been using the script with our own Jamf Pro server and some of our customers.

Since I built the script, you’d think I’d have pretty good idea on how it should be deployed. But then Mischa van der Bent showed me a better way of using Installomater with Jamf Pro and I asked him to write it up for a blog post. Since he doesn’t have a blog of his own (yet), he has allowed me to post his instructions here.

Note: Installomator is designed so it can work with other management systems, too. If you have implemented Installomator with a different management system, let me know!

Everything that follows is from Mischa:

Preparation

After you have downloaded or cloned Installomator from Github, you can run Installomator.sh from the command line or from your management system:

> ./Installomator.sh googlechrome

The script requires a single argument: a label that chooses the application to download and install. (you can find a list of labels of applications in the Labels.txt file in the repository)

Adding the Installomator Script to Jamf Pro

The first thing we need to do is create a new Script in Jamf by going to Settings > Computer Management > Scripts.
In the General section you can give the Script a Display Name. I called mine Installomator. Assign a category and add the link to the GitHub repository to the notes as a reminder of the source of this script.

In the Script section, paste the entire code from the Installomator.sh file.

Important: Change the DEBUG variable from 1 to 0 for using Installomator in procduction, otherwise it will not actually install the new software.

The script requires a single argument and designed to use argument 4 from Jamf when present.

We can set the Parameter Label of parameter 4 to “Application name” in the Options section. This is going to be a reminder that we need to fill in the argument when we are creating a policy. You can leave the labels for the other parameters empty or fill in “DONT-USE” because the script does not use the other arguments.

We are done here and you can save the Script.

Scoping

To make sure that we are targeting to the right devices with an older release version we need to create a couple of things.

I’m going to use Jamf Patch Management to determine the latest release version of Google Chrome. Jamf will check the version before publishing this into the Patch Management. And if the software title is not in Jamf default Patch Management list you can create your own Patch Management source and add this on to Jamf Pro. You can also join the community patch server.

Go to Patch Management under Computers > Content Management and create a New Software Title. We are going to use Jamf Repository. Scroll down the list and select Google Chrome.
The only thing we need to set here is the Software Title Settings and assign a Category. You can select the Jamf Pro Notification option to get emails when an update is posted..

Jamf Patch Management will query the inventory and list the clients where Google Chrome is installed and their versions. We now have the all the information we need!

Two Smart Computer Groups

Go to Smart Computer Groups and create a new one. I called this “Google Chrome not installed or out of date”

In the ‘Criteria’ section I add two criteria:

  • Patch Reporting Software Title: after choosing this select the right report; for our example select “Patch Reporting: Google Chrome”
  • change the ‘Operator’ to “Less than” with the ‘Value’ “Latest Version.”
  • add a second line and Changed the AND/OR to “or” and for the second criteria I used “Application Title”
  • change the ‘Operator’ to “does not have” with the ‘Value’ “Google Chrome.app”

This Smart Group will contain the clients where the application is not installed or is not up to date.

Unfortunately, we cannot use this smart group with a Policy. When you try you will get this error ‘Policy scope cannot be based on a smart computer group that uses the “latest version” criteria.’

But there is a work around:

  • create a second Smart Group, I called this one “Member of Google Chrome not installed or out of date”
  • in the ‘Criteria’ section add the criteria “Computer Group” changed the ‘Operator’ to “member of” with the ‘Value’ to “Google Chrome not installed or out of date”

The result is the same as the Smart Computer Group “Google Chrome not installed or out of date” but we can use this in a policy.

Policy

Let’s put all the bits and pieces together and create one policy that will install or update to the latest release version of Google Chrome. We also want to promote this in Self Service and we want to push this out as a mandatory update with a deferral duration of 7 days.

  • go to Policies and create a new one. I called this policy “Google Chrome”
  • use “Recurring Check-in as the trigger, and set the custom event value to ”googlechrome.” With the custom trigger name, we can use this policy in a script or can test with the terminal command sudo jamf policy -event googlechrome -verbose
  • set the ‘Execution Frequency’ to On-Going.
  • add the Installomator script to the payload
  • the Priority doesn’t matter, because there is no package, so leave it default ‘After’
  • in the Parameter values you see that the first one is ‘Application name’ (which we set earlier). Set “googlechrome” as value.

I removed the payload “Restart Options” because we don’t need to restart after we install Google Chrome , we can leave it there, but I like to keep my policies clean.

We need to report back to the Jamf Pro Server that we just installed the latest version so we are going to add the payload “Maintenance” and enable “Update Inventory” (this should be enabled by default).

We are done with the payload and need to set the Scope:

  • under target we add the Smart Computer Group: “Member of Google Chrome not installed or out of date”

Self Service

  • enable “Make the policy available in Self Service”
  • leave the Display Name the same as Policy.
  • Button Name Before Installation: use “Install”
  • Button Name After Installation: use “Update”
  • give a Description to display for the policy in Self Service like “Install or Update to the latest release of Google Chrome”
  • upload or select the Google Chrome icon for making the Self Service pretty (you can use the macOS Icon Generator app)
  • under User Interaction we change the Deferral Type to “Duration” and use 7 days.
  • we don’t need to set a Start or Complete Message (Installomator can notify on success)

Now, we can save and test the policy.

Testing

I tested this Policy with a couple of scenarios;

The first scenario is: no Google Chrome installed. Second: old version Google Chrome installed, notification for update, end user deferral, and later installation from the Self Service. Third: Google Chrome Beta is installed

The first scenario is easy, after running the policy latest version get installed.

In the second scenario I got prompted with the following message, and I submitted 1 hour.

I can’t install this update before the hour because I got this message in the jamf log “Policy ‘Google Chrome’ will not be executed because it was deferred by the user.”

The last scenario I installed the Google Chrome Beta version 84.0.4147.30, the latest version in Patch Management (for this moment) is 83.0.4103.61. This beta version registers as an “Unknown Version” and it will not fall into scope.

I can use this policy with the Installomator script to install the latest version on a clean machine, and I can push out an update (with a deferral time) to push a mandatory update in a polite way 😉

Because Installomator is checking the Developer Team ID of Google directly, I can be confident that it is the real installer from Google. So, we get security with less effort.

Weekly News Summary for Admins — 2020-05-29

Update week, part 2. macOS Catalina 10.15.5 dropped this week. Among many other changes, it contains an important change to softwareupdate --ignore which seriously affects MacAdmins.

As always, many thanks to those who are providing better update information than Apple. Especially: Mr Macintosh and Howard Oakley.

The conference schedule has been seriously affected by the pandemic. The silver lining here is that with all the conferences. Thanks to the MacDeployment YYC twitter post we have a virtual conference line up:

I will be presenting at at least two of these: a Campfire Session on June 11 on ‘Moving to zsh’ and ‘Practical Scripting’ at MacSysAdmin Online.

MacAD.UK is, as of now, still scheduled to occur in person on November 3 and 4.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

macOS Catalina 10.15 and iOS 13 Updates

Update Information

MacAdmins on Twitter

  • William Smith: “A gift to your future self (and others)… Use shortcuts like -s and -v for command options in your daily Terminal work to save you time and keystrokes. But use the full names of command options in your scripts to better explain what you’re doing.”
  • Tim Perfitt: “I wrote a shell script that gets the DEP record if you give it a Mac serial number. Here is what it does: Puts serial into VMWare image config Starts up VM SSH’es into VM and runs command to print DEP record (ssh keys set up prior) shuts down VM runtime is about 30 secs.”
  • Hannes Juutilainen: “If a folder name ends with .noindex it will not be indexed by Spotlight. And if a folder name ends with .nobackup it will not be included in Time Machine backups.”
  • Joel Rennich: “So… you’d like to find out if your IdP vendor supports Apple’s Single Sign On extensions? All SSOEs need to have an Apple App Site Association file hosted at the endpoint URL that the SSOE wants to be authoritative for.” (Thread)
  • Joel Rennich: “The only publicly available Apple SSO Extension that I’m aware of is Microsoft’s MSAL library with their latest Authenticator app from the App Store. Currently in public preview and only on iOS.”
  • Graham Gilbert: ““Major new releases of macOS are no longer hidden when using the softwareupdate(8) command with the --ignore flag” tldr: if you don’t patch, you’re vulnerable. We’re trying to improve your security. Finally something I agree with, well done @apple” (counterpoint)
  • Simon Carlson-Thies (LinkedIn): “Zoom has a seriously odd way of dealing with preferences…” (link for more)

Bugs and Security

Support and HowTos

Scripting and Automation

Updates and Releases

To Listen

Support

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!

Weekly News Summary for Admins — 2020-05-22

Update week, part 1! iOS 13.5 and siblings have arrived. macOS Catalina 10.15.5 GM was released to seed and beta testers, so probably next week?

I will be talking at the “Virtuele Macbeheerders bijeenkomst” (Virtual MacAdmins Meeting, which you probably could have guessed) about Installomator next week. Warning: other than mine, all sessions will be in Dutch, but they sound very interesting.

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

📰News and Opinion

⚙️macOS Catalina 10.15 and iOS 13 Updates

🦠Coronavirus and Remote Work

🐦MacAdmins on Twitter

  • Mactroll: “A heavily contrived, but still fun, example of using a Managed Apple ID with a Single Sign on Extension. A story in a few parts, but first the video…” (Video, thread)
  • Mactroll: “More SSO Extension fun! This time signing into an O365 application, Powerpoint, and activating the subscription.” (video, thread)
  • William Smith: “MacAdmins, support for Microsoft Office 2016 for Mac ends October 13, 2020 (five months). Plan to move to a Microsoft 365 subscription for your organization or upgrade your volume license to Office 2019. Announcement from December 2019
  • Patrick Fergus: “Support for 27 languages in Outlook for iOS being removed at the end of June 2020. Office 365 Message center MC213632.”
  • Jeff Johnson: “This is an interesting chart. 10.15 adoption seems to be significantly lower than 10.14 or 10.13.” (Chart, thread)

🐞Bugs and Security

🔨Support and HowTos

🤖Scripting and Automation

🍏Apple Support

♻️Updates and Releases

📺To Watch

🎧To Listen

🎈Just for Fun

📚 Support

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!

Weekly News Summary for Admins — 2020-05-15

Lots of security related news with a new thunderbolt exploit (mostly on Windows, but macOS is not entirely unaffected) and a nasty exploit for Acrobat Reader DC.

Many were expecting 10.15.5 to drop this week, but unless it comes on Friday afternoon, we will have to be more patient. But Apple continues to release something new every week, with a new “major” update to Logic Pro X. (What do versions numbers even mean anymore?)

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

#! On Scripting OS X

📰News and Opinion

🦠Coronavirus and Remote Work

🐦MacAdmins on Twitter

🐞Bugs and Security

Macs are fully vulnerable to all of the Thunderbolt security flaws when running Bootcamp, and ‘partly affected’ when running macOS.

🔨Support and HowTos

🤖Scripting and Automation

🍏Apple Support

♻️Updates and Releases

📺To Watch

🎧To Listen

📚 Support

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!

Introducing Installomator

As a System Engineer at an Enterprise Reseller, I have to manage and create many Jamf Pro instances.

Some of them are tightly managed and require version control on the OS and the apps. But, many of them are managed less stringently and often the requirement for applications is “install the latest version.”

This is not a statement which management strategy is ‘better.’ There are pros and cons for each. There are situations where either is really not appropriate. You will likely have to use a mixed approach for different pieces of software. When you are doing the first, more controlled deployment strategy, you really want to use AutoPkg and not this script. You can stop reading here.

Apple’s vision of deployment with ‘Automated App Installation’ through MDM (formerly known as VPP) is similar to the ‘less controlled’ strategy. When you install Mac App Store through MDM commands, then you will get the latest version available.

Not all applications are available on the Mac App Store. And even when they are available, installing applications with VPP is still unreliable and hard to debug, or retry when it fails.

If you are managing with the “just install the latest version” philosophy, then you probably have one or more scripts that will download and install the latest version of some software from the vendor’s website. This avoids the overhead work of having to download, repackage and manage every new update in the management system. (This can be automated with AutoPkg, but if you can avoid it entirely…)

When I started thinking about this, we had at least four different scripts. Most of them were internal, but William Smith’s installer script for Microsoft applications was a huge inspiration. it made me thing that you could generalize much of this.

Security Considerations

The main danger when downloading application archives and installers directly from the vendor is that a malicious actor might intercept the traffic or even hijack the servers and replace the download with a manipulated software that contains and or installs malware. Since management processes run with root privileges, we have to extra careful which files and processes are installed.

For user driven installation, Apple introduced GateKeeper, signed applications and Notarization as a way to verify downloaded software before execution. When you download software with a script, then you are bypassing GateKeeper. This is usually considered a benefit, because in a managed deployment we don’t want to scare and annoy a user with the warning dialogs.

But we can use the GateKeeper verification process in our script to verify that the archive, application, or installer is signed and notarized. With the spctl command, we can run the verification from the script without the user interaction.

We can even go one step further than GateKeeper. GateKeeper is happy when a software is signed and notarized with any Apple Developer ID. Since this script is working with a curated list of software, we can verify that the application is actually signed with the expected vendor’s Developer ID.

This will catch situations where someone creates or steals a Developer ID to sign and notarize a manipulated application. Apple can and will eventually block that Developer ID, but there will be a window where the manipulated application may be downloaded and installed. This is not theoretical, but has happened already. (more than once)

Installomator

With these ideas in mind, I started working on a script to unify all these installer scripts. (‘The one to rule them all.’) I may have gone a little overboard, but it turned into Installomator.

You can run Installomator from the command line or from your management system.

> ./Installomator.sh desktoppr

The script requires a single argument. The argument is a label that chooses which application to download and install. (As of now, Installomator can handle 56 applications, you can see a list of applications in the repository.

Please read the readme in the GitHub repository for more details.

Jamf or not

I have tried to keep Installomator generic enough that it can be used with platforms other than Jamf Pro.

However, we will use it with Jamf Pro, and thus I took the opportunity to add some workflows that Jamf is missing.

Drag’n Drop installations

“Drag this app to the Applications folder” is a common instruction found on downloaded dmg or zip archives for the Mac. The fact that Jamf Pro has always required repackaging and cannot directly handle application dmgs or zips is mystifying. Also, highly ironic, since Jamf delivers their own management applications in a disk image.

Nevertheless, Installomator can deal with apps that are downloaded in zip, tbz, and dmg archives.

Blocking Processes

Jamf will also happily attempt to install over a running application. So, Installomator will check for blocking processes and either stop the installation at that time or prompt the user and give them a chance to quit the application. (Yes, this is inspired by the behavior of Munki.)

Vendor update processes

Since Installomator will download and install the latest version of the application from the vendor website, it can be used for updates as well as first installations.

If an application has a built-in update process that can be triggered by the script, This can be used instead for updates. So, for Microsoft applications, when the script detects that the app is already installed, it will run msupdate instead of downloading a full installer. This way the update process will use Microsoft’s optimized thin updates. (Credit to Isaac Ordonez, Mann consulting for the idea and first implementation.)

So far, this is only implemented for Microsoft applications and Google Chrome. (and quite experimental)

Extensible

So far, the script can install 56 different applications or application suites. More application descriptions can be added fairly easily, by adding the proper variables. You can find more detailed explanations in the ReadMe, and of course, the existing applications serve as examples.

Not all applications are suitable to be installed with Installomator. To be able to install an application, the download URL must be accessible without requiring a login, and there must be some, fairly simple process to determine the URL for the latest version.

Installomator will only install the application itself, it will not configure any settings. You will have to use profiles, or additional scripts and installers for that.

When you add an application for your own workflow, please contribute as an issue or pull request! Thank you!

Installomator and AutoPkg

Obviously, much of Installomator’s workflow has been heavily inspired by AutoPkg. I have been using AutoPkg for a long time and provide a repository of recipes. And I plan to continue to use AutoPkg.

As mentioned before, Installomator is not suitable for every type of deployment. If you require control over the versions of the software deployed, then you need to download, re-package and manage the packages in your management system. This is obviously what AutoPkg was designed for.

Also, not every software can be installed with Installomator, mostly because the installer is not available as a direct download. In these cases, AutoPkg will be useful to automate the management and deployment, even when you management style is less controlling.

Going Forward

We have been using Installomator for the past few weeks in our own deployment and with one customer. We are now at a point, where we believe it is stable enough to share it and get feedback from other MacAdmins. (I have already shared it with a few, and many thanks to those that have given valuable feedback.)

We have been using this script with two smaller deployments and want to roll it out to more of our customers. But we probably haven’t hit all the weird edge cases yet. So, proceed with caution.

Consider this a beta release.

(Sidenote: I have tested the script with 10.14.6 and 10.15.x. Because it uses the notarization verification which is available in 10.14.4 and higher it will probably not run well on older macOS versions. Might be possible to adapt it though.)

If you are as excited about the script as we are, please start testing in your environment and provide feedback. But please, as with anything MacAdmin, don’t just go and push the script to hundreds or thousands of devices, but test, test, test first.

Then please provide any enhancements back on the GitHub repository. I have also created an #installomator channel on the MacAdmin Slack for discussion and questions.

Weekly News Summary for Admins — 2020-05-08

This week we learned that JNUC is also going virtual (20 Sep–1 Oct), as well as the dates for the virtual WWDC (starts 22 June). The good thing about having virtual conferences is that we all can go!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

Headlines

On Scripting OS X

My five-minute presentation from the Texas Apple Admin Virtual Meeting this week. Thanks again for having me!

News and Opinion

macOS Catalina 10.15 and iOS 13 Updates

Coronavirus and Remote Work

MacAdmins on Twitter

Bugs and Security

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Listen

Support

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!

Weekly News Summary for Admins — 2020-05-01

In this time where days and dates seem to lose all meaning and context: we made it to May…

New beta releases for macOS 10.15.5 and iOS 13.5 (changed from the initial and weird 13.4.5). Oh, and Microsoft is re-branding Office 365 as Microsoft 365.

The Houston Apple Admins group are hosting a virtual meetup next week, 5 May 2020 from 12–1p.m Central time (19:00–20:00 Central European time). I’ve been told everyone is welcome. I have the honor of being among their list of speakers for short 5–10 minute ‘lightning presentations.’ (It’s like speed dating, but with MacAdmin topics.) See you virtually there!

Stay Safe, everyone!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

News and Opinion

macOS Catalina 10.15 and iOS 13 Updates

  • Mr. Macintosh:Article Update! Apple has removed the “Restore from Snapshot” Feature from the macOS Catalina New Features Page. Having the ability to restore from a snapshot taken just before a macOS update was very useful. I hope this feature returns soon.”

Coronavirus and Remote Work

MacAdmins on Twitter

Bugs and Security

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Listen

Support

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!

Weekly News Summary for Admins — 2020-04-24

One of those “in between” weeks, where nothing particular happens, but enough to fill a newsletter. As usual, many thanks to everyone who shares their knowledge in a post.

Stay safe!

If you would rather get the weekly newsletter by email, you can subscribe to the Scripting OS X Weekly Newsletter here!! (Same content, delivered to your Inbox once a week.)

News and Opinion

macOS Catalina 10.15 and iOS 13 Updates

Coronavirus and Remote Work

MacAdmins on Twitter

  • Adam Codega: “You can place custom Teams video call backgrounds in ~/Library/Application \Support/Microsoft/Teams/Backgrounds/Uploads I imagine an upload GUI button will be coming soon. If you place it manually, Teams displays a broken thumbnail icon because of .DS_Store in the folder.”
  • Erik Gomez: “How I explained my job today: Imagine managing 80,000 servers, each one a unique node with a very opinionated System Administrator who indirectly and directly tries to break everything you do.”
  • Tim Perfitt: “The new T2 Macs had a bit of twist for Winclone. If you are migrating a Boot Camp partition from a non-T2 mac to a T2 Mac, the restored Boot Camp partition doesn’t have the Apple SSD driver need to boot and it blue screens.”
  • Carl Ashley: “Python versions 2.7.18, 3.7.7, and 3.8.2 from python.org are now codesigned bugs.python.org/msg366846

Bugs and Security

Support and HowTos

Scripting and Automation

Apple Support

Updates and Releases

To Listen

Support this News Summary

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!