XREA で独自ドメインの SSL/TLS と HTTP/2 を利用する


## TLS と HTTP/2 に対応する動機

2017年8月に XREA で独自ドメインの SSL/TLS および HTTP/2 が利用できるようになりました。近年、個人情報の保護の意識が高まり、Let's Encrypt は SSL/TLS 証明書を無料で自動生成するツールを配布しています。

2017年10月にリリースされる予定の Chrome 62 では HTTP 通信に対して警告が発せられるようになり、SSL/TLS と HTTP/2 に対応したホスティングサービスはより増えてゆくことが期待されます。

SSL/TLS はサーバーサイドだけでなくクライアントサイド JS でも注目されるようになりました。ウェブアプリのオフライン機能を実現するための Service Worker は SSL/TLS を必須とします。2017年の時点で Chrome と Firefox はサポートし、Safari と Edge は開発中です。

2016年に Google はウェブとネイティブアプリの両方の利点をもった PWA（Progressive Web Apps）の開発を支援するツールの開発および配布をはじめました。


## 別のサービスの選択肢

GMO デジロックが運営するサービス以外には同じく GMO グループのロリポップも HTTP/2 および無料 SSL/TLS に対応しています。ロリポップ独自の取り組みは matsumotory 氏の[スライド](https://speakerdeck.com/matsumoto_r/loli-next)で示されています。

プログラミング言語が利用できるものの、無料 SSL もしくは HTTP/2 のどちらか利用できないホスティングサービスであれば、CDN サービスの CloudFlare を組み合わせる選択肢があります。スターサーバーの無料プラン (旧名はウェブクロウ) での取り組みは[こちらの記事](http://qiita.com/masakielastic/items/f19b13fcae0f3ac41ce0)をご参照ください。


## Docker コンテナホスティング

Docker コンテナをアップロードするだけでウェブサービスを運営できるホスティングサービスが増えてきています。VPS と比べてサービスの管理負担が減ることが期待されます。DigitalOcean や Vultr などの VPS の業者も Docker を活用するためのチュートリアルやサービスを提供しています。

手軽に始められるサービスとして Heroku が挙げられます。Heroku はクレジットカードを登録すれば、月1000時間まで無料で使うことができます。SSL/TLS は有料サービス限定です。

日本国内ではさくらインターネットは ARUKAS の試験運用を続けています。2017年9月1日時点では受付は中止しています。

Hyper.sh は必要なときだけサービスを起動させるサーバーレスをうたっています。Cron や CI (Continuous Integration) のためのビルドボットの運用を支援するためのサービスが提供されています。


## クラウドサービス

しきいは上がりますが、クラウドサービスの無料枠を利用するのであれば Google Cloud Platform（GCP）が挙げられます。Google Compute Engine の f1-micro インスタンスは無期限で無料です。ただしリージョンは us-east1、us-west1、us-central1 にかぎられます (2017年8月時点)。



## PHP 拡張モジュールのサポート状況

PHP の標準バージョンを使う場合、OS でサポートされるさまざまな PECL パッケージが導入される一方で、標準ではないバージョンを使う場合、利用可能な拡張モジュールの種類は少なくなります。記事の執筆時点で PHP 7.1 では intl (ICU) モジュールが使えませんので、CakePHP や Symfony を導入する場合、ポリフィルライブラリの導入も必要になります。JavaScript でも Intl オブジェクトの機能拡張が進められています。

## PHP 以外の言語の選択肢
XREA では PHP 以外にも Ruby や　Python などさまざまな言語を CGI で利用できます。公式にサポートされている言語以外に Node.js や Go、Lua が使えます。SSH を通して Node.js や　Go の最新バージョンを導入することもできます。

PHP 以外の選択肢を選ぶ理由として PHP では利用がむずかしいプロトコルやツールの存在です。

### HTTP/2

記事の執筆時点で PHP の curl モジュールのバージョン (7.29.0) は　HTTP/2 をサポートしません。Go は v1.6 から http2 パッケージを標準化しました。

### QUIC

別の事例は QUIC です。QUIC は HTTP/2 の高速化に使われるプロトコルで Google が採用しています。記事の執筆時点で QUIC の仕様は策定段階にあります。C 言語および Go の実装ライブラリが配布されています。

### gRPC

gRPC は Google が開発する RPC (Remote Procedure Call) です。REST API の維持負担を減らすもしくは置き換えのツールとして期待されています。フォーマットには HTTP/2 と Protocol Buffers が採用されています。独自の定義ファイルをもとにクライアントとサーバーの両方のコードを生成します。公式サイトではさまざまな言語がサポートされています。記事の執筆時点では PHP サーバーのコードを生成できません。FastCGI 対応のサーバースクリプトの生成は実験段階にあります。

gRPC は GCP (Google Cloud Platform）で公式に採用される一方で AWS (Amazon Web Services) では公式に採用されていませんので、これらのクラウドサービスを利用するかどうかも gRPC 採用の検討項目になります。サーバーレスアーキテクチャ (Google Cloud Functions、AWS Lambda) で gRPC をどのように使えばよいのかについては議論がなされています。

サーバーレスアーキテクチャではプロセスは必要なときだけ起動させて、不要になったら停止させることができることから CGI と比べられることができます。クラウドサービスの料金は時間単位なので、必要のないプロセスを停止させる時間を増やせば、固定費用を減らすことができます。

### Service Worker のサポートチェック

ブラウザーが Service Worker をサポートしているかどうかチェックするには navigator オブジェクトを使います。

```js
if ('serviceWorker' in navigator) {
  console.log('Service Worker はサポートされます。');
} else {
  console.log('Service worker はサポートされません。');
}
```

## サーバー環境の調査
### LXD による OS の仮想化

XREA の運営会社であるデジロック社員の[スライド](https://www.slideshare.net/digirock/lxd-77067068)によると、OS の仮想化に LXD が採用されているとのことです。ホスト OS は Ubuntu 16.04 LTS で、ゲスト OS は CentOS とのことです。

### カーネルのバージョン

```bash
cat /proc/version 
Linux version 4.4.0-83-generic (buildd@lgw01-29) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017
```

TCP Fast Open を利用する場合、カーネルのバージョンが 3.6 とそれ以降のバージョンが必要になります。curl 7.49.0 から `--tcp-fastopen` が導入されましたが、記事の執筆時点で XREA の curl のバージョンは 7.29.0 なので利用できません。PHP の curl モジュールの設定オプションに `CURLOPT_TCP_FASTOPEN` があります。

カーネルのバージョンを調べると Ubuntu が表示されますが、ユーザーが使える OS は CentOS です。

```bash
cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
```

念のために Ubuntu のバージョンを調べるコマンドを実行しようとしてもエラーになります。

```bash
lsb_release -a
-bash: lsb_release: command not found
```

### HTTP/2

Google Chrome で HTTP/2 であるかを確認するには HTTP/2 and SPDY indicator を導入します。HTTP/2 であればアイコンが青くなります。

nghttp2 のサポートつきの curl で HTTP/2 がサポートされるかを確認することもできます。次のように HEAD リクエストを送信します。

```bash
curl -v -I https://example.com
```

curl 7.47.0 以前のバージョンでは明示的に `--http2` を指定する必要があります。

```bash
curl --http2 -v -I https://example.com
```

nghttp2 のサポートがあるかどうかは次のコマンドで調べることができます。

```bash
curl --version
```

### SSL/TLS に使われる暗号


Google Chrome のデベロッパーツールの Security タブから通信に使われる TLS を調べることができます。サーバーがサポートするすべての暗号を調べるには nmap を使います。

```bash
nmap --script ssl-enum-ciphers -p 443 example.com
```

ブラウザーから暗号を確認したいのであれば、SSL Labs で公開されている SSL Server Test を使うことができます。

### git


デフォルトでインストールされています。

```
git --version
```

## サーバー環境のセットアップ
### インストールディレクトリ

`~/local` (`$HOME/local`) に各種ツールを導入します。

パスを追加します。

```
export PATH=$HOME/local/bin:$PATH
```

### プロンプトの変更

ユーザー名とカレントディレクトリを表示するようにしました。

```bash
export PS1='\u@\h:\w '
```

### テキストエディタ
nano をインストールしました。

```bash
./configure --prefix=~/local --enable-utf8
```

別の選択肢は Go で開発されている micro です。micro-1.x.x-linux64.tar.gz からバイナリを入手できます。

### SSH

SSH 鍵に Ed25519 を使うことにしました。OpenSSH 6.5 からサポートされます。記事の執筆時点で XREA の OpenSSL のバージョンは 6.6 でした。Ed25519 は楕円曲線による署名方式で、ECDSA や DSA よりも安全で高いパフォーマンスを発揮します。

```bash
ssh-keygen -t ed25519
ssh-copy-id -i ~/.ssh/id_ed25519.pub myuser@example.com
```

### Linuxbrew の是非

さまざまなコマンドツールを導入する場合、パッケージマネージャの Linuxbrew が選択肢として挙げられます。注意する必要があることは容量の上限です。XREA Free の場合、上限が 1GB なのでいろいろなツールを導入するとあっという間に容量の上限を超えて、アカウントが凍結されてしまうおそれがありますので、必要なツールを個別に導入したほうがよいでしょう。プログラミング言語の複数のバージョンを管理するツールにも当てはまります。

もし、容量の上限を超えてアカウントが凍結された場合、上限を超える分のファイルを削除してから運営に凍結解除の申請をする必要があります。

## CGI
### node.js

公式サイトから Linux 64ビット版をダウンロードします。

```bash
tar -Jxvf node-vx.x.x-linux-x64.tar.xz
mv node-vx.x.x-linux-x64 node
mv node ~/local/
```

パスを追加します。

```bash
export PATH=$HOME/local/node/bin:$PATH
```

```js:node.cgi
#!/usr/bin/env node

console.log("Content-type: text/plain; charset=utf-8\n");
console.log("Hello World");
```

パーミッションを 700 以上にします。

```bash
chmod 700 node.cgi
```

### Go

公式サイトから Linux 64ビット版のファイルをダウンロードします。次のように展開すれば利用できます。

```bash
tar -C ~/local -xzf go1.x.x.linux-amd64.tar.gz
```

バージョンを確認します。

```bash
~/local/go/bin/go version
```

パスを追加しましょう。

```bash
export PATH=$HOME/local/go/bin:$PATH
export GOROOT=$HOME/local/go
```

CGI のコードを書いてみましょう。

```go:go.cgi.go
package main

import "fmt"

func main() {
  fmt.Print("Content-type: text/plain; charset=utf-8\n\n")
  fmt.Println("Hello World!")
}
```

ビルドして `go.cgi` を生成します。

```bash
go build go.cgi.go
```

パーミッションを 700 に変更します。

```bash
chmod 700 go.cgi
```

### Lua

インストールされている Lua のバージョンを調べてみましょう。

```
lua -v
```

CGI スクリプトを書いてみましょう。

```lua:test.cgi
#!/usr/bin/env lua

print("Content-type: text/plain; charset=utf-8\n")
print("Hello World")
```

パーミッションを 700 に変更します。

```bash
chmod 700 go.cgi
```