手帳

  • 2025-06-20
  • IT系

先日、ConoHaメールサーバーを利用した時の設定を書きました。ところがConoHaメールサーバーのAPIの仕様についてどこまで公開されているかわからなかったため、自分たちでメールサーバーを立てることにしました。

いくつか候補があったのですが、MailCow Dockerizedを利用することにし、nginx-proxyで動かしているサーバーに組み込むことにしました。その時の手順について簡単なガイドとしてまとめてみたいと思います。

始める前に

前提条件

  • nginx-proxyが既に稼働中
  • ドメインのDNS管理権限を持っている
  • サーバーのroot権限またはsudo権限
  • ファイアウォール設定の変更権限

ドメイン構成例

本ガイドでは以下のドメイン構成を前提とします:

  • `mail.yourdomain.com`: Mailcow管理画面専用ホスト名
  • `example.net`: メールサービスを提供するドメイン

ディレクトリ構成


/path/to/
├── nginx-proxy/                    # nginx-proxy関連ファイル
│   ├── docker-compose.yml          # nginx-proxyのDocker Compose設定
│   ├── custom.conf                 # nginx追加設定
│   ├── vhost.d/                    # 仮想ホスト個別設定
│   │   └── mail.yourdomain.com     # Mailcow用nginx設定
│   └── certs/                      # Let's Encrypt証明書(自動生成)
│       └── mail.yourdomain.com/    # ドメイン別証明書
│           ├── fullchain.pem       # 証明書チェーン
│           └── key.pem             # 秘密鍵
├── mailcow-dockerized/             # Mailcow本体
│   ├── docker-compose.yml          # Mailcowメインの設定
│   ├── mailcow.conf                # Mailcow設定ファイル
│   └── data/
│       └── assets/ssl/             # Mailcow用SSL証明書
│           ├── cert.pem            # 同期された証明書
│           ├── key.pem             # 同期された秘密鍵
│           └── dhparams.pem        # DHパラメータ
└── scripts/                        # 管理スクリプト
    └── sync-ssl.sh                 # SSL証明書同期スクリプト

重要なポイント

  • nginx-proxyが Let’s Encrypt証明書を`certs/`に保存
  • scriptsディレクトリの同期スクリプトが証明書をmailcowにコピー
  • mailcowは8080/8443ポートで動作し、nginx-proxyが80/443で受け取り

統合の課題

統合にあたって以下の課題を解決する必要があります:

  1. **ポート競合**: 両方がポート80/443を使用しようとする
  2. **SSL証明書の管理重複**: 証明書発行が競合する
  3. **ネットワークアドレスの競合**: Dockerネットワークの重複
  4. **DockerAPIの接続問題**: コンテナ間通信の設定

導入

Mailcowのインストール

bash
# 適切なディレクトリに移動
cd /path/to

# Mailcowをクローン
git clone https://github.com/mailcow/mailcow-dockerized.git

# ディレクトリに移動
cd mailcow-dockerized

# 公式の設定生成スクリプトを実行
./generate_config.sh

以下のプロンプトに回答:

  • **Mail server hostname (FQDN)**: `mail.yourdomain.com`
  • **Timezone**: `Asia/Tokyo`(デフォルトのままEnter)
  • **Branch**: `1`(masterブランチ)

mailcow.confの重要な設定

生成されたmailcow.confファイルを以下のように編集します:

# ポート設定の変更(nginx-proxyとの競合を避ける)
HTTP_PORT=8080
HTTP_BIND=0.0.0.0
HTTPS_PORT=8443
HTTPS_BIND=0.0.0.0

# ネットワーク設定(他のDockerネットワークとの競合を避ける)
IPV4_NETWORK=10.10.1

# Let's Encrypt設定(nginx-proxy側で管理するため無効化)
SKIP_LETS_ENCRYPT=y

# API設定(DockerAPI接続のため)
API_ALLOW_FROM=172.22.1.1,127.0.0.1,10.10.1.0/24

設定の理由

  • `HTTP_BIND=0.0.0.0`: nginx-proxyからアクセス可能にする
  • `IPV4_NETWORK=10.10.1`: デフォルトの`172.22.1`が競合する場合の対策
  • `SKIP_LETS_ENCRYPT=y`: SSL証明書はnginx-proxy側で一元管理

docker-compose.ymlの編集

