Ansible を使ったメール送信/転送サーバ構築


GOAL

Ansible を使って OS X から RaspberryPi 3 (Rasbian) 上にメールサーバを構築する。ただし送信と受信転送のみでメールボックスは不要。

宅鯖の Web サイト上で管理者のメールアドレスを公開する必要が出てきたので余っている RPi 上にメールサーバを構築した時の方法を記述します。受信したメールは全て普段使っている gmail アドレスに転送するので、まぁ会社の代表電話のようなものですね。

具体的なゴールは以下の3点となります。似たような要件であれば playbook を少し修正して対応可能かと思います。

  1. LAN 内 192.168.0.0/16 のPCやサーバから外部にメールを送信する SMTP サーバとする。
  2. 管理している複数のサイトの [email protected], [email protected], [email protected] 宛てのメールが全て [email protected] に転送される。
  3. 受信メールは全て転送するため mailbox としての機能は必要ない (POP3 や IMAP4 は不要)。

構成対象の RaspberryPi は IP アドレスやホスト名、それに raspi-config などの基本的な設定が済んでいるものとします。この文書では IP アドレス 192.168.100.1、ホスト名 garnet02 とします。

$ cat /etc/hostname
garnet02
$ cat /etc/hosts
...
192.168.100.1 garnet02

また OS X 上で Ansible が実行可能な状態で構成されているものとします。まだ Ansible が入っていない場合は以下の URL を参照してください。

構築手順

メールサーバにする RPi を inventory ファイルに既述します。

[mail-server]
192.168.100.1

以下の playbook ファイルを作成し playbook.yml で保存します。vars で定義した変数値は後述する template の内容に挿入されますので適当に変更してください。

playbook.yml
- hosts: mail-server
  sudo: yes
  gather_facts: no
  vars:
    hostname: garnet02
    myhostname: mail.foo.com
    mydomain: foo.com
    mydestination: bar.org, baz.jp, {{ hostname }}
    mynetworks: 192.168.0.0/16
    forward_to: [email protected]
  tasks:
    - apt: upgrade=full update_cache=yes
    - apt: name=postfix state=present
    - template: src=main.cf.j2 dest=/etc/postfix/main.cf
    - template: src=aliases.j2 dest=/etc/aliases
    - command: /usr/bin/newaliases
    - command: /etc/init.d/postfix restart

vars 値は postfix の main.cf と同じですが localhost など自明な値は template 側に直接記述しています。

名前 意味
myhostname このサーバのFQDN
mydomain LAN内から外部へ送信する時に付加するドメイン
mydestination 宛先ドメインがこのどれかと一致したらこのサーバ宛て(それ以上リレーしない)
mynetwork 送り元がここに含まれたら外部へリレーして良い
forward_to 受信したメールの転送先メールアドレス

local から local 宛のメールは xxx@garnet02 のように hostname のドメインとなるため、mydestination には {{ hostname }} を付加する必要があります。

テンプレートに使用しているのは以下の 2 ファイル。コメントを省略して最小限の部分だけにスリム化しているので、コメントも必要なら RPi から直接持って来て編集してください。

main.cf.j2
smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = {{ myhostname }}
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, {{ mydestination }}
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 {{ mynetworks }}
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
home_mailbox = Maildir/
aliases.j2
# See man 5 aliases for format
postmaster:    {{ forward_to }}

実行

以下を起動して pi ユーザの例のパスワードを入力するだけ。

$ ansible-playbook -i inventory -u pi --ask-pass playbook.yml -vvvv

以上。