ZNHOO Whatever you are, be a good one!

macOS

  1. Introductory
  2. Shortcuts
  3. Package Installation
  4. General Setup
  5. Shell Setup
  6. gh
  7. Docker Desktop
  8. Homebrew
    1. Homebrew Tap
      1. Personal Tap
    2. brew edit
  9. UTM

Introductory

macOS (Mac OS X or OS X) is a proprietary OS derived from Berkeley Software Distribution (BSD), and therefore is a Unix-like system. The main difference between macOS and other Unix-like distributions is that macOS is designed with desktop for personal PC.

Shortcuts

# Screenshot
shift + command + 3/4/5

# Lock Screen
ctrl + command + q

Package Installation

  1. Homebrew.
  2. App Store.
  3. Jamf Self Service.

General Setup

  1. touchpad tap with 1 click
  2. Rime
  3. Firefox
  4. iTerm2
  5. ssh; load-ssh-agent

Shell Setup

Set "bashrc" and "bash_profile" only after the following:

brew install coreutils
type gdate ; type date

brew install xz

brew install bash
type -a bash

cat >>/etc/shells <<EOL
> /opt/homebrew/bin/bash
> EOL

chsh -s /opt/homebrew/bin/bash

openssl version -a
brew install openssl@1.1
/opt/homebrew/Cellar/openssl\@1.1/1.1.1o/bin/openssl version -a
PATH="/opt/homebrew/opt/openssl@1.1/bin:$PATH"

brew install emacs weechat tmux nmap utm gnupg

brew install libpq
PATH="/opt/homebrew/opt/libpq/bin:$PATH"

brew install btop
mkdir -p ~/.config/btop

PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"

gh

brew install gh

Create a GITHUB_TOKEN and then run gh auth login with the token.

Docker Desktop

  1. Mac with Apple silicon
  2. For compatibility, run softwareupdate –install-rosetta.

Homebrew

After installing Homebrew, we can optionally update mirror to speed up package fetching.

Everything of Homebrew is located under $(brew --prefix) (e.g., /opt/homebrew). Especially, the prefix of a formulae is brew --prefix <formulae>.

Get help info.

~ $ brew commands

~ $ brew help install

~ $ brew config

~ $ brew doctor

brew supports installing both CLI and GUI formulae.

  1. CLI

    ~ $ brew install <formulae>
    
  2. GUI

    ~ $ brew install [--cask] <formulae>
    

    Option --cask is optinal and brew cask is no longer a supported command.

Sometimes, a formulate offers extra installation options (e.g. modules). For example, we can install OpenResty with --with-slice to include the corresponding modules.

~ $ brew options openresty
--with-iconv
        Compile with ngx_http_iconv_module
--with-postgresql
        Compile with ngx_http_postgres_module
--with-slice
        Compile with ngx_http_slice_module

Update formulae.

~ $ brew update

~ $ brew outdated

~ $ brew upgrade

Latest Homebrew uses API to install formulae, so it must fetch a file from https://formulae.brew.sh/api/formula.json. The file size is over 18M and so may report timeout issue as below.

11:46:09 zachary@Zacharys-MacBook-Pro ~/workspace/resty-redis-cluster$ brew search openresty
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5003 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received
Error: Failure while executing; `/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.20-137-g12f3fb8\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 13.2\)\ curl/7.86.0 --header Accept-Language:\ en --fail --pr
ogress-bar --max-time 5 --retry 3 --location --remote-time --output /Users/zachary/Library/Caches/Homebrew/api/formula.json --time-cond /Users/zachary/Library/Caches/Homebrew/api/formula.json --compressed --silent https://formulae.brew.sh/api/formula.json` exited with 28.
 Here's the output:
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5003 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received

Either set a proxy or disable API by HOMEBREW_NO_INSTALL_FROM_API=1.

Homebrew Tap

A tap is a repository from where brew retrieves packages. By default, brew assumes a Github repository.

Official tap list.

~ $ brew tap
homebrew/cask
homebrew/core

Say we have a tap named as user/repo, the repository is https://github.com/<user>/homebrew-<repo> (homebrew prefix). Take homebrew/core for example, the Github URL is https://github.com/homebrew/homebrew-core. The tap is cloned to local disk under directory $(brew –repository)/Library/Taps.

