SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

Stalwartメールサーバーの導入ガイド:Postfix/Dovecotとの比較

Rust製バイナリStalwartでメールサーバーを構築する方法を解説します。PostfixやDovecotとの機能差、導入時の注意点、そしてmailcowと比較してどちらを選ぶべきかを判断基準とともに紹介します。

Stalwart が 1 つのバイナリに集約する機能

Stalwart は、1 台の VPS 上で単一の Rust バイナリとして実行するメールサーバーです。同じプロセスで SMTP、IMAP、POP3、JMAP、CalDAV、CardDAV、WebDAV に応答します。また、独自のスパムフィルター、メッセージストア、ACME クライアントも備えています。一般的な構成では、Postfix、Dovecot、Rspamd、アカウント用データベース、別の証明書ツールを使用して同じ処理を実現します。Stalwart はこれらを、/etc/stalwart/config.json にある 1 つのサービス unit と 1 つの設定ファイルに置き換えます。

以下の数値、設定名、コマンドはすべて、Stalwart の公式ドキュメント、リリースページ、インストールスクリプトから引用しています。最初に 2026 年 8 月 28 日、リリース v0.16.19(2026 年 8 月 24 日公開)を対象に確認し、2026 年 10 月 12 日に再確認しました。この時点での最新リリースは v0.16.26(2026 年 10 月 11 日公開)でした。以下のコマンドは、自分のサーバーで実行するものです。各コマンドの後に、正常に動作したかを確認する方法を示します。

