2018年1月22日

AnsibleでMacの開発環境を構築する

Share

※2018年12月12日更新


定期的にmacのお掃除をしたくなるんですが、クリーンインストールして0から環境構築したいものです。

それ以外にも、PCの新規購入や買い替え、職場のPCが変わったりと、0から開発環境を構築する場面は多々あります。

しかしながら、この環境構築、やることが盛り沢山で大変です。

しかも頻繁にやる作業でもないので結構忘れてしまって、毎回調べながらやってる気がします。

いざ環境構築が終わって開発していると、あれインストールしてないや、あの設定どうだったっけ?

みたいなことは、あるあるですよね。

そこで、今後のことも考えて、macの環境構築をAnsibleを使って自動化(60〜70%くらい)したいと思います。

前提

実行環境

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.1
BuildVersion:	18B75

手順

Macのクリーンインストール(ここでは省略)

※参考サイト
macOS を消去して再インストールする

Homebrewのインストール

Homebrew公式

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew -v
Homebrew 1.8.5

MacにAnsibleをインストール

ここでは、brewコマンドを使ってAnsibleをインストール

$ brew install ansible
$ ansible --version
ansible 2.7.4

ファイル構成

tree コマンドで表示するとこんな感じです。
Ansible利用したことある方なら特に違和感ないと思います。

$ tree
.
├── README.md
├── localhost
├── roles
│   ├── awscli
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── fonts
│   │   └── tasks
│   │       └── main.yml
│   ├── golang
│   │   ├── tasks
│   │   │   ├── install.yml
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── homebrew
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── homebrew_cask
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── macos
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   └── vars
│   │       └── main.yml
│   ├── mas
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── node
│   │   ├── tasks
│   │   │   ├── install.yml
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── pip
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   ├── ssh
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   └── vars
│   │       └── main.yml
│   ├── vsc
│   │   ├── tasks
│   │   │   └── main.yml
│   │   ├── templates
│   │   │   └── settings.json
│   │   └── vars
│   │       └── main.yml
│   ├── xcode
│   │   └── tasks
│   │       └── main.yml
│   └── yarn
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
├── site.retry
└── site.yml

各ファイルの説明

site.yml

このファイルの内容、特にrolesを見る何を実行してるかわかるかと思います。
実行不要なものは、rolesの各行をコメントアウトすれば実行されません。
Ansibleなので実行時のtag指定などで臨機応変に対応可能です。

---
# file: site.yml

# ---------------
# localhost
# ---------------
- hosts: localhost
  connection: local
  gather_facts: yes
  roles:
    - homebrew
    - homebrew_cask
    - mas
    - macos
    # - awscli
    - xcode
    - fonts
    - vsc
    - golang
    - node
    - pip
    - yarn

roles/homebrew

homebrewで必要なパッケージをインストールします。
※homebrew tapでは必要なリポジトリを追加しています。

---
# file: ./homebrew/tasks/main.yml

- block:

  - name: homebrew update
    homebrew:
      update_homebrew: true
      upgrade_all: yes

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

  - name: homebrew packages install
    homebrew:
      name: "{{ item.name }}"
      state: "{{ item.state | default('present') }}"
    with_items: "{{ packages }}"

  tags:
    - homebrew

設定ファイルに必要なパッケージを追加していくだけです。

---
# file: ./homebrew/vars/main.yml

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

packages:
  - { name: ansible, state: present }
  - { name: awscli, state: present }
  - { name: git, state: present }
  - { name: hugo, state: present }
  - { name: jq, state: present }
  - { name: mercurial, state: present }
  - { name: mas, state: present } # mas-cli(mac apple store)
  - { name: tree, state: present }
  - { name: sassc, state: present }
  - { name: nkf, state: present }
  - { name: fontconfig, state: present }  # for fc-cache
  - { name: node, state: present }
  - { name: nodebrew, state: present }
  - { name: yarn, state: present }
  - { name: brotli, state: present }
  - { name: mozjpeg, state: present }
  - { name: maven, state: present }

roles/homebrew_cask

Ansible公式 homebrew_cask - Install/uninstall homebrew casks.

MacのGUIのアプリケーションをインストールします。

---
# file: ./homebrew_cask/tasks/main.yml

- block:

  - name: homebrew cask packages install 'item.name'
    environment:
      HOMEBREW_CASK_OPTS: --appdir=/Applications
    homebrew_cask:
      name: "{{ item.name }}"
      state: "{{ item.state | default('present') }}"
    with_items: "{{ packages }}"

  tags:
    - homebrew_cask

設定ファイルに必要なパッケージを追加していくだけです。

パッケージを検索するには、下記コマンドです。

