[Raspberry pi4] Docker でメールサーバー(Postfix + Dovecot)を建てる。

Docker

今回はDockerを使ってメールサーバの起動と諸々の設定までやってしまおう。という話。

概要

自宅のメールサーバーとして、PostfixとDovecotを使っていますが、ネイティブのパッケージでインストールすると、そもそもの設定が複雑で、かつ再構築やPCの移行時には、なにをどう設定してあるのかをすっかり忘れてしまうわけです。それに加え、スパム対策やFail2Banなど他ツールの設定も必要なので本当に面倒です。今回は Dockerを使って簡単インストールを目標にします。

ここでセットアップするラズパイは、Ubuntuのインストール、外部にポート開放ができる準備と、ドメインの設定、Let’s EncryptのSSL証明書を取得済みの状態です。

過去の関連記事
  1. Ubuntu 19.10 でPPPOE接続をしてポート開放を行う。
  2. [Raspberry pi4] Ubuntu 20.10 のヘッドレスインストール。 キーボード、ディスプレイなしでインストールする方法
  3. [Raspberry pi4] NginxのインストールとLet’s EncryptからSSLサーバー証明書を取得する
  4. [Raspberry pi4] Docker でメールサーバーを建てる。 ★ 今ここ
  5. [Raspberry pi4] Docker で WordPress を動かす。

試した環境

Raspberry Pi4 (RAM 8GB)
Ubuntu 20.10 (arm64)

$ docker –version
Docker version 20.10.2, build 2291f61

$ docker-compose –version
docker-compose version 1.25.0, build unknown

Dockerイメージは docker-mailserver を使いました。

以下のポートを使用します
・25 SMTP
・587 Submission
・993 IMAPS

docker-mailserver について

メールサーバの構築には docker-mailserver を使います。

A fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.). Only configuration files, no SQL database. Keep it simple and versioned. Easy to deploy and upgrade.

Why this image was created.

「シンプルかつ設定のバージョン管理が可能で、アップグレードも簡単にできる」 まさに私が望んでいたものでした。

docker-mailserverの 推奨スペックはこんな感じです。

推奨環境スペック
  • 1 Core
  • 1-2GB RAM
  • Swap enabled for the container
最低スペック:
  • 1 vCore
  • 512MB RAM

動かすサービスの種類と量によって、必要なリソースは変わってくるのでしょう。RaspberryPi 4であればひとまずは大丈夫そうです。

構築手順

それでは Docker で構築していきます。

docker-mailserver を取ってくる

まず、ラズパイに、githubのリポジトリをクローンします。

$ cd ~
$ git clone https://github.com/docker-mailserver/docker-mailserver.git

基本設定

クローンすると、docker-compose.ymlと、各種設定ファイルを取得できるので、メールサーバに関する基本的な情報を加えていきます。

compose.env コピーして .env ファイルを作ります。

$ cd ~/docker-mailserver
$ cp compose.env .env

.env には コンテナのホスト名、ドメイン名、コンテナ名を書きます。DOMAINNAME はメールサーバで使うメールのドメインになります。ホスト名、コンテナ名は何でも良いと思います。SELINUX_LABEL= には何も設定しません。

.envの設定例
# –––––––––––––––––––––––––––––––––––––––––––––––
# ––– Docker Compose Settings Variables –––––––––
# –––––––––––––––––––––––––––––––––––––––––––––––

HOSTNAME=mail           # コンテナのホスト名
DOMAINNAME=nosubject.io # メールサーバのドメイン名
CONTAINER_NAME=mail     # コンテナの名前

# –––––––––––––––––––––––––––––––––––––––––––––––
# ––– SELinux Compose File Settings Variables –––
# ––– options: empty, '-z' or '-Z'  –––––––––––––
# –––––––––––––––––––––––––––––––––––––––––––––––

SELINUX_LABEL=

mailserver.env にメールサーバの設定していきます。このファイルを変更するだけで、PostfixとDovecot だけでなく、いろいろなサービスを有効にできます。沢山あって使いこなせないほどですが、とりあえずは必要最低限で設定してみます。

