Amazon EC2 + Mailuでメールサーバー構築

[Mailu](https://mailu.io/1.7/)というGUIつきメールサーバーが何でもやってくれて便利だったので作業ログを残す

# Mailu
- メールの送受信はPostfixとDovecot
- Webからアクセスできる管理画面 + Webメール（Roundcube or RainLoop）
- Rspamd, ClamAV, Radicale連携
- Let's Encryptによる自動の証明書取得と更新
- これらがDocker ComposeやKubernetesでよしなに動いてくれるのがうれしい

今回はDocker Composeで最小構成 + RainLoop + Let's Encryptをセットアップ

# インスタンスの用意
適当に用意。今回はAmazon Linux2をt2.microで使用。
セキュリティグループはまずSSHのみ

## インスタンスのセットアップ
SSHでログイン後とりあえず`sudo yum update`

### sudoにパスワードを要求する
気になるなら設定

1. `sudo passwd ec-user`
2. `sudo visudo -f /etc/sudoers.d/90-cloud-init-users`
  - ディストリか何かによっては`/etc/sudoers.d/`の別のファイルとか`/etc/sudoers`に直接書いてあるかもしれないので`ec2-user`の設定が書かれている行を探す
3. `ec2-user ALL=(ALL) NOPASSWD:ALL`を  
   `ec2-user ALL=(ALL) ALL`に変更

### SSHのポート変更
ポート以外の設定は初期設定でそれほど問題ない気がする

1. `/etc/ssh/sshd_config`でポート変更
2. sshdを再起動
3. セキュリティグループのSSH設定を更新
4. 設定したポートでSSHできるか確認

### 必要なものをインストール
#### docker
docker-composeのインストール方法は[ここ](https://docs.docker.com/compose/install/)にあるのをそのまま

```shell-session
$ sudo yum install docker
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/  # suduで使うために
```

# ネットワークのセットアップ
25番ポートを頻繁に使う場合、[AWSで制限がかかっている](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-port-25-throttle/)ので注意。他のポートは制限されていないっぽい

## Elastic IPの設定
IPアドレスを固定したいのでElastic IPを設定してインスタンスに紐付け

## DNSレコードの設定
AレコードとMXレコードを適当に設定する

| Hostname | Type | Value |
|:---------|------|:------|
| mail.example.com. | A | （取得したElastic IP） |
| example.com. | MX | mail.example.com. |

## セキュリティグループの設定

# Mailuの設定と立ち上げ
ご丁寧にも`docker-compose.yml`と`mailu.env`を生成するツールが提供されている：[mailu setup utility](https://setup.mailu.io/1.7/)
Step 4のlisten addressはインスタンスのグローバルIPではなくプライベートIPを設定することに注意。通常プライベートIPは固定されている[^1]。

## 追加設定
`docker-compose.yml`と`mailu.env`をダウンロード後、必要であれば適宜編集する。

### WebUIのアクセス制限
adminページを有効にして管理ページにアクセスすると、設定変更はできなくても編集画面は表示される。IPによるアクセス制限等を行いたい場合はnginxの設定ファイルを追加する。
Mailuの`docker-compose.yml`があるディレクトリから見て`overrides/nginx/*.conf`にあるファイルをserverディレクティブにincludeしてくれるので、例えば次のようなファイルを置いておく。

```nginx:overrides/nginx/ip.conf
allow xxx.xxx.xxx.xxx;
deny all;
```

## 実行
1. `﻿sudo docker-compose up -d`
2. `sudo docker-compose exec admin flask mailu admin admin (ドメイン名) (パスワード)`で`admin@（ドメイン名）`に対して管理者アカウントが生成される

管理画面で行う操作のほとんどはコマンドラインからも可能

```shell-session
$ sudo docker-compose exec admin flask mailu
Usage: flask mailu [OPTIONS] COMMAND [ARGS]...

  Mailu command line

Options:
  --help  Show this message and exit.

Commands:
  admin          Create an admin user 'mode' can be: - 'create' (default)...
  advertise      Advertise this server against statistic services.
  alias          Create an alias
  alias-delete   delete alias
  config-update  sync configuration with data from YAML-formatted stdin
  domain         Create a domain
  password       Change the password of an user
  setlimits      Set domain limits
  setmanager     Make a user manager of a domain
  user           Create a user
  user-delete    delete user
  user-import    Import a user along with password hash.
```

## DKIM鍵の生成
DKIMに使用する公開鍵の生成もしてくれる。
管理画面から：メールドメイン → Actionsの詳細（左端のリストアイコン） → 右上の`Generate keys`ボタン
DNSレコード例も表示してくれるので設定も楽。

[^1]: https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-instance-addressing.html#concepts-private-addresses