QNAPにメールサーバーがないので、Container Stationを使って入れることにする。
やりたいこと
個人のQNAPにメールサーバーを入れてやりたいことって、だいたいこの3つなんじゃないかなと思う。
- dovecot(+sieve) : IMAPサーバー
- postfix : ローカルのSMTPサーバー。もらったメールはLMTPでdovecotに渡す。
- getmail : 他のアカウントのメールをとってきて集約する
spamassassinもあっていいけど後回し。
なぜ世の中のメールサービスを使わないでわざわざ自分のサーバーに立てるのか
そこにサーバーがあるから。
dockerイメージを作ってみる
既に世の中にあるような気もするけど、探すのも面倒なので自分でDockerfileを作る。
最初は
最初はお約束のいろいろ。メールの中身などは後でQNAPの共有フォルダーにマウントする。マウント先は/srv/mailとする。
FROM arm32v7/ubuntu:bionic
LABEL version="0.1"
LABEL description="intranet mail server"
EXPOSE 993
VOLUME /srv/mail
パッケージ
以下のパッケージを入れる。
- dovecot-imapd
- dovecot-sieve
- dovecot-lmtpd
- postfix
- getmail
- rsyslog
- cron
- incron
- vim
vim は本当はいらないんだけど、端末から入っていろいろやりたいときにないと不便なので入れておく。
#
# package installation
#
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
RUN DEBIAN_FRONTEND=noninteractive apt-get -q -y --no-install-recommends install dovecot-imapd dovecot-sieve dovecot-lmtpd postfix cron incron getmail rsyslog
# for debugging
RUN DEBIAN_FRONTEND=noninteractive apt-get -q -y --no-install-recommends install vim
# Clean
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/*
システム設定
vmailという名前のグループとユーザーを作る。このgidとuidはQTSと同じものでなくてはならない。
QTSの方は最初のグループが101、最初のユーザーが500になるので、それに合わせておく。
あと、syslogが吐かれるようにrsyslog.confを設定する。
#
# System
#
RUN groupadd -g 101 -o vmail
RUN useradd -u 500 -d /srv/mail -g 101 -M -r -s /bin/false vmail
ADD rsyslog.conf /etc/rsyslog.conf
ちなみにsyslogはQTSの方に転送するように設定する。(これで合ってるのかな)
module(load="imuxsock")
$RepeatedMsgReduction on
$PrivDropToUser syslog
$PrivDropToGroup syslog
$WorkDirectory /var/spool/rsyslog
*.* @@server (サーバーの名前)
dovecot
dovecotはvirtual userでユーザーは作らずにメールボックスだけ用意する。
証明書(server.pem, server,key)とパスワードファイル(passwd)を別途転送する。
ADD server.pem /etc/dovecot/server.pem
ADD server.key /etc/dovecot/private/server.key
ADD dovecot.conf /etc/dovecot/dovecot.conf
RUN mkdir -p /etc/dovecot/private
RUN chown dovecot /etc/dovecot/private
RUN chmod 700 /etc/dovecot/private
ADD passwd /etc/dovecot/private/passwd
RUN chown dovecot /etc/dovecot/private/passwd
RUN chmod 600 /etc/dovecot/private/passwd
RUN mkdir -p /var/mail
RUN chown vmail:vmail /var/mail
dovecot.conf は以下の通り。機能ごとに設定ファイルを分けるのが普通なんだけど、簡単な設定しかしない場合は1つにまとめてしまった方が簡単だよね。
protocols = imap lmtp
protocol lda {
mail_plugins = sieve
}
protocol lmtp {
mail_plugins = sieve
}
#
# Auth
#
auth_mechanisms = plain
passdb {
driver = passwd-file
args = username_format=%n /etc/dovecot/private/passwd
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/srv/mail/%n
}
#
# Mail Location
#
mail_home = /srv/mail/%n
mail_location = maildir:~/mail:INBOX=~/mail/.INBOX
namespace inbox {
inbox = yes
}
namespace inbox {
mailbox Drafts {
special_use = \Drafts
}
mailbox Junk {
special_use = \Junk
}
mailbox Trash {
special_use = \Trash
}
mailbox Sent {
special_use = \Sent
}
mailbox "Sent Messages" {
special_use = \Sent
}
}
#
# SSL
#
ssl = required
ssl_cert =</etc/dovecot/server.pem
ssl_key =</etc/dovecot/private/server.key
#
# Sieve
#
plugin {
sieve = file:~/sieve;active=~/sieve/active.sieve
}
#
# lmtp
#
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0666
}
}
#
# Log
#
#auth_debug = yes
#auth_verbose = yes
#mail_debug = yes
なお、最後の3行をコメントアウトするとログが出力されるようになるので、デバッグ中はつける。
ちなみにpasswdファイルは{plain}をつけてパスワードそのものを書いてもいいんだけど、こんな感じでエンコード後のものを入れる(もちろん本物じゃないよ)。エンコードはdoveadm pw
でできるよ。
user1:jklsdafASFJla342q8fasdfajl$$AJdasix
postfix
ローカルのメールを受け取るために、SMTPサーバーを用意する(もちろん外には開放しない)。
ADD postfix.cf /etc/postfix/main.cf
ADD postfix_vmailbox /etc/postfix/vmailbox
ADD postfix_valias /etc/postfix/virtual
RUN chmod 600 /etc/postfix/vmailbox
RUN chmod 600 /etc/postfix/virtual
postfixでは、リレーしないように、バーチャルユーザーに対してdovecotにlmtp経由で放り投げるように設定。
mydomain = MYSERVERNAME.myqnapcloud.com
myorigin = $mydomain
myhostname = MYSERVERNAME
mydestination = $myhostname, localhost
masquerade_domains = $mydomain
masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient
local_header_rewrite_clients = permit_mynetworks
relayhost =
relay_transport = error
mynetworks_style = subnet
inet_interfaces = all
inet_protocols = all
default_transport = error
compatibility_level= 2
smtpd_relay_restrictions = permit_mynetworks defer_unauth_destination
virtual_mailbox_domains = MYSERVERNAME.myqnapcloud.com
virtual_alias_maps = texthash:/etc/postfix/virtual
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_minimum_uid = 100
virtual_uid_maps = static:vmail
virtual_gid_maps = static:vmail
vmailboxは次のように書く。1列目はメールアドレス、2列目はdovecotに渡すユーザー名。
user1@MYSERVERNAME.myqnapcloud.com user1
メールアドレスの変換を入れたい場合(いわゆるalias)、virtualに次のように書く。1列目のメールアドレスが2列目に変換される。
root@MYSERVERNAME.myqnapcloud.com user1@MYSERVERNAME.myqnapcloud.com
postmaster@MYSERVERNAME.myqnapcloud.com user1@MYSERVERNAME.myqnapcloud.com
getmail
getmailで外部のメールサーバーのメールをとってくるようにすると、自動的にsieveで振り分けされるので便利。
getmail自体はデーモンモードはないので、cronで動かす。
普通にaptでインストールすると、なぜかpython2がないと言って動かないので、無理やりpython2にリンクを張っている。
RUN ln -s /usr/bin/python2.7 /usr/bin/python2
ADD getmailrc /etc/getmailrc
RUN chmod 0700 /etc/getmailrc
RUN chown vmail:vmail /etc/getmailrc
getmailでは、メールサーバーにPOP3で接続し、あるメールを全部とってきてdovecotへ流す。とってきたメールは削除する。自分専用なので、もう引数にユーザー名も書いてしまう。
[retriever]
type = SimplePOP3SSLRetriever
server = MAIL_SERVER_ADDRESS
username = USERNAME
password = PASSWORD
[destination]
type = MDA_external
path = /usr/lib/dovecot/deliver
arguments = ("-e","-d","user1","-r","%(recipient)")
[options]
read_all = true
delete = true
verbose = 0
cron
定期的に動かしたい処理はcronに書いておく。getmailと、あと定期的なメールボックス処理を書く。
USER vmail
ADD crontab /tmp/crontab.services
RUN crontab /tmp/crontab.services
USER root
doveadm expunge コマンドは、条件に合致したメールを自動で消してくれる。ここでは、Trash, bulk, logの各フォルダのメールで、保存後30日以上経過したものを自動で消すようにしている。
*/5 * * * * /usr/bin/getmail -r /etc/getmailrc -g /srv/mail/.getmail
36 5 * * * /usr/bin/doveadm expunge -u user1 \( mailbox Trash or mailbox bulk or mailbox log \) savedbefore 30d
最後に全部を動かす設定
dockerだとsystemdみたいなものはないので、各サービスを順番に起動するrun.shを書いて、CMDで実行できるようにしておく。
ADD run.sh /root/run.sh
RUN chmod 0755 /root/run.sh
CMD /root/run.sh
.getmailフォルダはコンテナの外のボリュームに作りたいので、Dockerfileではなく実行時にフォルダを作成する。後は各サービスを起動して無限ループだ。
#!/bin/sh
mkdir -p /srv/mail/.getmail
chmod 0700 /srv/mail/.getmail
chown vmail:vmail /srv/mail/.getmail
#
# Run services
#
/usr/sbin/rsyslogd
/usr/sbin/cron
/usr/sbin/dovecot
/usr/sbin/postfix start
while true
do
sleep 99999999
done