PostfixAdmin のインストール
~ Web 画面でメールアカウントを管理 ~
2023-01-11 作成 福島
2023-01-23 更新 福島
TOP > tips > postfixadmin

0. 設置要件

  • 既に構築済みのメールサーバに PostfixAdmin を組み込みます。
    注意: 必ず Postfix と Dovecot のメールサーバを平文ひらぶん (暗号化無し)暗号化ありで構築しておいてください。
    (本稿ではメールサーバとして動作する最低限の設定を省略しています)
  • データベースに SQLite を使用するのでセキュリティが少し弱くなります。
    Postfix と Dovecot のプロセスを SELinux の制限から解除して動作させます。
    (システム全体の SELinux を Disable にするよりマシ)

    SQLite が悪いのではなく、デーモンがファイルにアクセスする方法に問題があります。
    心配性な人は PostgreSQL や MySQL 等、ポート経由の SQL サーバを使用してください。

    本稿記述時点において PostfixAdmin で SQLite を使用する場合、データベースファイルを操作する SELinux のコンテキストタイプが用意されておらず、Apache で作成されたファイルを Postfix / Dovecot から読み込むには制限を解除する必要がある。
    理想は httpd_maild_content_rw_t みたいなコンテキストタイプがあるといいけど、ないものは無い。

  • 項目内容備考
    OSRocky Linux release 9.1 (Blue Onyx)本稿記述時の最新版。Rocky は CentOS の後継。
    SELinuxEnforcingSELinux は有効のままとする。
    実ホスト名mail.example.jpvirtual_mailbox_domains に実ホスト名を指定すると PostfixAdmin が動作しないので注意。
    Web サーバソフトApache 2.4.53Rocky に付属のもの。
    URLhttp://mail.example.jp/postfixadmin/本稿では説明を簡略化するため https にしていない。
    実際に運用する場合は https にすること。
    インタープリタPHP 8.0.20本稿記述時の最新版。
    PostfixAdmin は PHP で動作することが前提。
    データベースソフトSQLite 3.34.1本稿記述時の最新版。
    他に PostgreSQL, MySQL 等を選択できるが、
    実装が他と干渉せず運用コストが軽い SQLite を選択する。
    データベース設置パス/srv/postfixadmin/database/postfixadmin.db/postfixadmin/ はシンボリックリンク。
    初期設定用パスワードpassword123setup.php 操作用のパスワード。これを使ってメール管理者を設定する。
    このパスワード文字列をそのまま使わないこと
    条件は以下。
     · 長さを 5 文字以上にする。
     · 数字を 2 文字以上含める。
    メール送受信ユーザvmailPostfixAdmin では、ひとつのユーザ ID ですべてのメール送受信を行う。
    メール送受信グループmail
    メール送受信ホームディレクトリ
    (メールデータ格納ディレクトリ)
    /var/vmail/メールドメインごとにメールデータが格納される。
    例:
      /var/vmail/example1.com/user/ ~data~
      /var/vmail/example2.com/user/ ~data~


    1. OS の確認と必要モジュールのインストール

    1-1. Rocky Linux のバージョンを確認する。
    $ cat /etc/system-release

    Rocky Linux release 9.1 (Blue Onyx)
    1-2. SELinux の有効を確認する。
    $ getenforce

    Enforcing
    1-3. Apache のバージョンを確認する。
    $ LANG=C dnf info httpd | egrep 'Packages|Version'

    Installed Packages
    Version      : 2.4.53
    
    Installed Packages の表示になること。
    (未インストールなら Available Packages になる)
    1-4. php をインストールする。
    $ su
    # dnf -y install php
    # LANG=C dnf info php | egrep 'Packages|Version'

    Installed Packages
    Version      : 8.0.20
    
    Installed Packages の表示になること。
    (未インストールなら Available Packages になる)
    1-5. SQLite をインストールする。
    # dnf -y install sqlite
    # LANG=C dnf info sqlite | egrep 'Packages|Version'

    Installed Packages
    Version      : 3.34.1
                 : supporting a separate database server.  Version 2 and version 3 binaries
    Available Packages
    Version      : 3.34.1
                 : supporting a separate database server.  Version 2 and version 3 binaries
    
    Installed Packages の表示があること。
    (未インストールなら Available Packages になる)
    1-6. Postfix の SQLite モジュールをインストールする。
    # dnf -y install postfix-sqlite
    # LANG=C dnf info postfix-sqlite | egrep 'Packages|Version'

    Installed Packages
    Version      : 3.5.9
    
    Installed Packages の表示があること。
    (未インストールなら Available Packages になる)


    2. PostfixAdmin のインストール

    2-1. Apache に php の設定を追加する。
    # vim /etc/httpd/conf/httpd.conf
    <IfModule mime_module>
    
    
    AddType application/x-httpd-php .php </IfModule>
    PostfixAdmin は php で作成されたパッケージなので .php を有効にする。
    # systemctl restart httpd
    2-2. PostfixAdmin をダウンロードする。
    GitHub の PostfixAdmin のリポジトリ から PostfixAdmin 3.3.9 をダウンロードする。
    なぜか本家から最新 (3.3.9 以外) をダウンロードすると setup.php が正常に動作しない。

    # mkdir -p /srv/
    # cd /srv/
    /srv/# wget https://github.com/postfixadmin/postfixadmin/archive/refs/tags/postfixadmin-3.3.9.tar.gz
    2-3. PostfixAdmin を設置する。
    /srv/# tar xzf postfixadmin-3.3.9.tar.gz
    /srv/# ls -l | grep postfixadmin
    drwxr-xr-x. 15 root root 4096 5月 13 2021 postfixadmin-postfixadmin-3.3.9
    /srv/# ln -s postfixadmin-postfixadmin-3.3.9 postfixadmin
    2-4. アカウント用データベース (のパーミッション) を作成する。
    (スキーマは setup.php が作成する)

    /srv/# mkdir ./postfixadmin/database/
    /srv/# touch ./postfixadmin/database/postfixadmin.db
    /srv/# chown -R apache:apache ./postfixadmin/database/
    INISTALL.TXT によると www-data:www-data だが、それは ubuntu 用なので RedHat 系では apache:apache にする。
    2-5. テンプレート用キャッシュディレクトリを作成する。
    /srv/# mkdir -p ./postfixadmin/templates_c/
    /srv/# chown apache ./postfixadmin/templates_c/
    2-6. 設定ファイルを (仮に) 新規作成する。
    /srv/# vim ./postfixadmin/config.local.php
    <?php
    // データベースを指定する。
    $CONF['database_type'] = 'sqlite';
    $CONF['database_user'] = 'postfix';
    $CONF['database_password'] = 'postfixadmin';
    $CONF['database_name'] = '/srv/postfixadmin/database/postfixadmin.db';
    
    // ようこそメールの内容を指定する。
    $CONF['welcome_text'] = <<<EOM
    メールアカウントが作成されました。
    EOM;
    
    // 管理画面の Return to change-this-to-your.domain.tld を変更する。
    $CONF['footer_text'] = 'Return to mail.example.jp';
    $CONF['footer_link'] = 'http://mail.example.jp';
    
    $CONF['configured'] = true;
    
    // setup.php 用のパスワードハッシュを指定する。
    $CONF['setup_password'] = '';
    ?>
    
    $CONF['setup_password'] を仮置きで作成する。
    mail.example.jp は自サーバの FQDN に合わせること。
    2-7. 初期設定用パスワードのハッシュ文字列を生成する。
    /srv/# php -r "echo password_hash('password123', PASSWORD_DEFAULT);"
    $2y$10$gA7dBgNJuZ22y2kkYD.TfucCks/jFXaRyAf1MkEiPja6G2z4Xr3fK
    ↑説明用の例文なので、これをそのまま使用しないこと。
    2-8. パスワードハッシュ文字列を設定ファイルに組み込む。
    /srv/# vim ./postfixadmin/config.local.php
    ($CONF['setup_password'] に上記 2-7 で生成したハッシュ文字列をコピーする)
    <?php
    // データベースを指定する。
    $CONF['database_type'] = 'sqlite';
    $CONF['database_user'] = 'postfix';
    $CONF['database_password'] = 'postfixadmin';
    $CONF['database_name'] = '/srv/postfixadmin/database/postfixadmin.db';
    
    // ようこそメールの内容を指定する。
    $CONF['welcome_text'] = <<<EOM
    メールアカウントが作成されました。
    EOM;
    
    // 管理画面の Return to change-this-to-your.domain.tld を変更する。
    $CONF['footer_text'] = 'Return to mail.example.jp';
    $CONF['footer_link'] = 'http://mail.example.jp';
    
    $CONF['configured'] = true;
    
    // setup.php 用のパスワードハッシュを指定する。
    $CONF['setup_password'] = '$2y$10$gA7dBgNJuZ22y2kkYD.TfucCks/jFXaRyAf1MkEiPja6G2z4Xr3fK';
    ?>
    
    2-9. Apache に PostfixAdmin を組み込む。
    /srv/# cat /etc/httpd/conf/httpd.conf | grep ^DocumentRoot
    DocumentRoot "/var/www/html"
    /srv/# ln -s /srv/postfixadmin/public /var/www/html/postfixadmin
    2-10. Apache の書き込み用に SELinux のコンテキストを設定する。
    /srv/# chcon -R -t httpd_php_exec_t ./postfixadmin/
    /srv/# chcon -R -t httpd_sys_content_rw_t ./postfixadmin/database/
    /srv/# chcon -t httpd_sys_content_rw_t ./postfixadmin/templates_c/
    2-11. Apache を起動する。
    /srv/# firewall-cmd --zone=public --list-services
    cockpit dhcpv6-client imap pop3 smtp smtp-submission ssh
    /srv/# firewall-cmd --zone=public --add-service=http --permanent
    /srv/# firewall-cmd --zone=public --add-service=https --permanent
    /srv/# firewall-cmd --reload

    /srv/# firewall-cmd --zone=public --list-services
    cockpit dhcpv6-client http https imap pop3 smtp smtp-submission ssh
    /srv/# systemctl enable httpd
    /srv/# systemctl restart httpd
    2-12. PostfixAdmin を初期化する。
    /srv/# ls -l /srv/postfixadmin/database/postfixadmin.db
    -rw-r--r--. 1 apache apache 0 1月 3 16:30 /srv/postfixadmin/database/postfixadmin.db
    まだデータベースファイルは 0 バイトのまま。
    Web ブラウザで http://mail.example.jp/postfixadmin/setup.php を開く。

    ← → ◯ - □ ×
    
    
    Configure and Setup Postfixadmin This page helps you setup PostfixAdmin. For further help see the documentation. Warning: connection not secure, switch to https if possible · setup_password configured ·TODO You need to authenticate using the setup_password before you can perform some environment and hosting checks. One you have logged in with the setup_password, this page will ... ·run some simple hosting/environment checks which may help identify problems with your environment ·create/update your database of choice, ·allow you to list / add super user accounts Login with setup_password
    Setup password

    ~ 省略 ~
    パスワードを記入して
    をクリックする。
    (パスワードの 表示は ●●●● となる)
     ⇓
    (数秒後)
     ⇓
    ← → ◯ - □ ×
    
    
    Configure and Setup Postfixadmin This page helps you setup PostfixAdmin. For further help see the documentation. Warning: connection not secure, switch to https if possible · setup_password configured · You are logged in with the setup_password, some environment and hosting checks are displayed below. Hosting Environment Check Information · PHP version - 8.0.20 · Postfixadmin installed at - /srv/postfixadmin-postfixadmin-3.3.9/public · config.local.php file found : /srv/postfixadmin-postfixadmin-3.3.9/config.local .php · Database - MySQL (pdo_mysql) extension not found · Database - SQLite support available
    ~ 省略 ~
    2-13. スキーマが作成されていることを確認する。
    /srv/# ls -l /srv/postfixadmin/database/postfixadmin.db
    -rw-r--r--. 1 apache apache 110592 1月 3 16:33 /srv/postfixadmin/database/postfixadmin.db
    データベースが作成されている。(ファイルサイズが 0 バイトでなくなっている)


    3. Postfix の設定

    3-1. メール送受信用ユーザを作成する。
    PostfixAdmin では、個々の Unix ユーザ毎ではなく全体をひとつの固定 ID でメール送受信を行う。
    デーモン用ユーザ ID なので、ログインシェルは使用不能にする。

    # useradd -r -g mail vmail
    # usermod -d /var/vmail/ -s /sbin/nologin -G apache vmail

    # mkdir /var/vmail/
    # chmod 775 /var/vmail/
    # chown vmail:mail /var/vmail/
    # chcon -h system_u:object_r:mail_spool_t:s0 /var/vmail/
    3-2. Postfix とデータベースの連携用設定ファイルを作成する。
    # cat > /etc/postfix/sqlite_virtual_alias_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT goto FROM alias WHERE address = '%s' AND active = '1'
    EOF

    # cat > /etc/postfix/sqlite_virtual_alias_domain_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT goto FROM alias, alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = printf('%u', '@', alias_domain.target_domain) AND alias.active = '1' AND alias_domain.active = '1'
    EOF

    # cat > /etc/postfix/sqlite_virtual_alias_domain_catchall_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = printf('@', alias_domain.target_domain) AND alias.active = '1' AND alias_domain.active = '1'
    EOF

    # cat > /etc/postfix/sqlite_virtual_domains_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT domain FROM domain WHERE domain = '%s' AND active = '1'
    EOF

    # cat > /etc/postfix/sqlite_virtual_mailbox_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT maildir FROM mailbox WHERE username = '%s' AND active = '1'
    EOF

    # cat > /etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf << EOF
    dbpath = /srv/postfixadmin/database/postfixadmin.db
    query = SELECT maildir FROM mailbox, alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = printf('%u', '@', alias_domain.target_domain) AND mailbox.active = '1' AND alias_domain.active = '1'
    EOF
    3-3. メール送受信用ユーザのユーザ ID、グループ ID の数値を調査する。
    Postfix の virtual_uid_maps, virtual_gid_maps に static: を使用する場合は ID を数値で指定する必要がある。

    # id -u vmail ; id -g vmail
    972
    12
    
    ↑説明用の例文なので、これをそのまま使用しないこと。
    3-4. Postfix の設定ファイルを編集する。
    # vim /etc/postfix/main.cf
    以下を追記する。
    # 省略
    
    virtual_uid_maps = static:972 virtual_gid_maps = static:12 virtual_mailbox_base = /var/vmail virtual_mailbox_domains = sqlite:/etc/postfix/sqlite_virtual_domains_maps.cf virtual_alias_maps = sqlite:/etc/postfix/sqlite_virtual_alias_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_catchall_maps.cf virtual_mailbox_maps = sqlite:/etc/postfix/sqlite_virtual_mailbox_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domain_mailbox_maps.cf smtpd_sasl_auth_enable = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth
    smtpd_sasl_type = dovecot, smtpd_sasl_path = private/auth で Submission の認証に Dovecot を指定している。
    POP before SMTP と同様に思えなくもないが、Dovecot の認証に相乗りしてるだけなので POP before SMTP とは異なる。
    # postfix check
    何も表示されないこと
    3-5. Postfix を再起動する。
    # firewall-cmd --zone=public --add-service=smtp --permanent
    # firewall-cmd --zone=public --add-service=smtp-submission --permanent
    # firewall-cmd --reload

    # systemctl enable postfix
    # systemctl restart postfix


    4. Dovecot の設定

    4-1. メール保存方法の設定ファイルを作成する。
    Dovecot の first_valid_uid, last_valid_uid は ID を数値で指定する必要がある。

    # vim /etc/dovecot/conf.d/10-mail.conf

    mail_location = maildir:/var/vmail/%d/%n
    mail_uid = vmail mail_gid = mail
    mail_privileged_group = mail
    first_valid_uid = 972 last_valid_uid = 972
    (972上記 3-3 で調査したメール送受信用ユーザのユーザ ID)
    4-2. Dovecot とデータベースの連携用設定ファイルを作成する。
    Postfix の Submission の認証にも使用される。

    # vim /etc/dovecot/conf.d/10-master.conf
    service auth {
    
      unix_listener auth-userdb {
        #mode = 0666
        #user =
        #group =
      }
    
    
    # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix }
    # Auth process is run as this user. #user = $default_internal_user }
    # ls -l /var/spool/postfix/private/auth
    ls: '/var/spool/postfix/private/auth' にアクセスできません: そのようなファイルやディレクトリはありません
    
    まだ認証連携ファイルは存在しない。Dovecot を起動すると自動的に作成される。
    # vim /etc/dovecot/conf.d/10-auth.conf

    #!include auth-system.conf.ext !include auth-sql.conf.ext #!include auth-ldap.conf.ext
    # cat /etc/dovecot/conf.d/auth-sql.conf.ext | grep -B 3 -A 1 dovecot-sql.conf.ext
    passdb {
      driver = sql
    
      # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
      args = /etc/dovecot/dovecot-sql.conf.ext
    }
    --
    
    userdb {
      driver = sql
      args = /etc/dovecot/dovecot-sql.conf.ext
    }
    
    # vim /etc/dovecot/dovecot-sql.conf.ext
    (新規作成)
    driver = sqlite
    connect = /srv/postfixadmin/database/postfixadmin.db
    
    password_query = \
        SELECT \
            username as user, \
            password, \
            '/var/vmail/%d/%n' as userdb_home, \
            'maldir:/var/vmail/%d/%n' as userdb_mail \
        FROM \
            mailbox \
        WHERE username = '%u' AND active = '1'
    
    user_query = \
        SELECT \
            '/var/vmail/%d/%n' as home, \
            'maildir:/var/vmail/%d/%n' as mail \
        FROM \
            mailbox \
        WHERE username = '%u' AND active = '1'
    
    # doveconf -n 1>& /dev/null ; echo $?
    0
       0 (文法エラーなし) になること。
    4-3. Dovecot を再起動する。
    # firewall-cmd --zone=public --add-service=pop3 --permanent
    # firewall-cmd --zone=public --add-service=pop3s --permanent
    # firewall-cmd --zone=public --add-service=imap --permanent
    # firewall-cmd --zone=public --add-service=imaps --permanent
    # firewall-cmd --reload

    # systemctl enable dovecot
    # systemctl restart dovecot

    # ls -l /var/spool/postfix/private/auth
    srw-rw-rw- 1 postfix postfix 0  1月  3 20:30 /var/spool/postfix/private/auth
    
    認証連携ファイルが自動的に作成された。


    5. Postfix の実行制限を解除

    SQLite のデータベースファイルにアクセスできるよう、Postfix と Dovecot の SELinux 制限を一部解除する。

    上記 4 までの操作では Postfix と Dovecot が SELinux の制限により SQLite のデータベースにアクセスできないせいで、
    まだメールは送受信できずエラーメッセージが audit.log に出力される。
    そのエラーメッセージを利用して解除対象の実行コンテキストタイプを調査する。

    解除対象の実行コンテキストタイプを調査済みの場合は、下記 5-2, 5-3 を省略しても構わない。

    5-1. SELinux の有効を確認する。
    # getenforce
    Enforcing
    5-2. PostfixAdmin でメールアカウントを作成し、そのアカウントでメールを送受信する。
    5-3. 解除するコンテキストを調査する。
    # cat /var/log/audit/audit.log | grep denied \
    | awk 'match($0, /scontext=[^:]+:[^:]+:([^:]+)/, s) {print s[1]}' \
    | sort | uniq
    dovecot_auth_t
    postfix_cleanup_t
    postfix_master_t
    postfix_smtpd_t
    postfix_virtual_t
    
    5-4. 実行コンテキストの制限を解除する。
    # semanage permissive -a dovecot_auth_t
    # semanage permissive -a postfix_cleanup_t
    # semanage permissive -a postfix_master_t
    # semanage permissive -a postfix_smtpd_t
    # semanage permissive -a postfix_virtual_t
    5-5. 制限を解除した実行コンテキストを確認する。
    # LANG=C semanage permissive -l
    Builtin Permissive Types
    
    Customized Permissive Types
    
    dovecot_auth_t
    postfix_cleanup_t
    postfix_master_t
    postfix_smtpd_t
    postfix_virtual_t
    
    # exit
    $