Advanced Homebrew Options to Level Up Your Infrastructure as Code on macOS
Learn how to leverage Brewfiles to install a large number of Hombrew packages at once.
Homebrew is the default choice for managing software installations on macOS, because of its ease of use and the enormous number of well-maintained formulas that are ready to be installed with a few keystrokes. That said, there are some lesser-known super powers that Homebrew exposes to users. Today, we’ll look at two of these advanced options – the `Brewfile` and the `services` sub-command.
First, the `Brewfile` -- it can be cumbersome to have to install a large number of packages on a fresh server. Thankfully, in the case of macOS, we can employ Brewfiles to conveniently install large numbers of packages via Homebrew, as you likely will when using macOS compute resources with MacStadium.
What is a Brewfile?
Brewfiles are text files that allow Homebrew users to manage their infrastructure as code. They can grow to be quite significant, but they are fundamentally a list of list of various Homebrew resources to be installed in a given environment that have been written to a simple text file, like so:
In order to install the example packages listed – Jenkins and Java 8 – you can simply run the following:
brew bundle --file /path/to/Brewfile
How to Create a Brewfile
Brewfiles can either be created manually, or you can use `brew` to create a Brewfile that represents the current state of your system by running various `brew bundle` commands.
brew bundle dump
Write all installed brew packages to a local Brewfile.
brew bundle dump --force
Overwrite a local Brewfile with currently installed packages.
Advanced Options with Brewfiles
brew bundle cleanup
Remove all packages not listed in the local Brewfile.
brew bundle exec [command]
Execute a command in an isolated environment that contains the Brewfile’s listed packages. To see this in action easily, try running `brew bundle exec printenv` and you will see that the listed Homebrew resources remain in line with the resources defined in your Brewfile.
Manage `launchctl` services with `brew services`
Aside from installing large numbers of packages easily, Homebrew can also make easy work of managing macOS services controlled by `launchctl`. There are two common approaches to automating events in macOS -- either at machine startup or at user login. Both make use of the macOS tool `launchctl` in order to manage the service proper, which is defined with an XML file with the suffix `.plist` that lives in either the `/Library/LaunchAgents` (if it requires a logged in user) or `/Library/LaunchDaemons` directory (if it is to be run as `root`).
Whether a given process needs a logged in user or not will determine which of the above options will work best. Either way, there will likely be times when you want to call the service manually – either for development or maintenance. Homebrew makes this simple too!
brew services list
List all `LaunchAgents` associated with the currently logged in user.
sudo brew services list
List all `LaunchDaemons` currently in the system.
brew services run <service>
Run the named service without registering it as a `LaunchAgent` or a `LaunchDaemon`.
brew services start <service>
Start the service immediately and also register it to run at either startup or login.
Homebrew is ubiquitous in the macOS world, but there are lots of hidden super powers wrapped up in this package manager that you may not be familiar with. Above, we’ve looked at two of these – version-control friendly Brewfiles for defining all casks, taps and packages that you wish to install on a given Mac, and the `services` sub-command that allows Homebrew users to manage `launchctl` services on Mac easily.