How to install your personal font library with Homebrew
Tags: homebrew, macos, fonts
Published: 2022-03-19 20:58:04

## TL;DR

This tutorial shows you how to create your own private Homebrew Cask for your paid/closed-license fonts.

1. Create a ZIP (or TAR) file of all fonts
1. [Generate the Cask for your font library ZIP](https://github.com/Homebrew/homebrew-cask-fonts/blob/master/CONTRIBUTING.md#automatic-generation) 
1. Host the ZIP in a semi-secret location like Dropbox or Google Drive
1. Optionally, host the Cask file in a semi-secret location like Dropbox/Google Drive or as a GitHub gist.
1. Now you can install your font library on a new computer with a single `brew install --cask ...` command!

## Some caveats

If you don't like the idea of having your fonts out in the open, there _is_ a potential workaround—but that will be for a later post.

Also, I'm also aware that there are simpler, but slightly less convenient and portable ways to do this, like `cp`ing your fonts to `~/Library/Fonts`, but what fun is that?

Finally, if you have a font in mind that _is_ openly licensed but not yet on Homebrew, you can use what you learned in this tutorial and actually contribute a Pull Request to `homebrew-cask-fonts`!

## Intro

For macOS users, [Homebrew](brew.sh) is a convenient way to install open-license fonts, like [Fira Code](https://github.com/tonsky/FiraCode) or [JetBrains Mono](https://www.jetbrains.com/lp/mono/) via a command like this:

```shell
brew install --cask font-fira-code
```

However, if you have accumulated your own collection of paid fonts for coding or design, they will _not_ be available via Homebrew and you will need to individually download them to your computer and install them.

> For example, when I am provisioning a new Mac, I need to login to Dropbox, find my folder of files, download them, then install them through the Font Book application.

In this tutorial, I will describe how you can replace this manual workflow with the same `brew install --cask font-xyz` workflow available for free fonts. 

> By using Homebrew, you also get the ability to:
> - specify the installation directory with `brew install --cask --fontDir ...`
> - uninstall fonts with `brew uninstall font-xyz`
> - get modular and create casks for individual fonts, collections of fonts, specific versions or stylistic sets, and so on

## Prerequisites

1. [Install Homebrew](https://brew.sh/)
1. [Tap the fonts Cask] (https://github.com/Homebrew/homebrew-cask-fonts#homebrew-cask-fonts)
1. `brew install lcdf-typetools`, which you'll need later to create the custom Cask

## Step 1: Collect your private fonts into an archive

> For this tutorial, I will use [Roboto Mono](https://fonts.google.com/specimen/Roboto+Mono) from Google Fonts and pretend that is one of my private fonts (even though you could download it via Homebrew).

Collect your fonts in one place and create a ZIP archive of them.

You can also structure the archive however you want, with different font families in their own directory, for example.

```
$ unzip -l Roboto_Mono.zip 
Archive:  Roboto_Mono.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
    11560  05-13-2015 00:00   LICENSE.txt
    87872  05-13-2015 00:00   static/RobotoMono-Thin.ttf
    87788  05-13-2015 00:00   static/RobotoMono-ExtraLight.ttf
    87592  05-13-2015 00:00   static/RobotoMono-Light.ttf
    86908  05-13-2015 00:00   static/RobotoMono-Regular.ttf
    86820  05-13-2015 00:00   static/RobotoMono-Medium.ttf
    87076  05-13-2015 00:00   static/RobotoMono-SemiBold.ttf
    87008  05-13-2015 00:00   static/RobotoMono-Bold.ttf
    93056  05-13-2015 00:00   static/RobotoMono-ThinItalic.ttf
    93408  05-13-2015 00:00   static/RobotoMono-ExtraLightItalic.ttf
    93760  05-13-2015 00:00   static/RobotoMono-LightItalic.ttf
    93904  05-13-2015 00:00   static/RobotoMono-Italic.ttf
    93948  05-13-2015 00:00   static/RobotoMono-MediumItalic.ttf
    93940  05-13-2015 00:00   static/RobotoMono-SemiBoldItalic.ttf
    94148  05-13-2015 00:00   static/RobotoMono-BoldItalic.ttf
   182172  05-13-2015 00:00   RobotoMono-VariableFont_wght.ttf
   195012  05-13-2015 00:00   RobotoMono-Italic-VariableFont_wght.ttf
     2559  03-19-2022 12:44   README.txt
---------                     -------
  1658531                     18 files

```

> The ZIP from Google Fonts contains other files, but they will be ignored by the Cask generator.

## Step 2: Generate the Cask file for your private font archive

Follow [these instructions](https://github.com/Homebrew/homebrew-cask-fonts/blob/master/CONTRIBUTING.md#automatic-generation) to generate the Cask file, which automates some steps, like computing the SHA256 hash and creating a list of font files to install.

Run this command on its own to preview the file:

```shell
"$(brew --repository)/Library/Taps/homebrew/homebrew-cask-fonts/developer/bin/font_casker" Roboto_Mono.zip
```

Example:

```
$ "$(brew --repository)/Library/Taps/homebrew/homebrew-cask-fonts/developer/bin/font_casker" Roboto_Mono.zip
FAMILY: Roboto Mono
cask 'FIXME' do
  version "3.000"
  sha256 "d5c35dbe54b9fb53898f05f318492fb39b78c6c3d3aa919eaf0f01f4fe61387d"

  url ""
  name ""
  homepage ""

  font "RobotoMono-Italic-VariableFont_wght.ttf"
  font "RobotoMono-VariableFont_wght.ttf"
  font "static/RobotoMono-Bold.ttf"
  font "static/RobotoMono-BoldItalic.ttf"
  font "static/RobotoMono-ExtraLight.ttf"
  font "static/RobotoMono-ExtraLightItalic.ttf"
  font "static/RobotoMono-Italic.ttf"
  font "static/RobotoMono-Light.ttf"
  font "static/RobotoMono-LightItalic.ttf"
  font "static/RobotoMono-Medium.ttf"
  font "static/RobotoMono-MediumItalic.ttf"
  font "static/RobotoMono-Regular.ttf"
  font "static/RobotoMono-SemiBold.ttf"
  font "static/RobotoMono-SemiBoldItalic.ttf"
  font "static/RobotoMono-Thin.ttf"
  font "static/RobotoMono-ThinItalic.ttf"
end
```

> You will get an error if you did not install `lcdf-typetools`, as described in the prerequisites.

You can copy-paste this output to a text editor and save it as a Ruby file (e.g. `font-roboto-mono-private.rb`), or run the command again and pipe it to a text file.

```shell
"$(brew --repository)/Library/Taps/homebrew/homebrew-cask-fonts/developer/bin/font_casker" Roboto_Mono.zip > font-roboto-mono-private.rb
```

We will return to edit this file later on.

## Step 3: Host your font archive in a "secret" URL

Casks need to access their installation artifacts (e.g. font ZIPs) from a public URL.

> WARNING: if you publicize or share this URL in any way, you will most likely be in violation of your end-user license agreement. So don't do that!

The simplest way to do this is to upload it to a service like  Dropbox or Google Drive. In this tutorial, I will use Google Drive.

I uploaded `Roboto_Mono.zip` to my Google Drive and generated a public link. These links are formatted like this:

```
https://drive.google.com/file/d/{{FILE_ID}}/view?usp=sharing
```

Where `{{FILE_ID}}` is a long string like `1wWK75gYcMBxugCjAuyInW8tSGZJivjla`.

However, these links aren't directly usable by Homebrew, since they point to a preview page, and not the actual file.

To fix this, take the `FILE_ID` and create this URL (Source: [How To Geek](https://www.howtogeek.com/747810/how-to-make-a-direct-download-link-for-google-drive-files/)):

```
https://drive.google.com/uc?export=download&id={{FILE_ID}}
```

Test the link in your browser. Instead of being taken to a Google Drive preview page, your browser should download it directly to your computer, which is what we want.

## Step 4: Add the URL to the Cask

Going back to the Cask (`font-robot-mono-private.rb`), make these edits:

```ruby
# Make sure to delete the first line "FAMILY: Roboto Mono"

# The Cask name must match the file name
cask 'font-roboto-mono-private' do
  version "1.000"
  sha256 "d5c35dbe54b9fb53898f05f318492fb39b78c6c3d3aa919eaf0f01f4fe61387d"

  url "https://drive.google.com/uc?export=download&id={{FILE_ID}}"
  name "Robot Mono Private"
  homepage ""

  font "RobotoMono-Italic-VariableFont_wght.ttf"
  font "RobotoMono-VariableFont_wght.ttf"
  font "static/RobotoMono-Bold.ttf"
  font "static/RobotoMono-BoldItalic.ttf"
  font "static/RobotoMono-ExtraLight.ttf"
  font "static/RobotoMono-ExtraLightItalic.ttf"
  font "static/RobotoMono-Italic.ttf"
  font "static/RobotoMono-Light.ttf"
  font "static/RobotoMono-LightItalic.ttf"
  font "static/RobotoMono-Medium.ttf"
  font "static/RobotoMono-MediumItalic.ttf"
  font "static/RobotoMono-Regular.ttf"
  font "static/RobotoMono-SemiBold.ttf"
  font "static/RobotoMono-SemiBoldItalic.ttf"
  font "static/RobotoMono-Thin.ttf"
  font "static/RobotoMono-ThinItalic.ttf"
end
```

After you make these changes, the Cask is ready to use:

```shell
brew install --cask ./font-robot-mono-private.rb
```

## Optional: Host the Cask in a "secret" location

If you want to install these fonts on any other computer with Homebrew, you can host the Cask file in an obscure location, like a secret GitHub gist.

> WARNING: Again, because this Cask file contains a link to the ZIP file, don't publicize the Cask, or else be in risk of violating your fonts' EULAs!

Unfortunately, you can't directly use the URL in `brew install --cask`—you will have to download the file first and then reference the local copy.

Example using my ["secret" gist with Roboto Mono](https://gist.githubusercontent.com/jonboiser/655275dcf814b3f258846e4b86ebda5e/raw/db219fcad63368847bfe04aa6546aab37363608e/font-robot-mono-private.rb)

```shell
wget https://gist.githubusercontent.com/jonboiser/655275dcf814b3f258846e4b86ebda5e/raw/db219fcad63368847bfe04aa6546aab37363608e/font-roboto-mono-private.rb
brew install --cask ./font-roboto-mono-private.rb
```

Now you can save that snippet in a script or in your notes for the next time you want to download your personal fonts with one line!

## Conclusion

And that's it!

Let me know in the comments how you used this technique, how you plan to use it, or if you have any additional suggestions to improve it.

In an upcoming post, I will describe how to accomplish this process without publishing your fonts in secret-but-public URLs by preloading the Homebrew cache. 

This approach is not as portable, but still gives you the benefits of using the Homebrew CLI for managing your fonts.

I'd be curious if any of you might have some insights into this. Please share in the comments!