$ brew search
---
# file: ./homebrew_cask/vars/main.yml

packages:
  - { name: avira-antivirus, state: present }
  - { name: google-chrome, state: present }
  - { name: firefox, state: present }
  - { name: google-japanese-ime, state: present }
  - { name: dropbox, state: present }
  - { name: slack, state: present }
  - { name: skype, state: present }
  - { name: visual-studio-code, state: present }
  - { name: iterm2, state: present }
  - { name: sourcetree, state: present }
  - { name: docker, state: present }
  - { name: postico, state: present }
  - { name: java8, state: present }

roles/mas

A simple command line interface for the Mac App Store. Designed for scripting and automation.

Mac App Store用の簡単なコマンドラインインターフェイス。スクリプティングと自動化のために設計されています。

使い方は上のGithubのページに詳しく記載されています。

---
# file: ./mas/tasks/main.yml

- block:

  - name: mas is installed
    shell: brew list
    register: mas_brew_list
    changed_when: False
    check_mode: no

  - block:

      - name: mas get installed list
        shell: mas list
        register: mas_installed_list
        changed_when: False
        check_mode: no

      - name: mas install items
        shell: "mas install {{ item.id }}"
        when: '"item.id" not in mas_installed_list.stdout'
        with_items: "{{ packages }}"

    when: '"mas" in mas_brew_list.stdout_lines'

  tags:
    - mas

設定ファイルに必要なパッケージを追加していくだけです。

アプリIDの調べ方(例:Xcode)

$ mas search Xcode
   497799835  Xcode                                              (10.1)
  1163893338  App School for Xcode and  iOS 10 Development Free  (1.0)
  1183412116  Swiftify for Xcode                                 (4.5)
  1179007212  Code School for Xcode Free -Learn How to Make Apps (1.1.3)
  1083165894  Course for Xcode 7 Lite                            (1.0)
  1168397789  Alignment for Xcode                                (1.1.1)
   734258109  Watchdog for Xcode                                 (1.9)
  1246672247  BlockComment for Xcode                             (1.0.0)
   665134234  Training for Xcode                                 (1.3)
   830464758  IDAssetManager Lite for Xcode                      (1.13)
  1179234554  TabifyIndents for Xcode                            (1.0.1)
  1187815194  Comments for Xcode                                 (0.1.0)
  1168548047  EnumHelper for Xcode                               (1.0.0)
  1218781096  LanguageTranslator for Xcode                       (1.0.1)
  1212245111  Protocol for Xcode                                 (0.1.0)
  1214720236  Pastery for Xcode                                  (1.2)
   451202534  Project Analyzer for Xcode 4                       (1.3)
  1377998565  Comment Wrapper for Xcode                          (1.0)
  1218784832  NamingTranslator for Xcode                         (1.0.1)
  1153372713  App School for Xcode and  iOS 10 Development       (1.2)
  1076826166  Lessons for Xcode 7                                (1.0)
   650764572  Project Statistics for Xcode                       (2.0.2)
  1159371870  Code School for Xcode PRO - Learn Coding for iOS   (1.1.2)
  1360667102  Character Commands for Xcode                       (1.1)
   660835555  App Academy: Xcode Edition                         (1.3)
  1040160984  Swiftly-Clean for Xcode and Swift                  (2.0)
   949142405  AppIcon Maker for Xcode                            (2.0)
   882416115  Templates SourceCode for Xcode                     (1.0)
   884971675  Templates Apps For Xcode                           (1.0)
  1396408074  PrettyJSON for Xcode                               (1.3)
  1053790590  AssetsGenerator for Xcode                          (1.5.0)
  1185330099  Tutorial for Xcode and Swift Programming Language  (1.0)
  1004753760  iConeer - iconset and asset creator for Xcode      (1.2)
   552799390  Iconset for Xcode                                  (1.3.3)
  1296084683  Cleaner for Xcode                                  (1.0.3)
  1424316531  Localizer Xcode Extension                          (1.0)
  1003994181  Assets for Xcode: Resize images and icons for deve (3.1)
  1203792119  Code School for Xcode and iOS 10 Development       (1.2)
  1175032678  Step by Step Tutorials for Xcode 8 and IOS 10      (1.0)
  1042257116  Placeholders • Create stand-in assets for Xcode an (1.0)
   655575608  Archive Cleaner for Xcode                          (1.0.2)
  1016279141  XCArchiver - Archive Editor for Xcode              (1.4)
  1129885290  Tutorials for TVOS Swift Programming with XCODE    (1.0)

---
# file: ./mas/vars/main.yml

packages:
  - { id: 409201541, name: Pages }
  - { id: 409203825, name: Numbers }
  - { id: 409183694, name: Keynote }
  - { id: 497799835, name: Xcode }

