LoginSignup
0
1

More than 1 year has passed since last update.

Macの環境を自動構築してみる

Posted at

背景

数年前からずっとMac Bookが欲しいと考えていました。
Apple Storeを覗いてスペックを見たりしながら夢を膨らませていました。
つい先日、満を持して、Mac Book Air M1を購入しました。
新しいPCを購入したあとにやることといえば...
そう、環境構築です。
自分専用の使いやすい環境を構築する。
とても楽しいワクワクする作業です。

手作業でポチポチインストールするのも楽しいので環境構築は苦ではなく、むしろ大好きです。
でもそれではこれまでと何も変わりません。
せっかくなので、これまでの仕事で経験してきたIaCの技術を使ってアプリケーションの自動インストールを行ってみようと考えました。

幸い、まだMac Book Air M1が届くまで時間があるようです。
ならばこの到着までの時間を使って、調査やAnsibleの準備を進めてみようと思います。
image.png

参考

AnsibleでMacの環境構築をしてみた
community.general.mas – Manage Mac App Store applications with mas-cli
チェックモード (「ドライラン」)
いつの間にかbrew caskが使用できなくなっていた話

(番外編)Macとの出会い

就職してからほとんどWindowsに触れていました。
クライアントもサーバも。
職場のPCはともかく、自宅のPCもメーカーPC、自作PC、ショップPCと渡り歩いてきました。
次第にスペック不足に陥ったり、PCが不調になったりと、パーツ交換を繰り返しながら使っていましたが、どうにも手間がかかるなという思いから、買い替えを決意。
どうせプライベートだし、Windowsに固執する必要はない、40歳のときに思い切ってMac(Mac mini Late 2012)に切り替えました。
購入直後からいきなり分解しHDDをSSDに換装、メモリも8GBから16GBに増設したりと、これまでの自作PCの経験を活かしカスタマイズ。
そこからはMacに慣れることや、MacでWindowsを動かす方法を調べたりと、楽しいPCライフが始まり、今に至ります。

調査してわかったこと

自動構築はAnsibleを使うようです。
Ansibleでアプリケーションをインストールするのは数多くの先人たちが情報を蓄積してくださっています。
調べたところ、Macはbrewコマンド、brew-caskコマンド、そして、masコマンドを使うことでCLIでアプリケーションをインストールすることができるようです。

Ansibleからはこれらコマンドに対して、インストールしたいアプリケーション情報を引数で渡してあげると良いみたいです。

masコマンドでインストーするアプリケーションのIDとは?

例えばLINEですが、調べてみると、brewでもbrew-caskでもインストール出来ないようでmasコマンドでインストールするようです。
masコマンドにはアプリケーションのIDが必要です。
では、LINEのIDはどうやったらわかるのでしょうか?

答えは簡単でした。

MacのApp Storeで「LINE」を検索してもわからなかったのですが、
image.png

ブラウザで検索すれば、URLにIDが表示されていました。
どうやら「LINE」は「539883307」のようです。
image.png

なので、インストールするコマンドはこの様になるようです。

mas install 539883307

Ansibleを実行する前にやっておくこと

アプリケーションの自動インストールはAnsibleでできそうだということがわかりました。
でもその前に、準備することがあります。
アカウントの設定とかもですが、Ansibleを実行する環境は事前に構築しておく必要があります。

ターミナルを起動し、以下のコマンドを実行して環境を整えておきます。
(これも自動化できればよいのですが...)

  • Command line tools for Xcode
$ xcode-select --install
  • Homebrew
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • Homebrew-Cask
$ brew install cask
  • mas-cli
$ brew install mas
  • Ansible
$ brew install ansible
  • Ansible Community(Ansibleでmas-cliを使用するために必要な追加モジュールのインストール)
$ ansible-galaxy collection install community.general
- downloading role 'collection', owned by
 [WARNING]: - collection was NOT installed successfully: Content has no field named 'owner'

ERROR! - you can use --ignore-errors to skip failed roles and finish processing the list.

