プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Roundcube の立ち上げ : https での接続を可能にする (3/3)

前回の記事の続きです。今回は、 docker コンテナを起動して運用するところまでやってみます。

どこで稼働させるか?

いままで、 Rainloop は aws の EC2(スポットインスタンス)で運用していました。でも、無理に EC2 を使わずとも、 NAS 上で動かせればそれでいいのではないか?と思うようになりました。というのも、

  • メールクライアントなので、自分以外は誰も使わない
  • NAS 側に問題が起きても、 IMAP での運用なので、最悪は元のメールアカウントの Webメールを使えばよい
  • コンテナに問題が起きても、 docker で立ち上げなおしてメールアカウントを再設定すれば、(大きな遅延なく)復旧できる
  • aws で Elastic IP の有料化の話がでてきた

と考えた次第です。

ということで、いままでの検討を踏まえて、最終的に NAS の Container Station で起動することを目指します。

https での接続

本番環境として稼働させるとなると気になるのは、 Container Station で Roundcube を立ち上げると、https ではなく http での接続になっているの点です。

これ https 化するのにいい方法ないかな?と調べてみると、 docker のコンテナを立ち上げる際に、 https-portal というコンテナを使えば、めっちゃ簡単に https 接続を実現してくれるということがわかりました。

これらの記事でも触れてますが、 https-portal はリバースプロキシとして動作して、httpsでの接続を元のコンテナの公開ポート(httpプロトコルのポート)に振るという動作をしてくれます。

早速試してみます。こんな感じに docker-compose.yml を用意します。

version: '3'

services:
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    restart: always
    environment:
      DOMAINS: 'test.xxxx.yyyy.zzzz -> http://roundcubemail:80'
      # STAGE: 'production'
      # FORCE_RENEW: 'true'
  
  roundcubemail:
    image: myroundcube:latest
    container_name: myrc
#    restart: unless-stopped
    volumes:
      - ./www:/var/www/html
      - ./db/sqlite:/var/roundcube/db
#    ports:
#      - 9001:80
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://メールサーバー
      - ROUNDCUBEMAIL_DEFAULT_PORT=993
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://メールサーバー
      - ROUNDCUBEMAIL_SMTP_PORT=465

Roundcube 側は前回の記事で作ったイメージを指定しています(大きくは公式のイメージと異なりません)。 https-portal は上記の参考サイトに書かれているほぼそのままです。

test.xxxx.yyyy.zzzz に来たものを roundcubemail に振る設定ですね。

公開設定

これで、テストをしてもよかったのですが、 Container Station (NAS)がルータ(NVR510)の内側にいるので、ルータに穴をあける必要があります。

NVR510 内のサーバーを公開するにはこちらの記事などで触れていますので、詳しく書きませんが、ポイントは2か所です。

  • NAT ディスクプリタの編集:ルータの指定のポートに来たものを Container Station の https-portal のポートに転送します
  • IP フィルタの編集:内側から外側に戻るパケットを許可するルールにしてやります

特に、後者の IPフィルタについては、こちらの記事で触れたように、不正アクセス検知のパケット廃棄との兼ね合いがあるので、忘れないよう設定してやります。

接続テスト

ここまで準備できたら、さきほどの docker-compose.yml をつかって、 Container Station で起動します。 https-portal コンテナが証明書を取得するのにしばらく待ちます(コンソール画面に進行状況が表示されるのでしばし待ちます)。

上記のようにコンソールに done と表示されれば、準備完了です。完了したら、早速ブラウザから、 test.xxxx.yyyy.zzzz にアクセスしてみます。

https-portal が staging なので、証明書が信頼できないとエラーが出てきますが、無視して接続すると、ちゃんと https で接続できます。

https のポートを変更

https-portal の説明を読むと、 80 と 443 を開けておかないといけないっぽいのですが、

などからすると、 https のポート番号は変更できるようなので、これも試してみます。もちろん、テスト時は、ルータ側のポート番号も併せて変更しています。

https のポート番号を変更しても問題ないですね。

ただ、 https のポート番号を変更すると、 http で接続した際に自動的に https にリダイレクトされるのですが、リダイレクト先が 443 なので、この状態だと接続できないようになります。その点だけ注意する必要があります。

QNAP の Container Station で運用

ということで、最終的なコンテナステーションで起動するための docker-compose.yml を下記のようにします。

version: '3'

services:
  https-portal:
    image: steveltn/https-portal:1
    ports:
#      - '80:80'
#      - '443:443'
      - 'xxxx:80'
      - 'yyyy:443'
    restart: always
    volumes:
      - ./data/ssl_certs:/var/lib/https-portal
    environment:
      DOMAINS: 'xxxx.yyyy.zzzz -> http://roundcubemail:80'
      STAGE: 'production'
      # FORCE_RENEW: 'true'
  
  roundcubemail:
    image: myroundcube:latest
    container_name: myrc
#    restart: unless-stopped
    volumes:
      - ./www:/var/www/html
      - ./db/sqlite:/var/roundcube/db
#    ports:
#      - 9001:80
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://メールサーバー名
      - ROUNDCUBEMAIL_DEFAULT_PORT=993
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://メールサーバー
      - ROUNDCUBEMAIL_SMTP_PORT=465
      - ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=30M

https-portal の http 用のポート番号も変更しています。というのも、ルータで 80 番に来たものを上記の xxxx にポート番号を変更しているためです(80 番は NAS の別のサービスで使いたいので空けておきたいのです)。このようにしても、外部からは 80 番ポートを呼ぶことができるので、問題ないはずです。

また、 https-portal で取得した証明書を NAS 側から確認できるように volumes を追加しています。あと、 Roundcube の添付ファイルのファイルサイズを指定しています。

これで、コンテナを起動します。問題なく起動できたら、 QNAP に SSH でログインして、下記コマンドを実行して ident_switch をインストールして、有効化します。

[ユーザ名@NAS名 application]$ docker exec -it myrc composer require boressoft/ident_switch --update-no-dev --no-interaction

これで、完了です!

ちなみに、スマホから公衆回線経由でアクセスしてもレスポンス的にも問題なかったです。