roles/macos

owner: XXXXXは任意の値に変更

---
# file: ./macos/tasks/main.yml

- block:

  - name: DNS setting
    shell: networksetup -setdnsservers Wi-Fi 8.8.8.8 8.8.4.4
    tags:
      - dns

  - block:
    # check defaults
    # $ defaults read
    - name: set osx defaults
      osx_defaults:
        domain: "{{ item.domain }}"
        key: "{{ item.key }}"
        type: "{{ item.type }}"
        value: "{{ item.value }}"
      with_items: "{{ settings }}"
    tags:
      - osx_defaults

  - block:
    # bash setting
    - name: copy ~/.bash_profile template
      template:
        src: .bash_profile.j2
        dest: ~/.bash_profile
        owner: XXXXX
        group: staff
        mode: 0600

    - name: copy ~/.bashrc template
      template:
        src: .bashrc.j2
        dest: ~/.bashrc
        owner: XXXXX
        group: staff
        mode: 0600

    tags:
      - bash

  tags:
    - macos

設定値は、下記コマンドで見つける

$ defaults read

---
# file: ./macos/vars/main.yml

settings:
  - { domain: com.apple.finder, key: AppleShowAllFiles, type: string, value: TRUE }
  - { domain: NSGlobalDomain, key: AppleShowAllExtensions, type: bool, value: TRUE }
  - { domain: com.apple.dock, key: tilesize, type: float, value: 40 }
  - { domain: com.apple.dock, key: autohide, type: bool, value: TRUE }
  - { domain: com.apple.menuextra.battery, key: ShowPercent, type: string, value: YES }

テンプレート

# {{ ansible_managed }}
# ~/.bash_profile
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
# {{ ansible_managed }}
# ~/.bashrc
alias ls="ls -G"
alias ll="ls -lG"
alias la="ls -laG"

roles/awscli

AWS CLIを使う人用の設定

この記事(MacにAWS CLIインストール)のAnsible版

---
# file: ./awscli/tasks/main.yml

- block:

  - name: aws cli config aws_access_key_id
    command: "aws configure set aws_access_key_id {{ awscli.key }}"

  - name: aws cli config aws_secret_access_key
    command: "aws configure set aws_secret_access_key {{ awscli.secret }}"

  - name: aws cli config default.region
    command: "aws configure set default.region {{ awscli.region }}"

  - name: aws cli config default.output
    command: "aws configure set default.output {{ awscli.output }}"

  tags:
    - awscli

※key,secretを設定してください

---
# file: ./awscli/vars/main.yml

awscli:
  key: "your_key"
  secret: "your_secret"
  region: ap-northeast-1
  output: json

roles/xcode

Xcodeのコンポーネントのインストールです。

---
# file: ./xcode/tasks/main.yml

- block:

  - name: Xcode's additional required components
    raw: /Applications/Xcode.app/Contents/MacOS/Xcode -installComponents

  tags:
    - xcode

roles/fonts

開発用に使ってるフォントのインストールです。

ここでは、Rictyの派生、Ricty DiminishedとSource Han Code JP/源ノ角ゴシック Codeをインストールします。

---
# file: ./ricty/tasks/main.yml