このエラーがどうやっても解消できませんでした...
Ansibleで「community.general.mas」を使用していたので必要だと思うのですが、どうやってもインストールできませんでした。
仕方がありませんので、こちらのモジュールは使用せず、Ansibleでは純粋に「mas-cli」を使用することにします。

インストールしたいアプリケーションとインストール方法の調査

今回はクライアント用途のMac Book Air M1へのインストールなのでアプリケーションもそんなにたくさんはありません。
とりあえずは以下のアプリケーションをインストールします。
それぞれのインストール方法も合わせてチェックしておきました。

アプリケーション インストール方法
Python brew install python
Docker brew install docker
brew cask install docker
iTerm2 brew cask install iterm2
Typora brew cask install typora
LINE mas install 539883307
CleanArchiver brew install cleanarchiver
VLC brew cask install vlc
Google Chrome brew cask install google-chrome
TweetDeck mas install 485812721
DUET brew cask install duet

Ansible Playbookの作成

どうやらベストプラクティスなのか、以下のような構成を多く見ました。
私もこちらの構成に習って構築してみることにします。

構成

repositorys
 └──/setup-mac
     ├── README.md
     ├── inventory
     ├── roles
     │   ├── homebrew
     │   │   ├── tasks
     │   │   │   └── main.yml
     │   │   └── vars
     │   │       └── main.yml
     │   ├── homebrew-cask
     │   │   ├── tasks
     │   │   │   └── main.yml
     │   │   └── vars
     │   │       └── main.yml
     │   └── mas
     │       ├── tasks
     │       │   └── main.yml
     │       └── vars
     │           └── main.yml
     └── site.yml

ドライラン

いきなりたくさんのアプリケーションをインストールするのもリスクなので、まずは各モードで一つづつ確認。
確認は母艦のMac miniで実行します。
こちらには既に色々なアプリケーションをインストール済みなので、再インストールになるのが嫌なので、Ansibleのチェックモードで確認します。

Ansible Playbookのチェック「ドライラン」

$ ansible playbook -i inventory site.yml --check

homebrewは問題なし。

TASK [homebrew : homebrew install] *********************************************
changed: [xxx.xxx.xxx.xxx] => (item={u'state': u'present', u'name': u'cleanarchiver'})

PLAY RECAP *********************************************************************
xxx.xxx.xxx.xxx                : ok=1    changed=1    unreachable=0    failed=0

homebrew-caskはエラー...

TASK [homebrew-cask : homebrew cask install] ***********************************
failed: [xxx.xxx.xxx.xxx] (item={u'state': u'present', u'name': u'typora'}) => {"failed": true, "item": {"name": "typora", "state": "present"}, "msg": "Error: Unknown command: cask"}

どうやらcaskの指定はオプション扱いになったようです。
なので、Ansibleのcommandで「brew install --cask」を実行する形に変更してエラーを回避しました。

$ ansible-playbook --check -i inventory site.yml

PLAY [mac setup] ***************************************************************

TASK [homebrew-cask : homebrew cask install] ***********************************
skipping: [xxx.xxx.xxx.xxx] => (item={u'state': u'present', u'name': u'typora'})

PLAY RECAP *********************************************************************
xxx.xxx.xxx.xxx                : ok=0    changed=0    unreachable=0    failed=0

masは「mas-cli」を使用することにしたのでエラーなく実行できたようです。
前述のように、本来は「community.general.mas」を使用したかったところですが...
残念ですが今回はこれで良しとします。

$ ansible-playbook --check -i inventory site.yml

PLAY [mac setup] ***************************************************************

TASK [mas : mas install] *******************************************************
skipping: [192.168.3.3] => (item={u'485812721 state': u'present', u'id': None})

PLAY RECAP *********************************************************************
192.168.3.3                : ok=0    changed=0    unreachable=0    failed=0

結果、各ファイルは以下のようになりました。

/homebrew/tasks/main.yml

---
# file: ~/setup-mac/roles/homebrew/tasks/main.yml

- block:
  - name: homebrew tap
    homebrew_tap:
      name: "{{ item }}"
      state: present
    with_items: "{{ taps }}"

  - name: homebrew install
    homebrew:
      name: "{{ item.name }}"
      state: "{{ item.state }}"
    with_items: "{{ packages }}"

  tags:
    - homebrew