mailserver.env の設定例(変更したところだけの抜粋です)
# ポストマスターのメールアドレス
POSTMASTER_ADDRESS=xxxx@nosubject.io

# スプーフィングを防止する
SPOOF_PROTECTION=1

# Fail2Banを有効にする
ENABLE_FAIL2BAN=1

# SSLにLet's Encryptを使う
SSL_TYPE=letsencrypt

# メッセージサイズの制限 デフォルトの10MBから20MBに変更。
POSTFIX_MESSAGE_SIZE_LIMIT=20480000

# OP25B対策でRELAY HOSTを設定する。
RELAY_HOST=smtp.gmobb.jp
RELAY_PORT=587
RELAY_USER=xxxxxxxxxx@xxxx.gmobb.jp
RELAY_PASSWORD=XXXXXXX

OP25B対策のため、RELAY_HOSTを設定しプロバイダのSMTP経由で送信しています。

Diff
diff --git a/mailserver.env b/mailserver.env
index 61f1f85..672c2bd 100644
--- a/mailserver.env
+++ b/mailserver.env
@@ -16,7 +16,7 @@ ONE_DIR=0

 # empty => postmaster@domain.com
 # => Specify the postmaster address
-POSTMASTER_ADDRESS=
+POSTMASTER_ADDRESS=postmaster@nosubject.io

 # Set different options for mynetworks option (can be overwrite in postfix-main.cf)
 # **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or
@@ -47,7 +47,7 @@ TLS_LEVEL=
 #           See also https://en.wikipedia.org/wiki/Email_spoofing
 # 1 => (recommended) Mail spoofing denied. Each user may only send with his own or his alias addresses.
 #       Addresses with extension delimiters(http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
-SPOOF_PROTECTION=
+SPOOF_PROTECTION=1

 # Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/master/README.md#sender
-rewriting-scheme-crash-course) for further explanation.
 #  - **0** => Disabled
@@ -63,7 +63,7 @@ ENABLE_CLAMAV=0
 #    cap_add:
 #      - NET_ADMIN
 # Otherwise, `iptables` won't be able to ban IPs.
-ENABLE_FAIL2BAN=0
+ENABLE_FAIL2BAN=1

 # 1 => Enables Managesieve on port 4190
 # empty => disables Managesieve
@@ -85,7 +85,7 @@ SMTP_ONLY=
 # custom => Enables custom certificates
 # manual => Let's you manually specify locations of your SSL certificates for non-standard cases
 # self-signed => Enables self-signed certificates
-SSL_TYPE=
+SSL_TYPE=letsencrypt

 # Set how many days a virusmail will stay on the server before being deleted
 # empty => 7 days
@@ -113,7 +113,7 @@ POSTFIX_MAILBOX_SIZE_LIMIT=
 # Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!)
 #
 # empty => 10240000 (~10 MB)
-POSTFIX_MESSAGE_SIZE_LIMIT=
+POSTFIX_MESSAGE_SIZE_LIMIT=20480000

 # Enables regular pflogsumm mail reports.
 # This is a new option. The old REPORT options are still supported for backwards compatibility. If this is not set and reports are enabled with the old options, logrotate will be used.
@@ -417,16 +417,16 @@ DEFAULT_RELAY_HOST=
 #
 # empty => don't configure relay host
 # default host to relay mail through
-RELAY_HOST=
+RELAY_HOST=smtp.gmobb.jp

 # empty => 25
 # default port to relay mail
-RELAY_PORT=25
+RELAY_PORT=587

 # empty => no default
 # default relay username (if no specific entry exists in postfix-sasl-password.cf)
-RELAY_USER=
+RELAY_USER=xxxxxxxxxx@xxxx.gmobb.jp

 # empty => no default
 # password for default relay user
-RELAY_PASSWORD=
+RELAY_PASSWORD=XXXXXXX

起動前の設定 その2

docker-compose.yml を変更します。

ラズパイなので、ログファイルをRAMディスク(tmpfs)へ出力しておかないと、SDカードの寿命がすぐに来てしまいます。コンテナ内のログファイルをホスト側の/var/log/mailserver(tmpfs)に出力するようにします。あと ホスト側の letsencrypt の証明書を使うようにマウント設定をしています。