ファイルの最後のnetworks部分を以下のように編集

networks:
  mailcow-network:
    name: mailcow-network
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-mailcow
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: ${IPV4_NETWORK:-172.22.1}.0/24
        - subnet: ${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
  proxy-net:
    external: true

nginx-mailcowサービスの設定

nginx-mailcowサービスに以下を追加:

environment:
  # 既存の環境変数...
  - VIRTUAL_HOST=mail.yourdomain.com
  - VIRTUAL_PORT=8080
  - LETSENCRYPT_HOST=mail.yourdomain.com
  - LETSENCRYPT_EMAIL=yuki@goups.jp

networks:
  mailcow-network:
    aliases:
      - nginx
  proxy-net:

dockerapi-mailcowサービスの設定(重要)

DockerAPIのエイリアスを追加:php-fpmスクリプトが`dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network`という形式でDockerAPIにアクセスするため、このエイリアスが必要です。

networks:
  mailcow-network:
    aliases:
      - dockerapi
      - dockerapi.mailcowdockerized_mailcow-network

nginx-proxy側の設定

custom.confの編集

`/path/to/nginx-proxy/custom.conf`に以下を追加:

# メールサーバー用の追加設定
client_body_buffer_size 128k;

# WebSocketサポート(SOGoなどで必要)
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

vhost設定の作成

`/path/to/nginx-proxy/vhost.d/mail.yourdomain.com`を作成:

# メール関連の特殊なヘッダー
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;

# WebSocketサポート
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

# タイムアウトを長めに設定(IMAP/SMTP接続用)
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;

ファイアウォールの設定

メールサービス用のポートを開放:

sudo ufw allow 25/tcp    # SMTP
sudo ufw allow 465/tcp   # SMTPS
sudo ufw allow 587/tcp   # Submission
sudo ufw allow 143/tcp   # IMAP
sudo ufw allow 993/tcp   # IMAPS
sudo ufw allow 110/tcp   # POP3(オプション)
sudo ufw allow 995/tcp   # POP3S(オプション)

SSL証明書の準備

nginx-mailcowコンテナ起動のため、初期ダミー証明書を作成:

# SSLディレクトリを作成
sudo mkdir -p /path/to/mailcow-dockerized/data/assets/ssl

# ダミー証明書を作成
sudo openssl req -x509 -newkey rsa:4096 \
  -keyout /path/to/mailcow-dockerized/data/assets/ssl/key.pem \
  -out /path/to/mailcow-dockerized/data/assets/ssl/cert.pem \
  -days 365 -nodes \
  -subj "/C=JP/ST=Tokyo/L=Tokyo/O=Dummy/CN=mail.yourdomain.com"

# DHパラメータファイルも作成
sudo openssl dhparam -out /path/to/mailcow-dockerized/data/assets/ssl/dhparams.pem 2048

# 権限を設定
sudo chown -R $USER:$USER /path/to/mailcow-dockerized/data/assets/ssl

起動とネットワーク確認

# proxy-netネットワークが存在しない場合は作成
docker network create proxy-net

# nginx-proxyを再起動
cd /path/to/nginx-proxy
docker compose restart nginx-proxy

# Mailcowを起動
cd /path/to/mailcow-dockerized
docker compose up -d

ドメイン追加とメールボックス作成

Mailcow管理画面へのアクセス

**重要**: 初回ログイン後、必ずパスワードを変更してください。

URL: https://mail.yourdomain.com
初期ユーザー名: admin
初期パスワード: moohoo

ドメインやメールボックスの追加は略

DNS設定(PTRレコード/SPF/DKIM)

DNS設定は、メールサーバーの信頼性と配信率に直結する最重要項目です。

逆引きDNS(PTRレコード)の設定

**これが最も重要です**。メールサーバーの信頼性に直結します。以下XServerの例

  1. Xserverアカウントパネルにログイン
  2. VPS管理画面 → VPS管理 → VPS情報パネル → 逆引きホスト
  3. 以下のように設定:
標準ホスト名: xxx-xxx-xxx-xxx.provider.example.com (変更不要)
逆引きホスト名: mail.yourdomain.com (ここを変更)

設定確認

# サーバーIPアドレスの確認
curl -s ifconfig.me

# 逆引きDNSの確認
host [サーバーIP]
# 期待される結果: xxx.xxx.xxx.xxx.in-addr.arpa domain name pointer mail.yourdomain.com.

# 正引きDNSの確認
host mail.yourdomain.com
# 期待される結果: mail.yourdomain.com has address xxx.xxx.xxx.xxx

 example.netドメインのDNS設定

example.netのDNS管理画面で以下のレコードを追加:

# MXレコード(メール受信の要)
MX   example.net                  mail.yourdomain.com    10

# メールクライアント自動設定用
A    autodiscover.example.net     [サーバーのIPアドレス]
A    autoconfig.example.net       [サーバーのIPアドレス]

# SPFレコード(送信者認証)
TXT  example.net    "v=spf1 mx a ip4:[サーバーのIPアドレス] ~all"

DKIMレコードの設定

  1. Mailcow管理画面で **Configuration****Server configuration****DKIM** をクリック
  2. `example.net` の **DKIM key** をクリック
  3. 表示されたDKIMレコードをコピーして、DNSに追加:
# 例(実際の値は管理画面で確認)
TXT  dkim._domainkey.example.net    "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQ..."

DMARCレコード(推奨)

TXT  _dmarc.example.net    "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.net"

補足:DNSレコードの説明

  • **MXレコード**: どのサーバーがこのドメインのメールを受信するかを指定
  • **A レコード**: autodiscover/autoconfigで、メールクライアントが自動設定に使用
  • **SPF**: 送信者認証。このIPアドレスからの送信を許可
  • **DKIM**: 電子署名。メールの改ざんを検知
  • **DMARC**: SPF/DKIMの結果に基づく処理方針を指定

SSL証明書の自動同期設定

iPhoneなどのメールクライアントで「証明書を確認できません」エラーが発生することを防ぐため、nginx-proxyで生成された正式なSSL証明書をmailcowに自動同期する。

現状では以下の状況

  • mailcowが自己署名証明書(ダミー証明書)を使用
  • nginx-proxyでは正式なLet’s Encrypt証明書が発行されている
  • 証明書の同期機能が存在しない

SSL証明書同期スクリプトの作成

mkdir -p /path/to/scripts
vim sync-ssl.sh

sync-ssl.shファイル

#!/bin/bash

# SSL証明書をnginx-proxyからmailcowにコピー
echo "Syncing SSL certificates from nginx-proxy to mailcow..."

# 証明書をコピー
cp /path/to/nginx-proxy/certs/mail.yourdomain.com/fullchain.pem /path/to/mailcow-dockerized/data/assets/ssl/cert.pem
cp /path/to/nginx-proxy/certs/mail.yourdomain.com/key.pem /path/to/mailcow-dockerized/data/assets/ssl/key.pem

# 権限を設定
chown $USER:$USER /path/to/mailcow-dockerized/data/assets/ssl/*

# メールサービスを再起動
echo "Restarting mail services..."
docker compose -f /path/to/mailcow-dockerized/docker-compose.yml restart dovecot-mailcow postfix-mailcow

echo "SSL certificate sync completed!"
//実行権限の付与
chmod +x /path/to/scripts/sync-ssl.sh

自動更新設定の実装

`/path/to/nginx-proxy/docker-compose.yml`のacme-companionサービスに以下の環境変数を追加:

environment:
  - DEFAULT_EMAIL=yuki@goups.jp
  - NGINX_PROXY_CONTAINER=nginx-proxy
  - ACME_CA_URI=https://acme-v02.api.letsencrypt.org/directory
  - ACME_PREFERRED_CHAIN=ISRG Root X1
  - ACME_TOS_HASH_ENABLE=true
  - ACME_POST_HOOK=/path/to/scripts/sync-ssl.sh

設定を適用

# nginx-proxyを再起動して設定を反映
cd /path/to/nginx-proxy
docker compose restart acme-companion

運用とメンテナンス

定期的なメンテナンス

システムアップデート

# Mailcowのアップデート
cd /path/to/mailcow-dockerized
./update.sh

# nginx-proxyのアップデート
cd /path/to/nginx-proxy
docker compose pull
docker compose up -d

ログ監視

# メールログの確認
docker compose logs -f --tail=100 postfix-mailcow

# 認証失敗の監視
docker compose logs dovecot-mailcow | grep "auth failed"

# nginx-proxyのログ
docker logs nginx-proxy | tail -50