WSL上のUbuntu 18.04にElixirをerlang-solutions.comからインストール

# はじめに
Windows上でElixirの環境を作る方法としては、[fukuoka.ex#8のpiacereさんの資料](https://speakerdeck.com/piacere/ji-shu-wei-lai-toelixir-di-2hui-puroguraminguwei-jing-yan-demoexceldekirebaguan-shu-xing-yan-yu-elixirmasutadekiru)の通り、[公式のインストーラ](https://elixir-lang.org/install.html#windows)をダウンロードするのが一般的。よい子はそっちでインストールしましょう。

ここで紹介するのは、Windows Subsystem for Linux (WSL)でLinux環境を準備して、その上にElixirをインストールする方法。
ここでは、[Ubuntu 18.04](https://www.microsoft.com/ja-jp/p/ubuntu-1804/9n9tngvndl3q)を使います。

また上の資料では、Linux環境の場合は、ソースからビルドするか、Dockerイメージを利用することが推奨されています。
ここでは、[Erlang Solutions](https://www.erlang-solutions.com/)が提供しているパッケージからインストールする方法を紹介します。
ソースからビルドすることの利点は、最新版を素早く試すことができることですが、 `apt`などのパッケージ管理システムを利用できないのが欠点。
Erlang Solutionsのパッケージは、パッケージ管理システムで管理できる上、リリース版への追従も2～3日程度(Elixir 1.6.6のとき)となかなかのもの。開発版の最新機能を試したい、というような場合でなければ、十分です。

# 手順
## WSLの有効化
既定では、WSLが有効化されていないため、これを有効化します。
Windows上でPowerShellを管理者モードで起動し、以下の通り実行します。

```
PS C:\WINDOWS\system32> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
この操作を完了するために、今すぐコンピューターを再起動しますか?
[Y] Yes  [N] No  [?] ヘルプ (既定値は "Y"): y
```

再起動を促されますので、再起動します。

## Ubuntu 18.04の導入
Windows上からMicrosoft Storeを起動し、Ubuntu 18.04をインストールします。
一部のアンチウィルスソフトウェアが動いていると、インストールに失敗し、「BAD POOL HEADER」と表示されてBSoDになることがあります。その場合は、アンチウィルス機能を一時的に無効化するか、別のアンチウィルスソフトウェアを導入します。

## Ubuntu 18.04の起動
Ubuntu 18.04を起動します。
初回起動時には、初期ユーザ名とそのパスワードを入力する必要があります。

```
Installing, this may take a few minutes...
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: ultraman
Enter new UNIX password: ＜＜パスワード＞＞
Retype new UNIX password:
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ultraman@messier78:~$
```

## SSHDの起動
作業の利便性のため、Ubuntu 18.04側でSSHDを有効にします。

SSHDの起動も、アンチウィルスソフトウェアと干渉して、BSoDになる場合があります。その場合は、アンチウィルス機能を一時的に停止するか、別のアンチウィルスソフトウェアを導入してください。

### Windows 側での作業
この環境には、ローカルから接続できれば十分なので、ループバックアドレスのみリッスンするよう設定し、そのアドレスを `hosts` ファイルに登録します。
SSHDがリッスンするためのループバックアドレスを決めたら、それを `hosts` ファイルに書き込みます。
ここでは、ループバックアドレス 127.255.254.1 を使い、名前を `ubuntu` としました。

```
PS C:\Windows\System32> "`n# WSL`n127.255.254.1`t`tubuntu`t`t# Ubuntu on WSL" | Out-File -Append -Encoding ascii C:\Windows\System32\drivers\etc\hosts
PS C:\Windows\System32> Select-String WSL C:\Windows\System32\drivers\etc\hosts

drivers\etc\hosts:132:# WSL
drivers\etc\hosts:133:127.255.254.1             ubuntu          # Ubuntu on WSL


PS C:\Windows\System32>
```

### Ubuntu側での作業
#### sshd_config
以下の通り作業し、上で決めたループバックアドレスのみリッスンするよう設定します。
Windows側でもSSHDが動いている場合は、リッスンするポート番号も併せて変更するといいでしょう。

```
ultraman@messier78:~$ sudo sed -i 's/^#ListenAddress 0.0.0.0$/ListenAddress 127.255.254.1/' /etc/ssh/sshd_config
ultraman@messier78:~$
```

#### 起動→失敗
起動には `service` コマンドを用います(現時点では、WSL上でsystemdは動作しません)。

```
ultraman@messier78:~$ sudo service ssh start
 * Starting OpenBSD Secure Shell server sshd                                    Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
                                                                         [ OK ]
ultraman@messier78:~$
```

ホストキーが無い旨エラーが表示されています。

#### ホスト公開鍵ペアの生成
```
ultraman@messier78:~$ sudo ssh-keygen -A
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
ultraman@messier78:~$
```

#### 起動
```
ultraman@messier78:~$ sudo service ssh restart
 * Restarting OpenBSD Secure Shell server sshd                           [ OK ]
ultraman@messier78:~$
```

#### ローカル接続試験
ローカル環境から接続できるかどうか試験してみましょう。

##### ユーザ公開鍵ペアの生成
ユーザ公開鍵ペアを生成します。公開鍵ペアの名前は、既定のままでよいので改行のみを入力してください。秘密鍵ファイルのパスフレーズは、適切なものを二度入力しましょう。

```
ultraman@messier78:~$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/ultraman/.ssh/id_ed25519): ＜＜改行＞＞
Created directory '/home/ultraman/.ssh'.
Enter passphrase (empty for no passphrase): ＜＜パスフレーズ＞＞
Enter same passphrase again: ＜＜パスフレーズ＞＞
Your identification has been saved in /home/ultraman/.ssh/id_ed25519.
Your public key has been saved in /home/ultraman/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:Oqo＜＜略＞＞
|  .o.            |
+----[SHA256]-----+
ultraman@messier78:~$
```

##### 公開鍵登録
上で作成した公開鍵 `~/.ssh/id_ed25519.pub` を `~/.ssh/authorized_keys` に登録します。初回登録時には、正しいパーミッションを与える必要があります。

```
ultraman@messier78:~$ cp .ssh/id_ed25519.pub .ssh/authorized_keys
ultraman@messier78:~$ chmod 644 .ssh/authorized_keys
ultraman@messier78:~$
```

##### 接続試験
接続してみましょう。ホスト名は、上で `hosts` に登録した名前(ここでは `ubuntu`)を使います。

```
ultraman@messier78:~$ ssh ubuntu
The authenticity of host 'ubuntu (127.255.254.1)' can't be established.
ECDSA key fingerprint is SHA256:＜＜略＞＞.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ubuntu' (ECDSA) to the list of known hosts.
Enter passphrase for key '/home/ultraman/.ssh/id_ed25519':
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.4.0-17134-Microsoft x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Jun 16 15:19:57 DST 2018

  System load:    0.52      Memory usage: 20%   Processes:       10
  Usage of /home: unknown   Swap usage:   0%    Users logged in: 0

  => There were exceptions while processing one or more plugins. See
     /var/log/landscape/sysinfo.log for more information.

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

ultraman@messier78:~$
```

## Screen
作業の利便性のため、 `screen` コマンドを導入します。

### .screenrc
`termcap` および `terminfo` の行は、 `screen` コマンドを実行したときにターミナルの幅が80に変更されることを禁止する設定です。

```
ultraman@messier78:~$ cat > .screenrc
termcap xterm* 'is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l'
terminfo xterm* 'is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l'
startup_message off
vbell off
hardstatus string "[screen %n%?: %t%?] %h"
defencoding utf8
escape ^z^z
ultraman@messier78:~$
```

### 起動→失敗
この状態で起動しようとすると、以下の通り失敗します。
これは、WSLのUbuntuでは、必要なディレクトリが作成されないためです。

```
ultraman@messier78:~$ screen
Cannot make directory '/run/screen': Permission denied
ultraman@messier78:~$
```

### /run/screen 作成→起動
必要なディレクトリ作成し、正しいパーミッションを与えると、起動に成功します。

```
ultraman@messier78:~$ sudo mkdir /run/screen
ultraman@messier78:~$ sudo chmod 777 /run/screen
ultraman@messier78:~$ screen
```

## パッケージ更新
`apt` でパッケージを最新に更新しましょう。

```
ultraman@messier78:~$ sudo apt-get update
Get:1 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:2 http://security.ubuntu.com/ubuntu bionic-security InRelease [83.2 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [83.2 kB]
＜＜略＞＞
Reading package lists... Done
ultraman@messier78:~$ sudo apt-get dist-upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
＜＜略＞＞
76 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 36.2 MB of archives.
After this operation, 82.9 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 bsdutils amd64 1:2.31.1-0.4ubuntu3.1 [60.2 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 ncurses-bin amd64 6.1-1ubuntu1.18.04 [163 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libperl5.26 amd64 5.26.1-6ubuntu0.1 [3536 kB]
＜＜略＞＞
Errors were encountered while processing:
 /tmp/apt-dpkg-install-jU9oz6/31-ebtables_2.0.10.4-3.5ubuntu2.18.04.1_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
ultraman@messier78:~$
```

## 日本語ロケールのインストール
```
ultraman@messier78:~$ sudo apt-get install language-pack-ja*
Reading package lists... Done
Building dependency tree
Reading state information... Done
＜＜略＞＞
  ja_JP.UTF-8... done
Generation complete.
ultraman@messier78:~$
```

## Emacsの導入
Emacs教徒なら、 `emacs`を導入しましょう。

### インストール
```
ultraman@messier78:~$ sudo apt-get install emacs-nox
Reading package lists... Done
Building dependency tree
Reading state information... Done
＜＜略＞＞
61 not fully installed or removed.
Need to get 32.3 MB of archives.
After this operation, 104 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 emacsen-common all 2.0.8 [17.6 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 emacs25-common all 25.2+1-6 [13.1 MB]
Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 liblockfile-bin amd64 1.14-1.1 [11.9 kB]
＜＜略＞＞
Processing triggers for libc-bin (2.27-3ubuntu1) ...
ultraman@messier78:~$
```

### .emacs.d/init.el
日本語の設定し、パッケージ管理のソース[Melpa](https://melpa.org/#/)の追加します。後はお好みで。

```
ultraman@messier78:~$ cat > .emacs.d/init.el <<'EOF'
> ;;; 日本語
> (set-language-environment "UTF-8")
> (prefer-coding-system 'utf-8)
>
> ;;; package
> (require 'package)
> ;(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
> (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
> (package-initialize)
>
> ;;; for my emacs
> (global-set-key "\M-c" 'compile)
> (global-set-key "\C-cg" 'goto-line)
> (setq inhibit-splash-screen t)
>
> EOF
ultraman@messier78:~$
```

## Elixirの導入
ついに本命のElixirを導入です。[Erlang SolutionsのDownloadページ](https://www.erlang-solutions.com/resources/download.html)の指示の通り作業します。

### 1. Adding repository entry
```
ultraman@messier78:~$ wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
＜＜略＞＞
ultraman@messier78:~$ sudo dpkg -i erlang-solutions_1.0_all.deb
Selecting previously unselected package erlang-solutions.
(Reading database ... 32975 files and directories currently installed.)
＜＜略＞＞
# deb-src http://security.ubuntu.com/ubuntu/ bionic-security multiverse
ultraman@messier78:~$
```

### 確認
`apt update` する前と後で、パッケージ `elixir` のバージョンが上がっていることを確認します。下の例では、1.3.3-2から1.6.5-1に上がっています。

```
ultraman@messier78:~$ sudo apt list elixir
Listing... Done
elixir/bionic 1.3.3-2 all
ultraman@messier78:~$ sudo apt update
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [83.2 kB]
Hit:2 http://archive.ubuntu.com/ubuntu bionic InRelease
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [83.2 kB]
＜＜略＞＞
Reading state information... Done
1 package can be upgraded. Run 'apt list --upgradable' to see it.
ultraman@messier78:~$ sudo apt list elixir
Listing... Done
elixir/unknown 1.6.5-1 all
N: There is 1 additional version. Please use the '-a' switch to see it
ultraman@messier78:~$
```

### 2. Installing Elixir
Elixir をインストールします。
`erlang` を含め、必要なパッケージが自動的にインストールされます。[Erlang SolutionsのDownloadページのFAQ](https://www.erlang-solutions.com/resources/download.html)にもありますが、Erlangについては、`esl-erlang` というオールインワンなパッケージを利用することもできます。

```
ultraman@messier78:~$ sudo apt install elixir
Reading package lists... Done
Building dependency tree
Reading state information... Done
＜＜略＞＞
Need to get 15.0 MB of archives.
After this operation, 25.6 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 erlang-base amd64 1:20.2.2+dfsg-1ubuntu2 [7323 kB]
Get:2 http://packages.erlang-solutions.com/debian bionic/contrib amd64 elixir all 1.6.5-1 [3489 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic/main amd64 erlang-crypto amd64 1:20.2.2+dfsg-1ubuntu2 [104 kB]
＜＜略＞＞
Setting up erlang-ssl (1:20.2.2+dfsg-1ubuntu2) ...
Setting up erlang-inets (1:20.2.2+dfsg-1ubuntu2) ...
Setting up elixir (1.6.5-1) ...
ultraman@messier78:~$
```

### 確認
Elixirを起動して、バージョンを確認してみましょう。

```
ultraman@messier78:~$ elixir --version
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [kernel-poll:false]

Elixir 1.6.5 (compiled with OTP 19)
ultraman@messier78:~$
```

## Emacsのelixir modeとarchemist
EmacsでElixir編集を楽しくするパッケージ、elixir-modeとalchemistを導入する。

### パッケージの導入
Emacsを起動して、 `M-x package-list-packages` でパッケージの一覧を表示し、ac-alchemist、alchemistおよびelixir-modeの行で「I」を押下して対象パッケージを選択、「x」で実行し、確認に対して「y」を入力する。

```
  abyss-theme        0.7           available  melpa-s... A dark theme with cont$
I ac-alchemist       0.1           available  melpa-s... auto-complete source f$
  ac-capf            0.1           available  melpa-s... auto-complete source w$
＜＜略＞＞
  airline-themes     1.7           available  melpa-s... vim-airline themes for$
I alchemist          1.8.2         available  melpa-s... Elixir tooling integra$
  alda-mode          0.2.0         available  melpa-s... A simple major mode fo$
＜＜略＞＞
  elisp-slime-nav    0.9           available  melpa-s... Make M-. and M-, work $
I elixir-mode        2.3.1         available  melpa-s... Major mode for editing$
  elixir-yasnippets  0.0.1         available  melpa-s... Yasnippets for Elixir
```

### 設定
```
ultraman@messier78:~$ cat >> .emacs.d/init.el <<'EOF'
>
> ;;; for Elixir
> (require 'elixir-mode)
> (require 'alchemist)
> (add-hook 'elixir-mode-hook 'ac-alchemist-setup)
> EOF
ultraman@messier78:~$
```