特定時点のR環境をVagrantで再現する (Windows)

# 動機

数年前に作成したRスクリプトやRmarkdownファイルを持ち出してきて現在の環境で実行すると、当時問題なかったはずのコードが思うように動かないことがあります。再利用するなら古いコードを書き直すことが望ましいですが、検証目的の場合など、改変したくない or できない場合もあります。
かといって、現在使っている解析環境でR本体やライブラリを依存関係を含めて入れ替えるのは大変ですし、他のプロジェクトの解析にも影響が出てしまう恐れがあります。

## やりたいこと

「からだにいいもの」で[紹介されていた](https://www.karada-good.net/analyticsr/r-420) **`versions`** パッケージの[CRANページ](https://cran.r-project.org/web/packages/versions/index.html)を読んで、 Microsoft R Openのサイト [Microsoft R Application Network (MRAN)](https://mran.revolutionanalytics.com/) には、毎日のCRANライブラリのスナップショットが公開されていることを知りました。
そこからR本体やライブラリをインストールすることができれば、任意の時点（ただし2014年9月17日以降）における最新のR環境が再現できるはずです。

そこで、[Vagrantでローカルの仮想マシンにRStudioServer環境を作る](http://qiita.com/kazutan/items/6048fa8d46683dcad788) を参考に仮想環境に過去のR環境を再現することを考えました。


## 実行環境

この記事は、以下の環境で構築した際の記録です。

* Windows 10 Professional 64bit
* Oracle VM VirtualBox 5.1.2 r108956
* Vagrant 1.9.1
* Git for Windows 2.10.1

ベースになるVagrant boxは、上記ページに倣って **"ubuntu/trusty64"**（ubuntu 公式の Ubuntu Server 14.04 LTS イメージ）を使うことにしました。

# 手順

配布パッケージにライブラリが含まれているWindows版Rと異なり、UbuntuではCRANにある現時点の最新版のライブラリがインストールされるため、Rと必要なライブラリの入手元にMRANのスナップショットを利用するように変更します。
今回は [2016-04-01のスナップショット](https://mran.revolutionanalytics.com/snapshot/2016-04-01) からのインストールを行いました。

## 1. VirtualBoxとVagrantのインストール

それぞれの公式サイトから配布パッケージを入手し、インストールします（要再起動）。

* Oracle VM VirtualBox : https://www.virtualbox.org/
* Vagrant :              https://www.vagrantup.com/

## 2. Ubuntu Serverの仮想環境を作成

### 2-1. ターミナルの準備

今回は、Git for Windows の **Git Bash** (MINGW32/mintty) を使用しました。
これには、ssh接続に必要なツールもインストールされているので、そのまま操作に利用できます。

Vagrant自体はWindowsコマンドプロンプト（cmd.exe）から操作することもできますが、Ubuntu環境の設定には別途ssh接続のためのツールが必要です。一時的な設定であれば後述の方法でしのぐことはできます。

### 2-2. Vagrant boxの入手

Git Bash（またはコマンドプロンプト）を開いて、

```bash
$ vagrant box add "ubuntu/trusty64"
```
と入力すると、ubuntu 公式の Ubuntu Server 14.04 LTS イメージがダウンロードされVagrantに登録されます。
数百MBあるので気長に待ちます。一度ダウンロードが済めば、次からはダウンロード済のイメージが使用されるようになります。

### 2-3. 仮想環境の作成

操作しやすい場所に仮想環境用のディレクトリ（フォルダ）を準備します。
今回は`C:\Home\vagrant\r_2016Apr`に仮想環境を置くことにしました。
`mkdir`でもエクスプローラーでも良いので、上記ディレクトリを作成しておきます。

改めてGit Bash（またはコマンドプロンプト）を開いて、

```bash
$ cd /c/Home/vagrant/r_2016Apr/
# コマンドプロンプトの場合は
# > cd c:\Home\vagrant\r_2016Apr

$ vagrant init "ubuntu/trusty64"
```

とすると、作業ディレクトリに `Vagrantfile` が作成されます。この `Vagrantfile` を編集して様々な設定ができますが、まずはターミナルを閉じずに、そのままUbuntu Serverを起動してみます。

```bash
$ vagrant up
```

ターミナルに沢山の出力が表示され、しばらくして待機状態のプロンプトになります。
特にエラーメッセージが表示されていなければ、仮想環境が起動しているはずです（VirtualBoxマネージャーを起動してみると、`r_2016Apr_default_...`というUbuntu 64bitの仮想マシンが実行中になっています）。

`Vagrantfile` の設定を変えた後、仮想環境を再起動する時は、

```bash
$ vagrant reload
```

仮想環境の終了は、

```bash
$ vagrant halt
```

設定を変えすぎて、一旦破棄して最初の状態に戻したい場合は、

```bash
$ vagrant destroy
```

です。

### 2-4. 仮想環境の操作

#### a) sshログイン

設定を変更していなければ、動作中のVagrant仮想環境のディレクトリで（Git bashなどのssh接続が使える）ターミナル環境から

```bash
$ vagrant ssh
```

とするだけで仮想環境へssh接続、ログインした状態になります。

TeraTermなどでssh接続する場合は、IPアドレスやポート番号などの設定が必要とのことです。
参考：[WindowsでVagrantを導入、バックアップ、復元のまとめ](http://qiita.com/ruby_kumagoro/items/bf8d22e2731052fa7f8a)

#### b) Git bashなどがない場合

Windowsコマンドプロンプト（cmd.exe）から操作する場合は、sshなどがそのままでは含まれていないので、かわりにVirtualBoxのGUIで操作することにします。
参考：[Vagrant で仮想ウィンドウを GUI モードで起動する設定](http://weblabo.oscasierra.net/vagrant-vb-gui/)

まず、`Vagrantfile`をテキストエディタで開いて47行目前後にある `vb.gui = true` を有効にします。

```bash:Vagrantfile
  config.vm.provider "virtualbox" do |vb|                   # <- コメント外す
#   # Display the VirtualBox GUI when booting the machine
    vb.gui = true                                           # <- コメント外す
#
#   # Customize the amount of memory on the VM:
#   vb.memory = "1024"
  end                                                       # <- コメント外す
```

`vagrant reload` で再起動（停止中の場合は`vagrant up`で起動）すると、VirtualBoxの画面でターミナルが開くので、ユーザー名、パスワードとも `vagrant`でログインします。
ただし、キーボード設定が英語キーボードになっているので、ログイン後に

```bash
$ sudo loadkeys jp
```

として一時的に日本語キーボードに切り替えておきます。
参考：[Ubuntu12.04 キーボード設定の変更](http://qiita.com/ktyubeshi/items/847b05b7879e2f45da54)

![vb-terminal.png](https://qiita-image-store.s3.amazonaws.com/0/137711/e4fe8c3d-9d4b-3991-1982-07240e08d526.png)

### 2-5. 日本語フォントのインストール

グラフの文字化け対策のため、先に日本語フォントをインストールしておきます。
仮想環境へログインして、

```bash
$ sudo apt-get update
$ sudo apt-get install fonts-takao
```

参考：[RStudio Serverの練習 - Part1: はじめに](http://masato.github.io/2014/08/13/rstudio-exercise-part1/)

## 3. MRANスナップショットからRをインストール

### 3-1. aptレポジトリとgpg鍵の追加

スナップショットのURL ( https://mran.revolutionanalytics.com/snapshot/2016-04-01/ )と代表的なCRANミラーの https://cran.rstudio.com を見比べて、@kazutan さんの [記事](http://qiita.com/kazutan/items/6048fa8d46683dcad788#r%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) を参照しつつaptの `source.list` を更新します。

起動した仮想環境へログインし、

```bash
$ export MRAN="https://mran.revolutionanalytics.com/snapshot/2016-04-01"
$ echo "deb ${MRAN}/bin/linux/ubuntu trusty/" | \
  sudo tee -a /etc/apt/sources.list.d/cran.list
```

（スナップショットのURLは後でも必要なので、いったん環境変数に入れておきます）
MRANのスナップショットもgpg鍵は `E084DAB9` で良いようですので、登録します。

```bash
$ gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E084DAB9
$ gpg -a --export E084DAB9 | sudo apt-key add -
```

Rをインストールすべく、aptデータベースの更新を行います。

```bash
$ sudo apt-get update
```

認証エラーで mran.revolutionanalytics.com から情報が取得できなかったという警告が表示されました。

> W: Failed to fetch https://mran.revolutionanalytics.com/snapshot/2016-04-01/bin/linux/ubuntu/trusty/Packages  server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

インストール候補のRもubuntuのレポジトリにある（古い）もののようで、やはりMRANスナップショットの追加は機能していないようです。

```bash
vagrant@vagrant-ubuntu-trusty-64:~$ apt-cache policy r-base
r-base:
  Installed: (none)
  Candidate: 3.0.2-1ubuntu1
  Version table:
     3.0.2-1ubuntu1 0
        500 http://archive.ubuntu.com/ubuntu/ trusty/universe amd64 Packages
```

### 3-2. Microsoft IT SSL SHA2 CA証明書のインストール

mran.revolutionanalytics.com では、Microsoft IT SSL SHA2による証明書が使われています。これが `"ubuntu/trusty64"` には登録されていないのが原因のようですので、証明書を入手して登録します。

証明書自体は https://www.microsoft.com/pki/mscorp/cps/ で公開されていますが、そのままでは登録できないバイナリ（DER）形式のため、PEM (Privacy Enhanced Mail) 形式（拡張子は.pemではなく.crtにする必要あり）に変換する必要があります。

```bash
$ wget "http://www.microsoft.com/pki/mscorp/msitwww2(1).crt" -U ""
$ openssl x509 -in "msitwww2(1).crt" -inform DER -out msitwww2.crt -outform PEM
$ sudo cp msitwww2.crt /usr/share/ca-certificates/
$ echo "msitwww2.crt" | sudo tee -a /etc/ca-certificates.conf
$ sudo update-ca-certificates
```

* [RSA鍵、証明書のファイルフォーマットについて](http://qiita.com/kunichiko/items/12cbccaadcbf41c72735#pem%E5%BD%A2%E5%BC%8F%E3%81%AE%E8%A8%BC%E6%98%8E%E6%9B%B8--der%E5%BD%A2%E5%BC%8F%E3%81%AE%E8%A8%BC%E6%98%8E%E6%9B%B8)
* [How do you add a certificate authority (CA) to Ubuntu?](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)

### 3-3. 改めてRをインストール

CA証明書の登録が済んだら、aptデータベースの更新を行います。

```bash
$ sudo apt-get update
```

今度は警告なく更新が終了しました。Rのインストール候補も、MRANにある 2016-04-01時点で最新の version 3.2.4-revised に変わっています。

```bash
vagrant@vagrant-ubuntu-trusty-64:~$ apt-cache policy r-base
r-base:
  Installed: (none)
  Candidate: 3.2.4-revised-1trusty0
  Version table:
     3.2.4-revised-1trusty0 0
        500 https://mran.revolutionanalytics.com/snapshot/2016-04-01/bin/linux/ubuntu/ trusty/ Packages
     3.2.4-1trusty 0
        500 https://mran.revolutionanalytics.com/snapshot/2016-04-01/bin/linux/ubuntu/ trusty/ Packages
     # 以下省略
```

Rをインストールします。
大量のファイル・標準ライブラリがインストールされるのでしばらく待ちます。

```bash
$ sudo apt-get install -y r-base r-base-dev
```

### 3-4. ライブラリのインストール

はじめに、`install.packages()` で参照されるCRANレポジトリもMRANのスナップショットになるように `~/.Rprofile` に設定します。

```bash
$ echo "options(repos = '${MRAN}')" > ~/.Rprofile

# 確認
$ cat ~/.Rprofile
options(repos = 'https://mran.revolutionanalytics.com/snapshot/2016-04-01')

```

Rを起動して、必要なライブラリをインストールします。

```bash
$ R

R version 3.2.4 Revised (2016-03-16 r70336) -- "Very Secure Dishes"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

# Rの起動メッセージ 途中省略

> install.packages(c("dplyr", "tidyr", "ggplot2"))
```

**`rmarkdown`**パッケージのように、解析そのものに影響せず新しいバージョンを使いたいものは `repos=` オプションを指定してインストールすれば、最新のものを入れることができます。
（最近の**`rmarkdown`**を使う場合は、**`formatR`**の新しいバージョンを入れておいたほうが良いようです。）

```r
> install.packages(c("rmarkdown", "formatR"), repos = "https://cran.rstudio.com/")
```

## 4. RStudio Serverのインストール

### 4-1. RStudio Server本体のインストール

[RStudio公式](https://www.rstudio.com/products/rstudio/download-server/) のガイドに従い、RStudio Serverをインストールします。

```bash
$ sudo apt-get install gdebi-core
$ wget https://download2.rstudio.org/rstudio-server-1.0.136-amd64.deb
$ sudo gdebi rstudio-server-1.0.136-amd64.deb
```

RStudio ServerのCRANミラー設定は `/etc/rstudio/rsession.conf` に `r-cran-repos=` を記載すれば良いようです。
参考：[RStudio - Configuring the Server](https://support.rstudio.com/hc/en-us/articles/200552316-Configuring-the-Server)

```bash
$ echo "r-cran-repos=${MRAN}" | sudo tee -a /etc/rstudio/rsession.conf
```

しかし、これは私の手元ではうまく機能しませんでした。対処法をご存じの方がおられましたらご教示ください。

### 4-2. Vagrant側の設定

仮想環境のディレクトリ（今回は `C:\Home\vagrant\r_2016Apr`）にある`Vagrantfile`をテキストエディタで開き、25行目前後にある `"forwarded_port"` の設定を編集します。

```bash:Vagrantfile
# config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "forwarded_port", guest: 8787, host: 1111
```

上書き保存したら、仮想環境を再起動します。

```bash
$ vagrant reload
```

### 4-3. ブラウザ経由でアクセス

仮想環境の再起動が完了したら、以下のURLにブラウザでアクセスします。

```
http://localhost:1111
```

無事に稼働しているとログイン画面になりますので、ユーザー名、パスワードとも `vagrant` でログインすると、RStudio Serverが使用できるはずです。

確認できたらブラウザを閉じて、仮想環境を終了します。

```bash
$ vagrant halt
```

Windowsではその都度ターミナルを開いてコマンド入力で仮想環境を起動するのはやや不便なので、作業ディレクトリに以下のようなバッチファイルを作って、そのショートカットをデスクトップに置いておくと便利です。

```bat:R_2016Apr.bat
vagrant up
start http://localhost:1111/
pause 何かキーを押すと、RStudio/Vagrant/VirtualBoxを終了します。
vagrant halt
```

## 5. セットアップの自動化

あらかじめ `Vagrantfile` に設定や環境整備用の手順（プロビジョニングスクリプト）を記載しておけば、

```bash
$ vagrant up
```

だけで同じ環境を再現できるようになり、新しいパッケージを追加して後悔した場合などはいつでも

```bash
$ vagrant destroy
$ vagrant up
```

でもとに戻すことができます。

@kazutan さんの[記事](http://qiita.com/kazutan/items/6048fa8d46683dcad788#vagrantfile)を元に、上記の処理を自動化するための `Vagrantfile` を作成しました。

プロビジョニングスクリプトに書き足して、あわせてGitをインストールしたりすることも出来ます。

```:Vagrantfile
Vagrant.configure(2) do |config|

# ベースになるvagrant box
  config.vm.box = "ubuntu/trusty64"

# 共有ディレクトリ設定
# c:\Home\GitRepos を ~/GitRepos とする
# config.vm.synced_folder "c:/Home/GitRepos", "/home/vagrant/GitRepos"

# ポートフォワーディング設定
  config.vm.network "forwarded_port", guest: 8787, host: 1111

# 仮想マシンの設定
  config.vm.provider "virtualbox" do |vb|
  # Display the VirtualBox GUI when booting the machine
  #  vb.gui = true
  # Customize the amount of memory on the VM:
    vb.memory = "2048"
  end

# 以下プロビジョニング用スクリプト
$script = <<SCRIPT

## Japanese language support
#sudo apt-get install -y language-pack-ja-base language-pack-ja
sudo apt-get install -y fonts-takao

## install Microsoft IT SSL SHA2 CA Certificate
wget "http://www.microsoft.com/pki/mscorp/msitwww2(1).crt" -U ""
openssl x509 -in "msitwww2(1).crt" -inform DER -out msitwww2.crt -outform PEM
sudo cp msitwww2.crt /usr/share/ca-certificates/
echo "msitwww2.crt" >> /etc/ca-certificates.conf
sudo update-ca-certificates
rm *.crt

## settings to use Microsoft R Application Network (MRAN) snapshot
export MRAN="https://mran.revolutionanalytics.com/snapshot/2016-04-01"
echo "deb ${MRAN}/bin/linux/ubuntu trusty/" > /etc/apt/sources.list.d/cran.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E084DAB9
echo "options(repos = '${MRAN}')" > /home/vagrant/.Rprofile

## install latest version of R at 2016-04-01 (ver.3.2.4 revised)
sudo apt-get update
sudo apt-get install -y r-base r-base-dev

## for install devtools, rvest(libxml2)
sudo apt-get install -y libcurl4-openssl-dev libssl-dev libxml2-dev

## r-packages install
sudo R -e "install.packages('devtools', dep = TRUE)"
sudo R -e "install.packages('tidyr',    dep = TRUE)"
sudo R -e "install.packages('dplyr',    dep = TRUE)"
sudo R -e "install.packages('ggplot2',  dep = TRUE)"

sudo R -e "install.packages('rmarkdown', repos = 'https://cran.rstudio.com/', dep = TRUE)"
sudo R -e "install.packages('formatR',   repos = 'https://cran.rstudio.com/', dep = TRUE)"
sudo R -e "install.packages('revealjs',  repos = 'https://cran.rstudio.com/', dep = TRUE)"

## rstudio-server install
sudo apt-get install -y gdebi-core
wget https://download2.rstudio.org/rstudio-server-1.0.136-amd64.deb
sudo gdebi -n rstudio-server-1.0.136-amd64.deb
rm *.deb
echo "r-cran-repos=${MRAN}" >> /etc/rstudio/rsession.conf

SCRIPT

# スクリプト実行
  config.vm.provision "shell", inline: $script

end
```

## ToDo

* セキュリティなど、Ubuntu Serverの設定を整える
    * 現状はlocalhostで一時的に使用しているのみのため、Windowsのセキュリティソフトがあることを頼りにしてUbuntuの方では特に設定していない状態です
* Texをインストールして、RStudio/rmarkdownでPDFレポートが作成できるようにしたい
* Dockerも試してみたい

参考にさせて頂いた先達の皆様に感謝致します。