Stalwart は GNU Affero General Public License v3.0 (AGPL-3.0) と Stalwart Enterprise License v2 のデュアルライセンスです。一部の機能は enterprise 専用です。公式に記載された HTTP エンドポイント一覧では、/scim/v2/* と示されています。自分で動作確認していない機能を前提に導入を計画する前に、ライセンス条件を確認してください。

バイナリを 1 つにまとめることで、構成要素は実際に減ります。ただし、メールが到達するかどうかを左右する 2 つの要素まで減るわけではありません。

25 番ポートと DNS のレピュテーションは、実行するソフトウェアを区別しません

送信 TCP 25 番ポートが最初の関門です。多くの VPS プロバイダーは、新規アカウントでこのポートをデフォルトでブロックします。25 番ポートがブロックされていると、サーバーは他のメールサーバーへメールを直接配信できません。何もインストールする前に確認してください。

sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 alt1.aspmx.l.google.com 25

正常な結果では、約 1 秒で Connection to alt1.aspmx.l.google.com ... 25 port [tcp/smtp] succeeded! が出力されます。ブロックされている場合は、2 通りの結果になります。上流でパケットが破棄されると、リセットが返されないため、nc は 5 秒間待機した後に nc: connect to alt1.aspmx.l.google.com port 25 (tcp) failed: Connection timed out を出力します。ファイアウォールが拒否すると、ICMP エラーが返されます(netfilter の reject は、別の内容を指定しない限り port unreachable を送信します。たとえば administratively prohibited を指定できます)。この場合、通常は Connection refused または No route to host として、すぐに失敗します。どちらの場合も、プロバイダーにチケットを起票してください。

プロバイダーが開放しない場合、回避方法はリレーを使用することです。Stalwart は Relay route を介して、送信メールをすべて smarthost に渡せます。ポートのデフォルトは 25 ですが、1 から 65535 までの任意の値を指定できます。implicitTls スイッチと authUsername および authSecret フィールドを使用すれば、465 または 587 番ポートの認証済みリレーにも接続できます。メールは自分のレピュテーションではなく、リレーのレピュテーションで送信されます。

2 つ目の関門は、受信側のネットワークが IP アドレスとドメインをどのように評価するかです。対象となるのは、IP アドレスの reverse DNS、SPF、DKIM、DMARC、および割り当てられたアドレスブロックの送信履歴です。2026 年 8 月 28 日に確認した Stalwart の DNS 設定ページでは、これらの作業を行う場所が明確に説明されていました。reverse DNS レコードは「通常、Stalwart 自身ではなくホスティングプロバイダーが設定する」とされています。このカテゴリの他の設定も同じです。設定場所はメールサーバーではなく、DNS zone とプロバイダーの control panel です。

そのため、このページではこれらのレコードを改めて説明しません。詳しい説明は メールを送信するすべてのサービスで一度だけ設定する SPF、DKIM、DMARC にあります。そもそも自分でメールを運用するかどうかをまだ決めていない場合は、自己ホスト型メールに今も価値があるかを率直に検討した記事 から始めてください。Stalwart を選んでも、この計算結果は変わりません。

Stalwart メールサーバーの実行に必要な小規模 VPS

2026 年 10 月 12 日に確認した Stalwart のシステム要件ページには、次の数値が記載されています。アイドル時のメモリ使用量は約 100 MB です。5〜10 ユーザーの小規模な構成であれば、RAM 1 GB で十分です。低トラフィックで約 5 ユーザーの構成は、CPU 1 コアで動作します。また、このページには「同時実行数とアクティビティが増えると、低レイテンシーと高スループットを維持するために、より多くの CPU コアが必要になります」と記載されています。デフォルトの上限は、全サービス合計で同時接続 8,192 件です。この値は変更できます。

このページにはディスク容量の最小値が記載されていません。そのため、保持する予定のメールに加えて、ストアのコンパクション用の余裕を確保してディスク容量を決めてください。

3 つの送信先への通信が機能しないと、メールとは無関係な原因でサーバーが壊れているように見えます。Web インターフェースのバンドルを https://github.com/stalwartlabs/webui/releases/latest/ から取得します。証明書の取得では https://acme-v02.api.letsencrypt.org/directory に接続します。MX レコードと認証レコードを検索するため、DNS の UDP 53 番ポートと TCP 53 番ポートが必要です。最初の通信をブロックする、厳格な送信ファイアウォールを設定すると、起動しているのに管理インターフェースがないメールサーバーになります。

固定したリリースをインストールする。「latest」ではない

公式のインストーラーは shell スクリプトです。実行する前に内容を確認してください。

curl --proto '=https' --tlsv1.2 -sSf https://get.stalw.art/install.sh -o install.sh
less install.sh
sudo sh install.sh

2026 年 10 月 12 日にこのスクリプトを読むと、実行内容を正確に確認できます。stalwart サービスアカウントと必要なディレクトリを作成します。続いて https://github.com/stalwartlabs/stalwart/releases/latest/download からダウンロードします。バイナリは /usr/local/bin/stalwart に mode 0755 で配置されます。設定は /etc/stalwart/config.json、データは /var/lib/stalwart、ログは /var/log/stalwart に配置され、3 つのディレクトリはいずれも mode 0750 で、所有者は stalwart です。環境ファイルは /etc/stalwart/stalwart.env に mode 0640 で作成され、所有者は root:stalwart です。スクリプトが受け取るのは、任意のインストール先プレフィックス 1 つと、FoundationDB ビルド用の --fdb フラグです。バージョン引数は受け取りません。

この点が重要です。スクリプトは常に最新のリリースを取得するため、1 週間ずれて構築した 2 台のサーバーで同じコードが動作するとは限りません。バイナリは直後に自分で固定してください。これは v0.16.26 のリリースノートにも示されているアップグレード方法です。「v0.16.x からアップグレードする場合は、バイナリを置き換える(または docker pull を実行する)。」2026 年 8 月 24 日から 10 月 11 日までの間に 7 件のパッチリリースが公開され、そのうち複数にはセキュリティ修正が含まれています。最新のリリースを固定し、意図的に固定先を更新してください。

STALWART_TAG=v0.16.26
curl -fsSLO "https://github.com/stalwartlabs/stalwart/releases/download/${STALWART_TAG}/stalwart-x86_64-unknown-linux-gnu.tar.gz"
tar zxf stalwart-x86_64-unknown-linux-gnu.tar.gz
sudo systemctl stop stalwart
sudo install -m 0755 -o root -g root stalwart /usr/local/bin/stalwart
sudo systemctl start stalwart
systemctl is-active stalwart

systemctl is-active stalwart は active を出力するはずです。それ以外の場合は journalctl -u stalwart -n 50 を確認してください。各リリースのアセットには対応する .sigstore.json バンドルが含まれているため、インストール前にダウンロードの署名を検証できます。

スクリプトが作成する unit は User=stalwart として実行され、AmbientCapabilities=CAP_NET_BIND_SERVICE を設定します。この capability により、非特権アカウントでも 25、443、465、993 番ポートを待ち受けられます。後で独自の unit を作成し、この行を省略すると、通常のユーザーは 1024 未満のポートを待ち受けられないため、サービスは起動時に失敗します。

初回の管理者パスワードが表示される場所

Stalwart はブートストラップモードで起動し、16 文字の一時パスワードをサービスログに 1 回だけ書き込みます。

sudo journalctl -u stalwart -n 200 | grep -A8 'bootstrap mode'

セットアップウィザードはポート 8080 の平文 HTTP で待ち受けるため、このポートを公開しないでください。代わりに、SSH 経由でノート PC からトンネル接続します。

ssh -N -L 8080:127.0.0.1:8080 you@your-vps

次に http://127.0.0.1:8080/admin を開き、admin としてログインします。パスワードにはログに表示されたものを使用してください。ウィザードでは、サーバーのホスト名、デフォルトのメールドメイン、TLS、ストレージ、アカウントディレクトリ、ログ、DNS の処理方法を設定します。完了したらサービスを再起動し、それ以降は https://<your-host>/admin を使用してください。

パスワードがログの表示範囲から流れてしまった場合は、固定パスワードを設定します。/etc/stalwart/stalwart.env には、この用途のコメントアウトされた設定項目が用意されています。STALWART_RECOVERY_ADMIN=admin:changeme、STALWART_RECOVERY_MODE=true、STALWART_RECOVERY_MODE_PORT(デフォルトは 8080)などが含まれます。コメントを外して再起動し、ログインしたら、再びコメントアウトしてください。Stalwart のハードニングページでは、この認証情報を緊急時専用に保管し、管理者アカウントで IMAP、JMAP、WebDAV にログインしないように説明しています。

同じページには、維持すべきリスナーも記載されています。ポート 25 は受信 SMTP、465 は implicit TLS を使用する submission、993 は IMAPS、443 はすべての HTTP 用です。587、143、4190、110、995、8080 は必須ではないとされており、セットアップ完了後は 8080 を無効にするよう説明されています。

Docker で固定タグを指定して実行する

ドキュメントに記載されているイメージは stalwartlabs/stalwart です。v0.16.26 タグは 2026 年 10 月 12 日時点で Docker Hub にあり、-alpine バリアントも同時に提供されていました。Stalwart の Docker ページでは、本番環境に v0.16 マイナータグを使用することを推奨しています。ただし、上記のバイナリと同じ理由から、パッチバージョンを固定します。

services:
  stalwart:
    image: stalwartlabs/stalwart:v0.16.26
    container_name: stalwart
    restart: unless-stopped
    ports:
      - "25:25"
      - "465:465"
      - "993:993"
      - "443:443"
      - "127.0.0.1:8080:8080"
    volumes:
      - stalwart-etc:/etc/stalwart
      - stalwart-data:/var/lib/stalwart
volumes:
  stalwart-etc:
  stalwart-data:

このファイルは、ドキュメントに記載された docker run コマンドを Compose 形式で記述したものです。不要なリスナーは省略し、セットアップ用ポートは localhost にバインドしています。起動して、同じブートストラップ行を確認します。

docker compose up -d
docker compose logs stalwart 2>&1 | grep -A8 'bootstrap mode'

Docker ページには、起動時に固定の認証情報を設定する方法として -e STALWART_RECOVERY_ADMIN=admin:mySecretPass も記載されています。ログの確認よりこちらを使う場合は、Compose の environment: キーを使用します。

ドキュメントに記載されたポート一覧と、このファイルが短い理由

Stalwart の Docker ページには、443、8080、25、587、465、143、993、110、995、4190 が記載されています。ハードニングのページでは、587、143、110、995、4190 を不要とし、セットアップ後は 8080 を無効化するよう説明しています。実際にクライアントが要求するものだけを追加してください。スマートフォンが STARTTLS による送信を要求する場合は、587 を公開します。デスクトップクライアントからユーザーが Sieve ルールを作成する場合は、4190 を公開します。

Compose に慣れていない場合は、VPS 向けの Docker Compose 入門で、この構成で使用するファイル配置と名前付きボリュームの仕組みを説明しています。特にメールサーバーでは注意が必要です。Docker は独自のファイアウォールルールを作成してポートを公開し、そのルールは ufw より先に評価されます。そのため、ufw deny 8080 では Compose が公開したポートを閉じられません。ポートマッピングで 127.0.0.1 にバインドすることで、実際にポートを閉じられます。上のファイルがそのように設定されているのはこのためであり、SSH トンネルも引き続き適用されます。

証明書なしのTLSと、その代償

Stalwart は ACME(自動証明書管理環境)を直接実装しているため、certbot も更新フックも必要ありません。ドキュメントには、4 つの検証方法が記載されています。HTTP-01 は、port 80 でチャレンジ要求に応答します。TLS-ALPN-01 は、ACME 専用の ALPN プロトコルを使用し、port 443 でこの用途向けの証明書を提示します。DNS-01 は一時的な TXT レコードを公開する方法で、ワイルドカード証明書を発行できる 2 つの方法の 1 つです。DNS-PERSIST-01 は、更新のたびに新しいレコードを書き込む代わりに、長期間有効な認証用 TXT レコードを使用します。

代償は、Stalwart が TLS ハンドシェイクを直接処理する必要があることです。TLS-ALPN-01 は、Stalwart 自身がハンドシェイクを完了することで動作するため、TLS を終端するリバースプロキシの背後では成功しません。そのホストで nginx または Caddy がすでに 443 を使用している場合、対処方法は 3 つあります。Stalwart 自身の nginx ガイドでは、listen 443; proxy_pass 127.0.0.1:10443; proxy_protocol on; を使用して nginx を TCP パススルーとして動作させ、TLS 接続を変更せずに Stalwart へ到達させます。この構成では 443 へのすべての接続を Stalwart に渡すため、その port で nginx が他のサービスを提供していないホストに適しています。それ以外の場合は、Stalwart を DNS-01 または HTTP-01 に切り替えるか、専用の IP アドレスを割り当てます。

DANE と MTA-STS、知っておくべきデフォルト

どちらも Web インターフェースの Settings、MTA、Outbound、TLS Strategies にある MtaTlsStrategy オブジェクトで、TLS 戦略ごとに設定します。dane フィールドのデフォルトは optional です。受信側が TLSA レコードを公開している場合は DANE 検証を試み、公開していない場合は通常の STARTTLS にフォールバックします。require に設定すると、検証可能な TLSA レコードがある場合にだけ配送が進みます。mtaSts フィールドも同様に動作し、デフォルトは optional です。関連するタイムアウトは tlsTimeout(デフォルトは 3 minutes)と mtaStsTimeout(デフォルトは 5 minutes)です。

受信側では、Stalwart は https://mta-sts.<domain>/.well-known/mta-sts.txt に独自の MTA-STS ポリシーを公開できます。この設定には port 443 を開放する必要があります。MtaSts singleton には mode(デフォルトは testing)、maxAge(デフォルトは 7 days)、mxHosts があります。mxHosts が空の場合は、TLS 証明書に含まれるホスト名にフォールバックします。DNS レコードを 2 つ用意します。1 つはメールホストを指す mta-sts CNAME レコード、もう 1 つはポリシー識別子を格納する _mta-sts TXT レコードです。

dig +short TXT _mta-sts.example.org
curl -s https://mta-sts.example.org/.well-known/mta-sts.txt

TXT の検索結果は v=STSv1; id=... 文字列になり、curl はポリシー本文を返す必要があります。curl が何も返さない場合、port 443 が閉じているか、mta-sts.example.org の証明書が発行されていません。

両方の確認が成功するまで、mode は testing のままにします。証明書が壊れた状態で enforce モードにすると、他のサーバーから自分のサーバーへの配送が停止します。その事実をログではなく、ユーザーから知らされることになります。DANE にも同様の注意点があります。DNSSEC で署名されたゾーンと、リーフ証明書を固定する TLSA レコードが必要です。ACME が更新されるたびに、その TLSA レコードを再公開しなければなりません。発行元 CA を固定するか、更新作業を受け入れてください。

保存時の暗号化はエンドツーエンド暗号化ではない

この機能は最も誤解されやすいため、ドキュメントの記載内容を正確に説明します。各ユーザーの平文メッセージは、ディスクに書き込まれる前に、そのユーザーの OpenPGP または S/MIME 証明書を使用して自動的に暗号化されます。encryptAtRest はデフォルトで有効で、受信者が暗号化キーを登録していれば、SMTP または LMTP 経由で到着したメッセージに適用されます。encryptOnAppend のデフォルト値は false です。「これにより、追加されたメッセージは変更されず、クライアントが保存する内容を完全に制御できます」と説明されています。OpenPGP では、古い PGP/Inline ではなく PGP/MIME を使用し、AES-256 または AES-128 で暗号化します。Stalwart はキーを生成しません。ユーザーが ASCII-armored 形式の公開キーをエクスポートし、Account の Public Keys に PublicKey オブジェクトとして登録します。

このため、盗まれたディスクイメージ、盗まれたバックアップ、配信後にストアを閲覧するオペレーターからは保護できます。秘密キーがなければ保存されたバイト列は読めず、管理者も復号できません。

ただし、転送中のメッセージは保護されません。メッセージは、2 台のサーバーが合意した TLS の設定に従ってインターネットを通過し、平文で到着します。Stalwart はその時点でメッセージを暗号化します。送信者、送信者のプロバイダー、TLS を解除した中継経路は、すでに平文を確認しています。

さらに、3 つの制限を明確にしておく必要があります。Sent と Drafts フォルダーはクライアントによって書き込まれます。これは append であり、encryptOnAppend はデフォルトで false なので、設定を変更しない限り内容は平文のままです。2026 年 10 月 12 日に再確認したドキュメントには、メッセージ本文についてのみ記載があり、エンベロープデータ、ヘッダー、インデックスエントリが暗号化されるとは書かれていません。暗号化されると仮定しないでください。また、キーをアップロードする前から保存されているメッセージが再暗号化されるとも書かれていないため、再暗号化されないものとして扱い、確認してください。暗号化された本文に対しても全文検索が機能するかどうかは記載されていません。誰かに提供できると約束する前に、使い捨てのアカウントでテストしてください。

ユーザーが秘密キーを失うと、そのユーザーのメールは失われます。設計上、復旧手段はありません。

WKD はメールサーバーの機能ではなく、Web サーバーの機能です

WKD(Web Key Directory)は OpenPGP の仕組みを補完するもので、別の問題を解決します。ドメイン配下の固定された HTTPS URL で公開鍵を公開するため、送信者のメールクライアントは、メッセージが送信者の端末から出る前に公開鍵を取得して暗号化できます。これがエンドツーエンド暗号化です。Stalwart の保存時暗号化は、ディスク上に保存されたコピーを対象とします。一方を設定しても、もう一方は有効になりません。

Stalwart は WKD を提供しません。2026 年 10 月 12 日時点のドキュメントに記載された HTTP エンドポイントには、jmap、caldav、carddav、oauth-authorization-server、openid-configuration、acme-challenge、mta-sts.txt、mail-v1.xml、および autoconfig の well-known パスがあります。openpgpkey パスはありません。通常の静的 Web サーバーから提供してください。

仕様では 2 つのレイアウトを定義しています。advanced method は https://openpgpkey.example.org/.well-known/openpgpkey/example.org/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe を使用します。direct method は https://example.org/.well-known/openpgpkey/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe を使用します。この 32 文字の文字列は、小文字化した local part の SHA-1 を z-base-32 でエンコードしたものです。そのため、これらのファイル名を手作業で作成してはいけません。GnuPG が作成します。

gpg --export --armor you@example.org > you.asc
gpg-wks-client --print-wkd-url you@example.org
gpg-wks-client --install-key you.asc you@example.org

--print-wkd-url は、sub-domain 形式を使用してクライアントが取得する URL を出力します。--install-key は、WKD のレイアウトを反映したローカルディレクトリツリーに鍵を書き込みます。デフォルトでは最上位ディレクトリとして openpgpkey という名前を使用し、-C dir で変更できます。そのツリーを Web root にコピーし、hu ディレクトリと同じ場所に必要な policy ファイルを追加します(空のファイルでも有効です)。最後に curl で自分の URL を取得し、404 ではなく鍵のバイト列が返ることを確認します。

1 台の VPS 上のストレージ

Stalwart はストレージを 4 つの役割に分けます。メールボックスの状態などの構造化レコードを保存するデータストア、メッセージ本文や添付ファイルの生データを保存する blob ストア、全文検索用のインデックスを保存する検索ストア、レートリミッター、認証トークン、セッションデータを保存するメモリ内ストアです。それぞれ異なるバックエンドを指定できます。対応するバックエンドには、RocksDB、FoundationDB、PostgreSQL、MySQL、SQLite、S3 互換オブジェクトストレージ、Azure Blob Storage、Redis、ElasticSearch、Meilisearch があります。

1 台の VPS であれば、答えは明確です。ドキュメントでは、RocksDB を「速度と信頼性のため、Stalwart の単一ノード構成で推奨されるバックエンド」としています。Redis はメモリ内ストアとしてのみ対応しており、データストアや blob ストアにはできません。そのため、開始時に Redis 用の別コンテナを用意する必要はありません。メールボックスがディスク容量を超えるようになったら、後から blob ストアを S3 に移行します。

バックアップ方法はバックエンドに従います。外部データベースの場合は、そのデータベース固有の手順を使用します。組み込みストアの場合、FAQ では /var/lib/stalwart ディレクトリをコピーするよう説明されています。コピーはサービスを停止してから実行するか、ファイルシステムまたはボリュームのスナップショットから行います。実行中の key-value ストアをファイル単位でコピーすると、書き込み途中の状態を取得する可能性があります。その問題は、復元を試すまで判明しません。

Rspamd に代わるスパムフィルター

フィルタリングは同じプロセス内で実行されるため、維持すべき別のデーモンはありません。分類器は、Settings、Spam Filter、Classifier にある SpamClassifier シングルトンで設定します。分類器には、feature hashing を用いた FTRL-Proximal アルゴリズムを使用します。ほとんどのデプロイでは FtrlFh が推奨されるデフォルトです。FtrlCcfh は cuckoo feature hashing に切り替えてハッシュ衝突を減らすもので、大規模なデプロイを対象としています。分類器は継続的に学習します。ユーザーがメッセージを spam または ham として指定すると、そのラベルが今後の判定に直接反映されます。

分類器の周囲には、DNS blocklist、greylisting、フィッシング検出、spam trap、Pyzor が配置されています。手放せないルールがある場合は、milter 経由で SpamAssassin を呼び出すこともできます。

mailcow が依然として適切な選択肢である場合

Stalwart には webmail がありません。これは最大の不足点であり、現時点で解消の見込みはありません。2026 年 10 月 12 日に確認した mailcow のドキュメントには、SOGo を含む 16 個のコンポーネントが記載されています。SOGo により、ユーザーはブラウザーからメールボックスを利用でき、CalDAV と CardDAV のインターフェースもすぐに使えます。2025 年 6 月 20 日付の Stalwart のロードマップ記事では、組み込み webmail について「計画には含まれていますが、現在の最優先事項ではありません」と説明されています。v1.0 の後に Dioxus を使って Rust で実装する予定で、「おそらく 2026 年のどこかの時点」とされています。2026 年 10 月 12 日時点で、プロジェクトブログには webmail の提供を告知する記事がありません。そのため Stalwart を使う場合は、自分で Roundcube を導入するか、すべてのユーザーにメールクライアントの設定を求める必要があります。

Stalwart には web admin interface があるため、そこが想定される不足点ではありません。2 つ目の不足点は、バージョンの成熟度です。FAQ には、Stalwart は 0.x の段階にあり、v1.0 より前にデータレイアウトや設定が変更される可能性があるため、移行が必要になる場合があると記載されています。プロジェクト自身が公開した 2026 年 6 月の記事のタイトルは「オープンなバグ報告ゼロ: Stalwart 1.0 への道」です。現在の位置付けは、完成に近いものの、まだ到達していない段階だと分かります。2026 年 10 月 12 日時点でも、最新リリースは v0.16.26 です。

3 つ目の不足点は、機能一覧には誰も載せないものです。Postfix、Dovecot、Rspamd には、10 年分の文書化された回答の蓄積があります。午前 2 時にメールがキューに残り、ユーザーが待っている状況では、エラー文字列に一致する検索結果のほうが、洗練されたアーキテクチャーより価値があります。そのような状況であれば、mailcow のインストールガイドでスタック全体を最初から最後まで説明しています。夜間の対応時間も短くて済みます。

単一のバイナリ、単一の設定ファイル、JMAP を求め、初期段階のソフトウェアを使うことに抵抗がないなら Stalwart を選んでください。今すぐ webmail が必要で、既存の回答が豊富にある環境を求めるなら mailcow を選んでください。

既存メールの移行

一般的な方法は、imapsync を使って IMAP から IMAP へ移行することです。移行元と移行先で何が動作しているかは問いません。最初に dry run を実行してください。

imapsync --dry \
  --host1 old.example.org --user1 you@example.org --passfile1 /root/.old.pw \
  --host2 mail.example.org --user2 you@example.org --passfile2 /root/.new.pw

--dryを指定すると、imapsync は「実際には何も実行せず、実行される内容だけを表示」します。そのため、このフラグを外す前に出力を確認してください。各パスワードファイルの先頭行にはパスワードが記録されているため、chmod 600両方を削除してください。

Stalwart には、ほかの多くのサードパーティー製ガイドがまだ反映できていない新しいツールもあります。公式ブログでは、JMAP のインポーター兼エクスポーターである Vandelay(29 May 2026)と、ダウンタイムなしのアップグレードに使う移行プロキシ(10 June 2026)が紹介されています。大規模な移行を計画する前に、両方を確認してください。ほかで見つかる情報のほとんどより新しい内容だからです。

障害モードと表示される文字列

管理インターフェースがまったく読み込まれない。 FAQ でも直接説明されています。初回起動時に Web インターフェースの bundle を GitHub からダウンロードするため、github.com への外向き HTTPS 接続がないサーバーではサービス自体は起動していても、Web インターフェースのすべてのルートが 404 を返します。サーバー上で curl -sI https://github.com/stalwartlabs/webui/releases/latest/ を実行して確認します。ほかに挙げられている一般的な原因は、HTTP と HTTPS の scheme の不一致、および reverse proxy がクライアント IP を転送していないことです。

ログに bootstrap password がない。 bootstrap mode の起動時に 1 回だけ出力されます。サービスがその後に再起動されている場合は、sudo journalctl -u stalwart --since today | grep -A8 'bootstrap mode' で確認範囲を広げます。本当に失われている場合は、/etc/stalwart/stalwart.env に STALWART_RECOVERY_ADMIN を設定して再起動します。

ローカルプロキシ経由の relay が拒否される。 v0.16.19 の release notes には、host resolves loopback address によって relay route が拒否される問題の修正が記載されています。この文字列がそのまま表示される場合は、古い build を実行しています。回避策を使わず、更新先を固定してください。

独自の unit を作成した後、サービスが起動しない。 AmbientCapabilities=CAP_NET_BIND_SERVICE がない場合、stalwart user は port 25、443、465、993 に bind できず、最初の listener で起動に失敗します。installer が生成した unit から capability の行をコピーしてください。

証明書が発行されない。 HTTP-01 では port 80 に到達でき、かつ空いている必要があります。TLS-ALPN-01 では、443 で Stalwart 自身が TLS handshake に応答する必要があります。サーバー上の別のプロセスがいずれかの port を使用していると、ほかの機能が正常に見えても ACME は静かに失敗し続けます。

FAQ

Stalwart は 1 台の VPS 上で Postfix、Dovecot、Rspamd を置き換えられますか?

はい。1 つの Rust バイナリで SMTP、IMAP、POP3、JMAP、CalDAV、CardDAV、WebDAV に対応し、スパムフィルター、メッセージストア、ACME クライアントも組み込まれています。4 つのデーモンとその連携設定の代わりに、systemd の unit 1 つと /etc/stalwart/config.json の設定ファイル 1 つで構成できます。ただし、DNS ゾーンやプロバイダーの port 25 ポリシーは置き換えません。実際のセルフホストメール運用の成否は、そこに左右されます。

Stalwart のメールサーバーには、どの程度の RAM が必要ですか?

2026 年 10 月 12 日に確認した Stalwart のシステム要件ページでは、アイドル時の使用量はおよそ 100 MB で、5 から 10 ユーザーの小規模構成には RAM 1 GB が適するとされています。トラフィックの少ない約 5 ユーザーの構成であれば、CPU 1 コアで動作します。デフォルトの上限は、すべてのサービスを合計した同時接続数 8,192 です。この値は変更できるため、上限はユーザー数だけでなく、接続数とメール量に応じて上昇します。必要な最小ディスク容量は公開されていないため、保存するメール量に合わせてディスク容量を決めてください。

Stalwart に切り替えると、メールの到達性は向上しますか?

いいえ。到達性は、VPS で送信 TCP port 25 が開いているか、IP に逆引き DNS が設定されているか、ドメインに SPF、DKIM、DMARC が設定されているかで決まります。Stalwart は DANE、MTA-STS、SMTP TLS reporting に対応しており、MTA-STS ポリシーを公開することもできます。ただし、これらは転送時のセキュリティを制御するものであり、受信側ネットワークが送信元アドレスを信頼するかどうかを決めるものではありません。インストール前に nc -vz -w 5 alt1.aspmx.l.google.com 25 で port 25 をテストしてください。

Stalwart には webmail が含まれていますか?

2026 年 10 月 12 日時点では含まれていません。Web 管理インターフェースは提供されますが、webmail とは別のものです。プロジェクトの 2025 年 6 月 20 日のロードマップ記事では、version 1.0 の後に、Dioxus を使った Rust 製の webmail クライアントを開発する予定で、「おそらく 2026 年のどこかの時点」と説明されています。ただし、プロジェクトのブログにはまだその発表がありません。現在ブラウザーで利用できる受信トレイが必要な場合は、Roundcube を併設するか、SOGo を含む構成を使用してください。

Stalwart の保存時暗号化は、何から保護しますか?

各ユーザーの OpenPGP または S/MIME 公開鍵でメッセージを暗号化してからディスクに書き込むため、盗難されたディスクやバックアップ、またはストアを読む管理者から内容を保護できます。エンドツーエンド暗号化ではありません。メッセージは平文で到着し、配信時に暗号化されるため、それまでの各ホップでは内容を確認できます。encryptOnAppend のデフォルト値は false です。そのため、変更しない限り、クライアントが書き込む Sent と Drafts は平文のままです。ドキュメントが説明しているのはメッセージ内容だけで、メタデータ、インデックスエントリ、鍵をアップロードする前に保存されたメールの再暗号化については何も記載されていません。推測で判断せず、これらを自分で確認してください。

#stalwart#email#self-hosting#mail-server#smtp