WindowsにLinux環境をvagrantで構築する

# はじめに
故あって自PCのWindowsをクリーンインストールすることになったため、改めてWindows上に開発っぽい環境を組み立てることにする。
以下はその記録。

## 必要なもの
- [Windows PC](https://www.microsoft.com/ja-jp/windows)(10なら後々まで大丈夫。7は2020年までの命)
- [VirtualBox](https://www.virtualbox.org/)(昔は古いverじゃないとVagrantがだめって言っていたけれど今は最新版でok)
- [Vagrant](https://www.vagrantup.com/)(手に入れられる最新版でok)
- [cmder](http://cmder.net/)(ターミナル補助と最低限のUnixツールのために)
- [Visual Studio Code](https://code.visualstudio.com/)(エディタ。JavaScriptの開発ならこれ一本でよい)

## ダウンロードandインストール
Windows PC以外、上記のものすべてを公式サイトから入手する。
インストール自体は専用のインストーラに任せてもよいが、cmderとvscodeはzipを拾ってきても問題ない。
アーカイバはWindows環境のままなら[7z](https://sevenzip.osdn.jp/)だけでだいたい足りる。以前はLhaplusも選択肢だったが、UTF-8回りをうまく解釈できないぽいので除外。

### それぞれを選ぶ理由
VirtualBoxは他の仮想環境プロバイダと比較してシステムにひどく依存しないので不具合は少ないと思われる。Vagrantは仮想環境のフロントエンドとして使う。
cmderはふたつあるリンクのうち、git for windowsが入ってる方を選択することで、いろいろ足りないツールを補うことができる。
VscodeはもうひとつのElectron製であるAtomと比較して、C++アドオンによる実装部分がその軽さにつながっている。

## セットアップする。
一通りのツールをインストールしたら、いったんPC自体を再起動してからcmderを起動する。cmderを起動すると自動で最小限のPath設定をしてくれるので簡単。あとはプロンプトからいろいろ入力する。
まず、vagrant cloudにloginする必要がある。

```shell-session
Generating clink initial settings in "C:\cmder\config\settings"
Additional *.lua files in "C:\cmder\config" are loaded on startup.
Creating initial user-aliases store in "C:\cmder\config\user-aliases.cmd"...
        1 個のファイルをコピーしました。
Creating user startup file: "C:\cmder\config\user-profile.cmd"

λ vagrant login
In a moment we will ask for your username and password to HashiCorp's
Vagrant Cloud. After authenticating, we will store an access token locally on
disk. Your login details will be transmitted over a secure connection, and
are never stored on disk locally.

If you do not have an Vagrant Cloud account, sign up at
https://www.vagrantcloud.com

Vagrant Cloud username or email: [メールアドレスを入力]
Password (will be hidden):[パスワードを入力]
Token description (Defaults to "Vagrant login from DESKTOP-UV5A46S"):[空欄でおｋ]
You are now logged in.
```

vagrant cloudのIDとパスを持っていない場合は、[VagrantCloud](https://app.vagrantup.com/)のページの右上からSign upしておく。
自分のユーザー名とメールアドレス、パスワードを設定するだけで簡単に登録できる。

これを完了したらvagrantに立ち上げたいLinuxのディストリビューションを教えてやる。今回はdebian9をサンプルにしている。

```shell-session
λ vagrant box add debian/contrib-stretch64
==> box: Loading metadata for box 'debian/contrib-stretch64'
    box: URL: https://vagrantcloud.com/debian/contrib-stretch64
==> box: Adding box 'debian/contrib-stretch64' (v9.3.0) for provider: virtualbox
    box: Downloading: https://vagrantcloud.com/debian/boxes/contrib-stretch64/versions/9.3.0/providers/virtualbox.box
    box: Progress: 100% (Rate: 8053k/s, Estimated time remaining: --:--:--)
==> box: Successfully added box 'debian/contrib-stretch64' (v9.3.0) for 'virtualbox'!

λ mkdir debian9
λ cd debian9
λ vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

```

これで、vagrantの作業用として作成したdebian9ディレクトリ内にVagrantfileが作られる。
いろいろコメントアウトされているので、必要な修正を加えたのちに`vagrant up`すればよい。
ちなみに、cmderのコンソールであれば、自動でvimを使えるようになるので、仮想環境内の設定ファイルをちょっと弄るような場合なんかのためにvimを覚えておくと何かと都合がいい。

```ruby:Vagrantfile
Vagrant.configure |2| do config
  # vagrant box addで入れたboxを指定。
  config.vm.box = "debian/contrib-stretch64"

  # ホストからゲストを参照する際のIPを設定。
  # デフォルトでは192.168.33.10になっているので、必要に応じて変更する。
  config.vm.network "private_network", ip: "192.168.33.10"

  # ゲストがホストと共有するフォルダを指定。
  # オーナー・グループや、ゲスト側でのパーミッション、
  # 同期方法、共有しないフォルダを指定する。
  config.vm.synced_folder "./workspace", "/home/vagrant/workspace",
       :mount_options => ['dmode=700', 'fmode=604'],
       owner: "vagrant", group: "vagrant",
       create: true, type: "rsync", rsync_exclude: ".git/"

  # 仮想環境のプロバイダであるVirtual Boxに伝える設定。
  # なお、ストレージの確保量はdebianだとデフォルトで10GBほど準備される。
  config.vm.provider "virtualbox" do |vb|
     # Virtual BoxのGUIで起動したい場合はtrueにする。
     # デスクトップ環境を入れたい場合に。
     # もしtrueにしたときは、login: vagrant password: vagrantで入れる。
     # vb.gui = true

     # 仮想環境のメモリを指定する。
     vb.memory = "1024"
  end
```

provisionの設定はここでは除くが、設定しておくと消して入れてをする場合によく使うツールを自動で入れられるようになるので、設定したい場合は都度記述する。
そのまま`vagrant up` => `vagrant ssh`したいところだが、共有フォルダをmkdirするのを忘れずに。
これで、すぐに組み立てた仮想環境を使えるようになる。

## debianする場合の留意点。
自分の手元でいろいろ作ってみた際に気が付いたこと。

- もちろんgitは入ってない。githubリポジトリにバックアップがあるならgitのインストールと、github用のconfigにssh関連の設定も必要になる。
- 仮想環境内の設定ファイルをいじるのに、デフォルトのviだとほぼ読み取り専用状態なので、vimも入れておく。
- メイン開発の言語環境は都度そろえる。私はNode.js主体なのでnvmを導入するが、provisionで設定する場合は一工夫必要になる。
- WEBサーバーは単純な開発環境ならパッケージを導入したりdockerで済ませたりというところ。ソースコンパイルまでしてチューニングは時間的余裕がある場合に。

### nvmをprovisionする。
Vagrantdileのprovisionセクションで、単純にnvmのインストールを記述しても仮想環境に接続してnvmが使えるようにはならない。これはprovisionがrootで実行されるために発生する。
そのため、provisonでnvmを一般ユーザー(この場合はvagrant)ですぐ実行できるようにするためには、以下の記述をprovisionセクションにする必要がある。

```ruby:vagrantfile
  # yオプションをつけてupgrade及び、gitとvimをインストール。
  # nvmはgithubのリポジトリをhttpsプロトコルで引っ張って、vagrantユーザーフォルダへ。
  # .bashrcに必要な追記をした後、/home/vagrantフォルダ以下のファイル権限を
  # すべてvagrantユーザーのものに変える。
  config.vm.provision "shell", inline: <<-SHELL
     apt-get update
     apt-get -y upgrade
     apt-get install -y git vim
     git clone https://github.com/creationix/nvm.git /home/vagrant/.nvm
     echo 'export NVM_DIR="$HOME/.nvm"' >> /home/vagrant/.bashrc
     echo '[ -s "$NVM_DIR/nvm.sh" ] && \\. "$NVM_DIR/nvm.sh"' >> /home/vagrant/.bashrc
     echo '[ -s "$NVM_DIR/bash_completion" ] && \\. "$NVM_DIR/bash_completion"' >> /home/vagrant/.bashrc
     chown vagrant.vagrant -R /home/vagrant
  SHELL
```

これでゲストOSへ接続したあと、一般ユーザーのローカルでnvmが使えるようになる。
node本体のインストールはゲストOSの中で行うようにする。

### github用の設定
gitを入れたら、以下を入力。

```shell-session
$ touch ~/.gitconfig
$ git config --global user.name=ユーザーネーム
$ git config --global user.email=メールアドレス
```

nameとemailを自分のもので設定すると、gitのcommit者を指定できる。
続いてsshのキーペアを作る。

```shell-session
$ cd ~/.ssh
$ ssh-keygen -t rsa -b 2048
```

sshのキーペアは-tオプションの後にアルゴリズムを指定できる。楕円曲線ならgithubが対応しているecdsaなりed25519を指定可能。-bは鍵の長さにあたる。rsaの場合だと16384bitまで、ecdsaなら256～521bitを指定できる。
特にこだわりがないならrsaの2048bit以上を指定してあればよい。
特別に何かを指定せずエンターで送ると、id_(アルゴリズム名)と、id_(アルゴリズム名).pubという2つのファイルが出来上がっている。
この.pubのついていないほうが秘密鍵、ついているほうが公開鍵になる。
続いて同じフォルダにconfigファイルを作り、githubを設定する。

```config:config
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa #ここに自分の秘密鍵のファイル名
  User git
```
configファイルを保存したら、Githubをブラウザで見て、自分のアカウントのProfileエディット画面からssh登録ページを表示する。

![2018-03-02.png](https://qiita-image-store.s3.amazonaws.com/0/171650/526e6d2b-4bb3-7ea3-ca87-b1ccc761917f.png)
上記のNew SSH keyをクリック。

![2018-03-02 (1).png](https://qiita-image-store.s3.amazonaws.com/0/171650/3cc68d01-497e-c5a7-daf8-c9d51a0bfe10.png)
ここのtitleを後で見てもわかる表記にし、keyにconfigで指定した秘密鍵のペアにあたる公開鍵ファイルの内容をコピペする。
viなりcatなりでコンソールに表示させた公開鍵を選択してctrl+cでコピーし、このテキストエリアにctrl+vで貼り付け。

登録が完了したら、コンソールからいったんテスト。

```shell-session
vagrant@contrib-stretch:~/.ssh$ ssh -T github
The authenticity of host 'github.com (192.30.255.112)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.255.112' (RSA) to the list of known hosts.
Hi exli3141! You've successfully authenticated, but GitHub does not provide shell access.
vagrant@contrib-stretch:~/.ssh$
```

githubが持っている鍵の情報が~/.ssh/known_hostsファイルに登録され、以後はgithubにssh経由でcloneを行えるようになる。

![2018-03-02 (2).png](https://qiita-image-store.s3.amazonaws.com/0/171650/41ba3d82-6c57-283b-1f5b-9b01a26bb43a.png)

sshのテスト接続が問題なければ、鍵アイコンが緑色で表示され、ssh経由による接続があったことを伝えてくれる。

## 終わりに
環境構築はなるべく手間取らずに行えるようにする必要がある。
自動化ももちろんであるが、手順自体をきちんと把握し、クリーンインストールが発生した場合には、より迅速に最低限の環境を整えて実行できるようにする必要がある。
本記事は自身のローカル環境のメモ的要素が強いが、自分の環境を都度組み立てるために何をするかの手順書は、どこかに書き留めておくとよい。

### 追記
VS Codeが「Gitが見つかりません」と言ってくるが、Gitを動作させるのは基本的にゲストOS内なので、このエラーは無視してもかまわない。