/homebrew/vars/main.yml

---
# file: ~/setup-mac/roles/homebrew/vars/main.yml

taps:
  - homebrew/cask
  - homebrew/cask-versions
  - homebrew/cask-fonts
  - homebrew/core

packages:
  - { name: python, state: present }
#  - { name: cleanarchiver, state: present }
#  - { name: docker, state: present }

/homebrew-cask/tasks/main.yml

---
# file: ~/setup-mac/roles/homebrew_cask/tasks/main.yml

- block:

  - name: homebrew cask install
    command: brew install --cask "{{ item.name }}"
    with_items: "{{ packages }}"

  tags:
    - homebrew_cask

/homebrew-cask/vars/main.yml

---
# file: ~/setup-mac/roles/homebrew_cask/vars/main.yml

packages:
#  - { name: docker, state: present }
  - { name: iterm2, state: present }
  - { name: typora, state: present }
  - { name: vlc, state: present }
  - { name: google-chrome, state: present }
  - { name: duet, state: present }
  - { name: google-japanese-ime, state: present }
  - { name: cleanarchiver, state: present }

/mas/tasks/main.yml

---
# file: ~/setup-mac/roles/mas/tasks/main.yml

- block:

  - name: mas install
    command: mas install "{{ item.id }}"
    with_items: "{{ packages }}"

  tags:
    - mas

/mas/vars/main.yml

---
# file: ~/setup-mac/roles/homebrew/vars/main.yml

packages:
  - { id: ,539883307 state: present } # LINE
  - { id: ,485812721 state: present } # TweetDeck
  - { id: ,600925318 state: present } # Parallels Client

リモートリポジトリへ登録

今回はリポジトリは使用しませんが、資材の保管先として有志との活動で構築したgitlabを使用します。
予め、gitlab上にリポジトリを作成しておき、空のリポジトリをローカルにcloneし、資材をリモートリポジトリにpushしておきます。
実はこの活動を有志に相談したときに、次のテーマの構想が出てきたため、そのための事前準備として登録しておこうという魂胆です。

$ git clone http://xxx.xxx.xxx.xxx/example/setup-mac.git
$ cd setup-mac
$ git config --global user.name "example example"
$ git config --global user.email "example@example.com"
$ git add .
$ git commit -m "first commit"
$ git push
Username for 'http://xxx.xxx.xxx.xxx': example
Password for 'http://example@xxx.xxx.xxx.xxx':
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 469 bytes | 469.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To http://xxx.xxx.xxx.xxx/example/setup-mac.git
   359cfc6..ca5b4de  main -> main

Ansible Playbookの実行

$ ansible playbook -i inventory site.yml

無事にインストール完了!と言いたいところですが問題点が2つ。
cleanarchiverとdockerがインストールできませんでした。
terminalで直接実行してもだめです。
調べてみたところ、どうやらM1チップはちょっと癖があるようで、Intelチップと同じことが出来ないらしいです。
今回はDockerは手動でDocker Desktopをインストールしてコンテナを利用可能にしておきました。
そして、このあと、コンテナの利用でも問題が発覚することになります...
cleanarchiverは...今度調べてみます。

おわりに

今回の検証でMacへのアプリケーションのインストールはAnsibleで行えることがわかりました。
brewなのか、brew caskなのか、masなのか、masならIDを調べる、この段取りでなんとかなりそうだとわかりました。

もし、Mac Book Air M1の調子が悪くなり、再インストールすることになったとしても、このAnsible Playbookがあればすぐに同じ環境を構築することが出来ます。

さらに、アプリケーションを追加インストールしたければ、各vars/main.ymlに情報を追記してansible-playbookを再実行すればよいだけです。

Ansible Playbookは本来ならGitHubなどに登録しておき、必要に応じてgit cloneすればよいのですが、今回は完全に個人用だし、Ubuntu Serverにでも保存しておき、必要に応じて更新して再利用可能な状態にしておき、大事に保管しておきます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1