We can add/remove 3rd-party taps on demand.

# assume Github repo
~ $ brew tap <user/repo>
# -or-
~ $ brew tap <user/homebrew-repo>

# Other repo with specific URL
~ $ brew tap <user/repo> <URL>

# remove
~ $ brew untap user/repo

Once added, we can install formulae as in Homebrew.

However, brew tries to install a formulae from official taps first. In case of duplicate formulae names among taps, We can install a formulae from a specific 3rd-party tap.

~ $ brew install user/repo/formulae

Personal Tap

This section shows how to create a 3rd-party tap.

Step 1. Create an empty Github repo as the personal tap, namely homebrew-wrk2. The repo name must follow pattern homebrew-<foo> (homebrew prefix). We will put our formulaes into directory "Formula".

Now, let's add the personal tap to Homebrew.

~ $ brew tap outsinre/wrk2

~ $ brew tap
homebrew/cask
homebrew/core
outsinre/wrk2

~ $ cd $(brew --repository outsinre/wrk2)
~ $ git status

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ tree
.
├── Formula
└── README.md

1 directory, 1 files

~ $ brew tap --eval-all outsinre/wrk2

Step 2. Prepare code release.

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git branch -a
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git checkout wrk2-a64-support
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git diff head~1

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git checkout master
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git merge wrk2-a64-support

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git tag -l
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git tag -a 1.0.0 -m "release 1.0.0" HEAD
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git tag -l
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git show -s 1.0.0

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git push origin head
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git push origin 1.0.0

Go to Github and create release 1.0.0.

Step 3. Create formulae.

~ $ brew create --tap outsinre/wrk2 https://github.com/outsinre/wrk2/archive/refs/tags/1.0.0.tar.gz

Command above puts the newly formulae into our local personal tap outsinre/wrk2. If we don't offer the --tap option, the formulae would, by default, be placed into the official tap (i.e. homebrew/core).

An editor is popped up to edit the new formulae. Please follow wrk.rb and wrk2.rb.

Step 4. Audit the new formulae's adherence to Homebrew house style.

# validate tap
~ $ brew tap --eval-all outsinre/wrk2

# validate formula
~ $ brew audit --strict --online outsinre/wrk2/wrk2

# validate formula more strictly
~ $ brew audit --new outsinre/wrk2/wrk2

outsinre/wrk2/wrk2:
  * 2: col 9: Description shouldn't start with an article.
  * 7: col 3: `license` (line 7) should be put before `head` (line 6)
  * 24: col 12: Ambiguous splat operator. Parenthesize the method arguments if it's surely a splat operator, or add a whitespace to the right of the `*` if it should be a multiplication.
Error: 3 problems in 1 formula detected

Update formulae according to audit results.

~ $ cd $(brew --repository outsinre/wrk2)
~ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ nano -w wrk2.rb

Step 5. Sync local tap with Github.

~ $ cd $(brew --repository outsinre/wrk2)

~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git status
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git add .
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git commit -m "add formulae wrk2"
~ $ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2$ git push origin head

Step 6. Install the new formulae.

~ $ brew install outsinre/wrk2/wrk2

If a new release is out. We should firstly backup and remove $(brew --repository outsinre/wrk2)/Formula/wrk2.rb and then repeat steps 2 ~ 6 above. Mostly, we only need to update the sha256 and url part.

However, we can also install the from the latest source code if head is defined the formulae.

~ $ brew install --HEAD outsinre/wrk2/wrk2

References:

  1. Formula-Cookbook
  2. Creating and running your own Homebrew tap
  3. Step by step guide to create Homebrew tap

brew edit

Sometimes, we want to change (version, url, etc.) formulas locally in place. For example, we do not want to wait for upstream update.

The following steps demostrate how to upgrade OpenResty version locally.

Remove the formulae in advance.

~ $ brew uninstall openresty

Edit formula "openresty" in tap "openresty/brew". We change "VERSION" from "1.21.4.1" ro "1.21.4.2rc1".

~ $ brew tap
openresty/brew

~ $ brew edit openresty/brew/openresty
> VERSION = "1.21.4.2rc1"

