GitLab Omnibus package の SSL 証明書を Let's Encrypt で取得する

# はじめに

Let's Encrypt では、SSL サーバ証明書を取得する際に、HTTP サーバのドキュメントルートに `.well-known` というディレクトリを作り、そこにアクセスできるかどうかでドメインの所有者の確認をしているようです。
GitLab を Omnibus package でインストールしている場合、Nginx の設定は GitLab の管理下にあるため、ドキュメントルートに手を加える場合は GitLab の設定ファイル `/etc/gitlab/gitlab.rb` をいじる必要があります。

Let's Encrypt の使い方自体は、まだ Beta 版ということもあり、他のもっと解りやすい記事に譲るとして、ここでは GitLab 側でやらなければならないことを中心に書いていきます。

# 前準備

[Let's Encrypt で手軽に HTTPS サーバを設定する - Qiita](http://qiita.com/ww24/items/9fa19594b4e3a8eb9b6f)

こちらの記事に書かれているように、Let's Encrypt では SSL サーバ証明書を取得するために、3 つのプラグインを用意しているそうです。
今回のように、既に Nginx で HTTP サーバが動いている場合は、この中の `webroot` を使います。

`webroot` は Let's Encrypt 側で HTTP サーバを用意するのではなく、既に動いているサーバのドキュメントルートにファイルを置くことで、`.well-known` の確認を行います。

まずは、それを可能にするために、GitLab にドキュメントルートの設定を行います。


## GitLab の Nginx が Let's Encrypt 用の設定を読み込むように設定

お好きなエディタで `/etc/gitlab/gitlab.rb` を開き、L450 辺りにある `nginx['custom_gitlab_server_config']` の設定をしている行をコメントアウトして、以下のように書き換えます。

```/etc/gitlab/gitlab.rb
nginx['custom_gitlab_server_config'] = "include /etc/letsencrypt/nginx.conf;"
```

GitLab が利用している Nginx の GitLab に関する設定[^1]は、`/var/opt/gitlab/nginx/conf/gitlab-http.conf` に書かれているのですが、`nginx['custom_gitlab_server_config']` を設定すると、設定した文字列をこのファイルの中に追記してくれます。

今回は `/etc/letsencrypt/nginx.conf` に書かれた設定内容をインクルードするように書きました。


## Let's Encrypt 用の設定ファイルを作成

次に、`/etc/letsencrypt/nginx.conf` を新規作成し、以下のように書きます。

```/etc/letsencrypt/nginx.conf
location ^~ /.well-known {
    alias /var/letsencrypt/.well-known;
}
```

HTTP サーバの `/.well-known` 以下にアクセスがあった場合は `/var/letsencrypt/.well-known/` を参照するように、と書きました。


## Let's Encrypt 用のドキュメントルートを用意

次に、`.well-known` を置くためのドキュメントルートとなるディレクトリを作成します。

```bash
$ sudo mkdir /var/letsencrypt
```

Let's Encrypt のスクリプトは `sudo` されて動くので、所有者は `root` のままで大丈夫でした。
SELinux などを有効にしている場合は、Nginx がここにアクセスできるようにしておいてください。


## GitLab に設定を反映

ここまでの設定を反映させるために、`reconfigure` します。

```bash
$ sudo gitlab-ctl reconfigure
```

前準備はこれで終わりです。


# SSL サーバ証明書の取得

まず Let's Encrypt をインストールします。[^2]

次に、前述したように `webroot` プラグインを使って SSL サーバ証明書を取得します。
この際に、証明書を取得したいドメインと、先ほど用意したドキュメントルートを指定します。

```bash
$ ./letsencrypt-auto certonly --webroot --webroot-path /var/letsencrypt -d gitlab.example.com
```

成功すれば以下のように表示されます。

```
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/git.example.com/fullchain.pem. Your cert will
   expire on 2016-06-29. To obtain a new version of the certificate in
   the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```

Congratulations!


# SSL サーバ証明書の設置

`/etc/letsencrypt/live/` に取得した SSL サーバ証明書のシンボリックリンクが張られているので、これを Nginx に設定します。
ここでも Nginx の設定は `/etc/gitlab/gitlab.rb` で行います。

まず HTTPS を有効にするために、`external_url` のプロトコルの部分を `http://` から `https://` に書き換えます。

```/etc/gitlab/gitlab.rb
external_url 'https://gitlab.example.com'
```

もし HTTP へのアクセスを HTTPS にリダイレクトしたい場合は、`nginx['redirect_http_to_https']` を `true` に設定します。

```/etc/gitlab/gitlab.rb
nginx['redirect_http_to_https'] = true
```

次に、先ほど Let's Encrypt で取得した証明書を設定します。

```/etc/gitlab/gitlab.rb
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.example.com/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.example.com/privkey.pem"
```

設定したら `reconfigure` して反映させます。

```bash
$ sudo gitlab-ctl reconfigure
```

# SSL サーバ証明書の更新

最後に、SSL サーバ証明書を自動更新するように設定します。

Let's Encrypt で発行された証明書は有効期限が 90 日しかないので、定期的に更新する必要があります。
発行済みの証明書を更新するためには、以下のようにします。

```bash
$ ./letsencrypt-auto renew
```

こうすると、失効期限が近づいている場合のみ更新されるようです。
強制的に更新させるには `--force-renew` オプションを付けます。

```bash
$ ./letsencrypt-auto renew --force-renew
```

これを自動で実行するために、cron に設定しましょう。

```bash
$ sudo crontab -u root -e
```

```crontab
00 05 01 * * /path/to/letsencrypt/letsencrypt-auto renew --force-renew && gitlab-ctl restart
```

GitLab の Nginx のみを再起動する方法が分からなかったので、GitLab ごと再起動しています。


[^1]: Nginx の設定ファイルの中には GitLab CI に関する設定が書かれたファイルもあるのでこう書きましたが、ややこしいですね……
[^2]: インストールの仕方については、他の記事を参考にしてください。