./docker-compose.yml の設定例
version: '3'

services:
  mailserver:
    image: docker.io/mailserver/docker-mailserver:latest
    hostname: ${HOSTNAME}
    domainname: ${DOMAINNAME}
    container_name: ${CONTAINER_NAME}
    env_file: mailserver.env
    ports:
      - "25:25"
      # - "143:143" # 追記:外部に公開が不要なポートは外しておくこと。
      # LAN内だけに公開する場合は、"127.0.0.1:143:143" とする必要がある。
      - "587:587"
      - "993:993"
    volumes:
      - maildata:/var/mail
      - mailstate:/var/mail-state
      # ログの出力先をホスト側のtmpfsに変更
      # - maillogs:/var/log/mail
      - /var/log/mailserver/mail:/var/log/mail/
      - /var/log/mailserver/supervisor/:/var/log/supervisor/
      - ./config/:/tmp/docker-mailserver/
      # ホスト側にあるletsencryptの場所を指定する
      - /etc/letsencrypt/:/etc/letsencrypt/
    cap_add: [ "NET_ADMIN", "SYS_PTRACE" ]
    restart: always

volumes:
  maildata:
  mailstate:
  #  maillogs:

Fail2Banのログも、tmpfsに出力するように設定を変更します。./config/ にあるファイルを変更します。

./config/fail2ban-fail2ban.cf
# ログの出力先を指定
logtarget = /var/log/mail/fail2ban.log

ホスト側にフォルダを作っておきます。(作らなくてもvolumeのマウント時に自動で作ってくれるかもしれません。未検証)

# コンテナがログを出力するためのフォルダを作成
$ sudo mkdir /var/log/mailserver

※注: tmpfs上のフォルダ・ファイルはラズパイを再起動したら消えてしまいますので、ご注意。

アカウントの作成とコンテナの起動

./setup.sh で、アカウントを一つ作ってからコンテナを起動します。(アカウントはあとからでも良いかもしれません。忘れました。)

$ ./setup.sh email add xxxx@nosubject.io xxxxxxx
$ docker-compose up -d

setup.sh で、ユーザの追加やエイリアスの作成ができます。このあたりの使い勝手もシンプルですごい楽ですねー。setup.shの使い方は setup.shのガイド を見てください。

./setup.sh alias add hoge@nosubject.io xxxx@nosubject.io
./setup.sh alias add moge@nosubject.io xxxx@nosubject.io
./setup.sh alias add fuga@nosubject.io xxxx@nosubject.io

作成したユーザとエイリアスは、下記のファイルに記録されていてます。

./config/postfix-accounts.cf
./config/postfix-virtual.cf

これらのコンフィグを残しておけばdocker-compose down でコンテナを消しても、再度 up したときに同じものを作成してくれるスグレモノです。

Dockerのコンテナ起動後のポートの状態は、こんな感じです。

$ netstat -ltn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:993             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:587             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN
tcp6       0      0 :::80                   :::*                    LISTEN
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 :::443                  :::*                    LISTEN

ファイアーウォールの設定

ポート 25(smtp)、587(submission)、993(imaps)を開放します。⚠143(imap)は使わないので、開放しません。

$ sudo ufw limit smtp
$ sudo ufw limit submission
$ sudo ufw limit imaps

⚠追記:※後にポート143(imap)が開放されていることが判明し、追加の設定を行っています。下記の記事と同じ状況でした。大変参考になりましたありがとうございます。

参考:公開ホストのセキュリティがガバガバだった話
https://www.ryotosaito.com/blog/?p=492

これで、メールサーバの構築は完了です。

メールクライアントを設定すれば、外からでもメールの送受信ができるようになります。

おまけ

リレーチェック

スパムの踏み台になっていないか、Open Relay のチェックサイトで確認してみます。

open relay checker

Network Tools: DNS,IP,Email
DNS and Network troubleshooting and diagnostic tools integrated into one sweet interface.

Open Relay になっていなければOKです。Fail2Ban が動いていると チェックサイトが Banされてしまいますのでご注意。Fail2Ban がちゃんと動いていることの確認にはなりますが。

