redmineコンテナサーバーのnginxで自己証明書を使ってHTTPS通信にする

##はじめに

前回はredmineサーバーをpostgres,nginx,fluentdで運用するリポジトリとその使用方法にあたる記事を書きました。

[github: https://github.com/kurawo/redmine-ops-docker](https://github.com/kurawo/redmine-ops-docker)

[qiita: redmine, postgres, nginx, fluentdをdocker-composeで運用する https://qiita.com/GCkurabe/items/a1f47498f55fe85c681a](https://qiita.com/GCkurabe/items/a1f47498f55fe85c681a)

これでも簡単に運用を始められるのですが、通信の暗号化はHTTPなのでさすがにできないです。かといって私のように個人利用レベルではドメインとって証明書をちゃんとつくって運用すると手間です。ちょっと試してみたいくらいだと微妙にハードルが高いというわけです。お金もさらにかかるようになる可能性がありますからね、ドメインとっちゃうと。

というわけで、自己証明書、いわゆるオレオレ証明書を使用してHTTPS通信を行えるようにしておきます。

##注意：自己証明書なのでいったんクライアント側で証明書のための設定がいります

あくまで今回の実装は自己証明書なので、Webブラウザ、たとえばChromeがアクセスを拒否するようになってしまいます。これは証明書を正式な第三者がつくったものではないとブラウザが判定しているためです。

なのでクライアント側にこの自己証明書を許可するという処理が必要になります。つまり、webアプリ特有の「クライアントマシンではwebブラウザ入れる以外はだいたい何もしなくていい」という前提が崩れます。

一回やってしまえば終わりな個人利用であれば問題ありませんが、複数人で使用する場合はLet’s Encryptとかでもいいのでこれで発行したほうがよさげです。しかし証明書発行のためには今度はドメイン名を取得しないと始められないみたいなので、さらにやることが増えます。

[さくらインターネット　無料SSL証明書のLet’s Encryptとは？: https://ssl.sakura.ad.jp/column/letsencrypt/](https://ssl.sakura.ad.jp/column/letsencrypt/)

自己証明書でクライアント側に負荷をかけるか？曲がりなりにも第三者の目の入ってる証明書とドメインをとるためにサーバー側に負荷をかけるか？ユーザー数がひとりでも増えたら後者に倒してあげてください。とりあえず私もこれから安めのドメインをとってみるつもりです。どのみちサイト公開の予定があるので……

##コンテナを終了する
とりあえず動かしている場合はコンテナダウンしときます。

```
docker-compose down
```

## 自己証明書をDockerホストで作成する

以下の記事を参考に実装しました。

[nginxでオレオレ証明書をする https://qiita.com/snowdog/items/9c96ee0fa6ed096e8940](https://qiita.com/snowdog/items/9c96ee0fa6ed096e8940）

Docker Hostにopensslをインストールします。

```
apt-get install openssl
```

作業ディレクトリを作成します。

```
mkdir /etc/nginx
mkdir /etc/nginx/ssl
```

秘密鍵を作成します。

```
openssl genrsa -out /etc/nginx/ssl/server.key 2048
```

```
openssl req -new -key /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.csr
```

サーバーのドメイン名（またはfqdn）にコマンド名を入力します。

自分でcrtを作成します。ここがオレオレ証明書と呼ばれる由来なのでしょうか。私はこの辺を実際にやるのは初めてだったのでまだあまり理解はしきれていないですが。

```
openssl x509 -days 3650 -req -signkey /etc/nginx/ssl/server.key -in /etc/nginx/ssl/server.csr -out /etc/nginx/ssl/server.crt
```

## docker-compose.ymlでのnginxのHTTPS用ポート設定とnginx.conf設定

ブランチでhttpsというものをつくってあります。コードの編集が面倒だと思う私みたいな方は以下のコマンドで編集を行ってください。gitがいい感じにやっておいてくれます。

```
git pull origin https
```

以下は実際にやってみたい方、何をしたか知りたい方向けです。まずはdocker-compose.ymlのコメントアウトとコメント解除。

before：

```
  nginx:
    image: nginx:1.17.8
    [...]
    ports:
      - "80:80"
      #- "443:443"
```

after：

```
  nginx:
    image: nginx:1.17.8
    [...]
    ports:
      #- "80:80"
      - "443:443"
```

./nginx/nginx.confコメントアウトおよびコメント解除。

before：

```
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        # listen       443 ssl http2 default_server;
        # listen       [::]:443 ssl http2 default_server;
        client_max_body_size    4G;

        # ssl_certificate     /etc/nginx/ssl/server.crt;
        # ssl_certificate_key /etc/nginx/ssl/server.key;
```

after：

```
    server {
        #listen       80 default_server;
        #listen       [::]:80 default_server;
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        client_max_body_size    4G;

        ssl_certificate     /etc/nginx/ssl/server.crt;
        ssl_certificate_key /etc/nginx/ssl/server.key;
```

秘密鍵とcrtを作業ディレクトリからコピーします。

```
cd redmine-ops-docker
cp /etc/nginx/ssl/server.crt ./nginx/ssl/
cp /etc/nginx/ssl/server.key ./nginx/ssl/
```

コンテナアップ。

```
docker-compose up -d
```

## クライアント側での証明書を信頼するための設定

これで以下のような感じのurlでアクセスしていただければHTTPS通信に切り替わります。

```
https://192.168.33.10
```

ただし、webブラウザ側で「この接続ではプライバシーが保護されません」と表示が出るようになってしまいます。これだとwebにアクセスができません。結構高い壁ですね。

windwosでChrome使っている方は以下の方の記事の「自己証明書をChromeに設定」の項目をもとに設定を行います。

[自己署名証明書で「この接続ではプライバシーが保護されません」「SAN対応のSHA-2自己署名証明書」 https://blog.fileshelfplus.com/vps/312](https://blog.fileshelfplus.com/vps/312)

一方わたしのようなマカーの場合は以下の方の記事をもとに設定を行います。

[https://qiita.com/suin/items/be87a7a581f30b38c5f7](https://qiita.com/suin/items/be87a7a581f30b38c5f7)

これで再びwebページにアクセスしていただければhttps通信でredmineが使えるようになります。

##終わりに

これでredmineコンテナサーバーのnginxで自己証明書を使用してhttps通信にすることはできました。ただ、これだとユーザーが増えた時にこの操作をアナウンスしないといけないのでお互いに大変不便です。私はこれから簡単なドメイン取得と証明書の作成をしてみて接続できるようにしてみようと思います。