~ $ brew --repository openresty/brew
/opt/homebrew/Library/Taps/openresty/homebrew-brew

~ $ cd $(brew --repository openresty/brew)

15:12:31 zachary@Zacharys-MacBook-Pro /opt/homebrew/Library/Taps/openresty/homebrew-brew$ git diff
diff --git a/Formula/openresty.rb b/Formula/openresty.rb
index f25142d..46262e2 100644
--- a/Formula/openresty.rb
+++ b/Formula/openresty.rb
@@ -3,7 +3,7 @@ require 'etc'
 class Openresty < Formula
   desc "Scalable Web Platform by Extending NGINX with Lua"
   homepage "https://openresty.org"
-  VERSION = "1.21.4.1".freeze
+  VERSION = "1.21.4.2rc1".freeze
   revision 2
   url "https://openresty.org/download/openresty-#{VERSION}.tar.gz"
   sha256 "0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99"

However, we should also update "sha256" of the new version. We can manually download the tarball and calculate "sha256" locally. Alternatively, we let brew calculate it as follows.

~ $ brew fetch --build-from-source openresty/brew/openresty

==> Fetching openresty from openresty/brew
==> Downloading https://openresty.org/download/openresty-1.21.4.2rc1.tar.gz

Downloaded to: /Users/zachary/Library/Caches/Homebrew/downloads/ad1460c199727f56f390f2dfd99817dc8d6bdedd539e3b8fac4efa6eb0519a27--openresty-1.21.4.2rc1.tar.gz
SHA256: ee96bbcf119abe5f1fc90461dd4674bd9397aa3db5544139578d9ace81983fdb
Warning: Formula reports different sha256: 0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99

The new "sha256" is printed to stdout. Let's update accordingly.

~ $ brew edit openresty/brew/openresty

15:16:25 zachary@Zacharys-MacBook-Pro /opt/homebrew/Library/Taps/openresty/homebrew-brew$ git diff
diff --git a/Formula/openresty.rb b/Formula/openresty.rb
index f25142d..afdf97c 100644
--- a/Formula/openresty.rb
+++ b/Formula/openresty.rb
@@ -3,10 +3,10 @@ require 'etc'
 class Openresty < Formula
   desc "Scalable Web Platform by Extending NGINX with Lua"
   homepage "https://openresty.org"
-  VERSION = "1.21.4.1".freeze
+  VERSION = "1.21.4.2rc1".freeze
   revision 2
   url "https://openresty.org/download/openresty-#{VERSION}.tar.gz"
-  sha256 "0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99"
+  sha256 "ee96bbcf119abe5f1fc90461dd4674bd9397aa3db5544139578d9ace81983fdb"

   option "with-postgresql", "Compile with ngx_http_postgres_module"
   option "with-iconv", "Compile with ngx_http_iconv_module"

We can validate the update according to instructions in section Personal Tap.

If everything is ok, we install the new version.

~ $ brew install openresty/brew/openresty

One side effect is that, local edits may conflicts with future upstream updates!

UTM

UTM is an open source VMM supporting iOS and OSX. What is more, it supports Apple ARM64!

  1. Installation.
  2. Gallery.
  3. After installation, remove and re-add the USB (DVD) drive, otherwise the boot menu break from time to time.
  4. Follow tutorial UTM Ubuntu 20.04.

UTM uses davfs2 to share files with host OS. Here is setup on guest OS:

# clipboard sharing, mouse integration
~ $ apt install spice-vdagent

# file shareing
~ $ apt install spice-webdavd davfs2

# group
~ $ sudo usermod -a -G davfs2 kong
~ $ sudo reboot

# /etc/fstab
http://127.0.0.1:9843   /media/webdav   davfs   _netdev,noauto,noexec,user,uid=kong,gid=kong    0       0

~ $ mkdir -p /media/webdav
~ $ mount /media/webdav
~ $ ls -al ~/.davfs2/

# auto password
# ~/.davfs2/secrets
/media/webdav   kong    kong

~ $ umount /media/wevdav
~ $ mount /media/wevdav

If just use Web browser (e.g. VM has X), then no need to install davfs2.