コンテナには setup.sh を使えば入れます。

$ cd ~/docker-mailserver
$ ./setup.sh debug login 

クライアントの設定

SMTP/IMAPSのユーザ名はドメイン名までを含むメールアドレス(xxxx@nosubject.io)になります。
パスワードは、setup.shで設定したものを設定すればOKです。

iPhone 標準のメールアプリだと

受信設定は
ホスト名:nosubject.io
ユーザ名:xxxx@nosubject.io
パスワード:xxxx
SSLを使用:ON
サーバーポート:993

送信設定は
ホスト名、ユーザ、パスワード、同上
SSLを使用:ON
認証:パスワード
サーバーポート:587
で接続できます。

EmacsのMewでも送受信ができました。😂

まとめ

docker-mailserver を使うとこんなにも楽に構築できるよ。というご紹介です。便利なものを作ってくれてありがたい。

わし
わし

Mewの設定も備忘録に書いておくかな。

Amazon.co.jp: ゲームウォッチ: ゲーム
ゲーム の優れたセレクションでオンラインショッピング。
Yahboom Raspberry Pi 5 アクリルケース 公式 Raspberry Pi 5 アクティブクーラーと互換性があり、Raspberry Pi 5 4GB/8GB に適しており、開発ボードを保護する Raspberry Pi 5 アクリルケース
この 5 層アクリル ケースは Raspberry Pi 5 用に特別に作られており、Raspberry Pi ボード上のすべてのコンポーネントを効果的に保護します。 透明な素材は見た目の美しさを高めるだけでなく、Wi-Fi と Bluet...
ゲーム&ウオッチ スーパーマリオブラザーズ (【Amazon.co.jp限定】ゲーム&ウオッチ オリジナルピンズ 同梱)
ゲーム&ウオッチ スーパーマリオブラザーズ (【Amazon.co.jp限定】ゲーム&ウオッチ オリジナルピンズ 同梱)
UGREEN M.2 SSD 外付けケース-M.2 NVME/PCIE SSD ケース USB C 3.2 Gen 2接続 UASP対応 10Gbps高速転送速度 アルミ制 8TB容量対応 M.2 NVMe to USB 変更 2230 2242 2260 2280(M-Key M&B Key) SSD対応 ssd 外付けケース 【NVME/PCIE専用】
このM.2 SSD 外付けケースはUSB 3.0接続又はUASPも対応しており、10Gbpsの転送規格で快適にデータを転送できます。堅牢性に優れたABSとアルミ合金を採用したボディデザインにより、耐久性が期待できるM.2 SSD 外付けケー...
Geekworm USB-C 電源アダプター PD 27W Type C、Raspberry Pi 5に適用
Geekworm Raspberry Pi 5 電源、 USB C (Type C) PD27W 電源アダプター ;
uxcell ソケットキャップヘッド M2.5 x 20mm メトリック 12.9合金鋼製 六角ネジボルト ブラック 10個
説明: 特徴:M2.5 x 20mm六角穴付きボルト、12 . 9合金鋼材。 固定部品、産業と建設のファスナー。 家の中、オフィスや工場の機器、通信機器、船の組立と他の機械工業で広く使われている。
Geekworm X1002 V1.1 PCIe NVMe M.2 SSD 2280拡張ボード、Raspberry Pi 5に適用
梱包内容: 1*X1002 NVMe M.2 SSD拡張ボード
プリンストン 内蔵 SSD 1TB PCIe Gen 3.0 x4 NVMe 連続読み取り最大2350MB/秒 M.2 2280 3D NAND メーカー保証期間3年 EPHD-ISM2-1T
■容量(※1):1TB ■フォームファクター:M.2 2280 ■インターフェイス:PCIe 3.0x4 NVMe ■コントローラー:Phison PS5013-E13T ■NANDフラッシュ:3D NAND ■連続読み取り/書き込み(最大...
Geekworm Raspberry Pi 5 ケース、アーマーアルミ金属ケース、冷却ファンが付き、ラズベリーパイ5に適用
Geekworm Raspberry Pi 5 ケース、アーマーアルミ金属ケース、冷却ファンが付き、ラズベリーパイ5に適用

コメント