- block:

  - name: Download ricty
    get_url:
      url: http://www.rs.tus.ac.jp/yyusa/ricty_diminished/ricty_diminished-4.1.1.tar.gz
      dest: ~/Downloads/ricty_diminished-4.1.1.tar.gz

  - name: Unzip ricty
    raw: tar zxvf ~/Downloads/ricty_diminished-4.1.1.tar.gz -C ~/Library/Fonts/


  - name: Download Source Han Code JP
    get_url:
      url: https://github.com/adobe-fonts/source-han-code-jp/archive/2.000R.tar.gz
      dest: ~/Downloads/2.000R.tar.gz

  - name: Unzip Source Han Code JP
    raw: tar zxvf ~/Downloads/2.000R.tar.gz  -C ~/Library/Fonts/

  - name: mv *.otf to  ~/Library/Fonts/
    copy:
      src: "{{ item }}"
      dest: "~/Library/Fonts"
    with_fileglob:
      - ~/Library/Fonts/source-han-code-jp-2.000R/OTF/*.otf

  - name: fc-cache
    raw: fc-cache -vf

  tags:
    - fonts

roles/vsc

開発に使ってるエディタVisual Studio Codeのインストールです。

---
# file: ./vsc/tasks/main.yml

- block:

  - name: visual studio code basic setting
    template:
      src: settings.json
      dest: "~/Library/Application Support/Code/User"
      mode: 0644

  - name: visual studio code install extension
    raw: "code --install-extension {{ item }}"
    with_items: '{{ extensions }}'

  tags:
    - vsc

インストールするエクセテンションのリストです。extensionsはUnique Identifierを指定します。

vscode-iconsのページでUnique Identifierの文字列を検索してみてください。

---
# file: ./vsc/vars/main.yml

extensions:
  - robertohuertasm.vscode-icons
  - equinusocio.vsc-material-theme
  - CoenraadS.bracket-pair-colorizer
  - mechatroner.rainbow-csv
  - IBM.output-colorizer

  # git
  - eamodio.gitlens
  - donjayamanne.githistory

  # develop
  - HookyQR.beautify
  - robinbentley.sass-indented
  - dbaeumer.vscode-eslint
  - ionutvmi.path-autocomplete

  # golang
  - ms-vscode.go

  # java, spring
  - vscjava.vscode-java-pack
  - vscjava.vscode-spring-initializr

  # ansible
  - vscoss.vscode-ansible

  # docker
  - peterjausovec.vscode-docker

  # bash
  - shakram02.bash-beautify
  - rogalmic.bash-debug

  # tools
  - humao.rest-client
  - chrmarti.regex
  - arjun.swagger-viewer

こちらは、基本設定のjsonファイルで、templateをコピーしています。

{
    "editor.cursorStyle": "block",
    "editor.fontFamily": "Ricty Diminished",
    "editor.fontSize": 16,
    "editor.highlightActiveIndentGuide": true,
    "editor.insertSpaces": true,
    "editor.minimap.enabled": false,
    "editor.renderWhitespace": "boundary",
    "editor.tabSize": 2,
    "files.insertFinalNewline": true,
    "files.trimTrailingWhitespace": true,
    "files.trimFinalNewlines": true,
    "git.confirmSync": false,
    "markdown.preview.fontFamily": "Ricty Diminished",
    "terminal.external.osxExec": "iTerm.app",
    "window.zoomLevel": -1,
    "workbench.colorTheme": "One Dark Pro",
    "workbench.iconTheme": "vscode-icons",
    "workbench.startupEditor": "newUntitledFile"
}

インストールされているvisual studio codeのエクステンションの一覧を表示する方法です。
VSC doc: Command Line Interface (CLI)

$ code --list-extensions
Arjun.swagger-viewer
chrmarti.regex
CoenraadS.bracket-pair-colorizer
dbaeumer.vscode-eslint
donjayamanne.githistory
eamodio.gitlens
Equinusocio.vsc-material-theme
HookyQR.beautify
humao.rest-client
IBM.output-colorizer
ionutvmi.path-autocomplete
mechatroner.rainbow-csv
MS-CEINTL.vscode-language-pack-ja
ms-vscode.Go
PeterJausovec.vscode-docker
redhat.java
robertohuertasm.vscode-icons
robinbentley.sass-indented
rogalmic.bash-debug
shakram02.bash-beautify
vscjava.vscode-java-debug
vscjava.vscode-java-pack
vscjava.vscode-java-test
vscjava.vscode-maven
vscjava.vscode-spring-initializr
vscoss.vscode-ansible
zhuangtongfa.Material-theme

roles/golang

gvmで管理してます。

---
# file: ./golang/tasks/main.yml

- block:

  - name: install gvm
    shell: bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
    args:
      executable: /bin/bash
    ignore_errors: yes

  - name: include install.yml
    include: "install.yml in_item={{ item }}"
    with_items: "{{ versions }}"

  tags:
    - golang

※path XXXXXは任意の値に変更

---
# file: ./golang/tasks/install.yml

- block:

  - name: "install go{{ in_item }}"
    shell: "source /Users/XXXXX/.gvm/scripts/gvm && gvm install go{{ in_item }} -B"
    args:
      executable: /bin/bash

  - name: "set default go{{ in_item }}"
    shell: "source /Users/XXXXX/.gvm/scripts/gvm && gvm use go{{ in_item }} --default"
    args:
      executable: /bin/bash

  tags:
    - golang

インストールするバージョンを指定

---
# file: ./golang/vars/main.yml

versions:
  - "1.4"
  - "1.7.6"
  - "1.8.7"
  - "1.9.7"
  - "1.10.5"
  - "1.11.2"

localhost

ホストを書いてあるだけのファイル

localhost

Ansibleの実行

$ ansible-playbook -i localhost site.yml

最後に

参考にされる方は、これベースに思考錯誤してください。

他にもできそうなことはたくさんあると思います。

技術の移り変わりも激しいのでやり過ぎ注意です。

そんなに頻度もないでしょうし、完璧を求めすぎると逆に時間かかって本末転倒になるパターンもありそうなので、60〜70%自動化するくらいの気持ちでがんばりましょう。