antony@notes:~/container$ cat "Docker-Mail-Server-完整部署指南.md"
Docker Mail Server 完整部署指南
Docker Mail Server 完整部署指南
前置條件
開始部署前,請確認以下環境條件皆已滿足。
基礎架構
| 項目 | 需求 | 說明 |
|---|---|---|
| DNS Server | 必須 | 內網需有可控的 DNS Server(如 BIND),用於新增 MX / SPF / DKIM / DMARC 等 TXT Record。本文以 nsupdate 動態更新為例 |
| DNS MX Record | 必須 | 域名的 MX 記錄需指向 Mail Server(例如 kubeantony.com. MX 10 mx1.kubeantony.com.) |
| DNS A Record | 必須 | Mail Server 主機名需有對應的 A 記錄(例如 mx1.kubeantony.com. A 192.168.11.3) |
| 固定 IP | 建議 | Mail Server 應使用固定 IP,避免 DNS 記錄失效 |
Mail Server 主機
| 項目 | 需求 | 說明 |
|---|---|---|
| 作業系統 | Linux(Debian/Ubuntu/RHEL/Rocky 等) | 需支援 Podman 4.4+ |
| Podman | 4.4 以上 | 需支援 Quadlet(.kube 單元檔)。確認版本:podman --version |
| Git | 必須 | 用於下載 mkcert 憑證工具 |
| OpenSSL | 必須 | 用於產生自簽憑證及驗證 TLS。確認版本:openssl version |
| systemd | 必須 | Quadlet 依賴 systemd generator 產生 service |
網路 Port
Mail Server 需開放以下 Port(使用 hostNetwork 模式會直接綁定主機 Port):
| Port | 協定 | 服務 | 說明 |
|---|---|---|---|
| 25 | TCP | SMTP | 接收外部郵件 |
| 465 | TCP | SMTPS | SMTP over TLS(隱式 TLS) |
| 587 | TCP | Submission | SMTP 寄信(STARTTLS + 認證) |
| 993 | TCP | IMAPS | IMAP over TLS(收信) |
| 995 | TCP | POP3S | POP3 over TLS(收信) |
| 11334 | TCP | Rspamd Web UI | Rspamd 管理介面(HTTP) |
測試機器
| 項目 | 需求 | 說明 |
|---|---|---|
| 同網段的其他機器 | 必須 | 測試寄信步驟需在內網其他機器執行(不是 Mail Server 本機) |
| s-nail 或 msmtp | 建議 | 用於 SMTP 寄信測試。步驟十一會說明安裝方式 |
| dig | 建議 | 用於驗證 DNS Record。安裝:apt install dnsutils 或 apk add bind-tools |
快速檢查腳本
在 Mail Server 主機上執行,一次確認所有前置條件:
cat << 'SCRIPT' | sudo tee /usr/local/bin/check-mail-prereqs.sh
#!/bin/bash
# Mail Server 前置條件檢查腳本
# 用法:bash check-mail-prereqs.sh <DNS_IP>
DNS_IP="${1:?用法: bash $0 <DNS_IP>}"
R='\033[31m'
G='\033[32m'
N='\033[0m'
P=0
F=0
c(){
local label="$1"
local cmd="$2"
if eval "$cmd" >/dev/null 2>&1; then
echo -e " [${G}PASS${N}] ${label}"
((P++))
else
echo -e " [${R}FAIL${N}] ${label}"
((F++))
fi
}
# 檢查 Port 是否被非 mail 服務佔用
# 排除 master (Postfix)、dovecot、rspamd — Container 內的 mail 服務屬正常
check_port(){
local port="$1"
! ss -tlnp 2>/dev/null | grep -E ":${port}\b" | grep -Eqv 'master|dovecot|rspamd'
}
echo "===== Mail Server 前置條件檢查 ====="
PODMAN_MAJOR=$(podman --version 2>/dev/null | awk '{print $3}' | cut -d. -f1)
c "Podman >= 4.4" "test ${PODMAN_MAJOR:-0} -ge 4"
c "Quadlet generator" "test -f /usr/libexec/podman/quadlet"
c "OpenSSL" "openssl version"
c "Git" "git --version"
c "systemd" "systemctl is-system-running | grep -qE 'running|degraded'"
c "Port 25 未被其他服務佔用" "check_port 25"
c "Port 465 未被其他服務佔用" "check_port 465"
c "Port 587 未被其他服務佔用" "check_port 587"
c "Port 993 未被其他服務佔用" "check_port 993"
c "Port 995 未被其他服務佔用" "check_port 995"
c "Port 11334 未被其他服務佔用" "check_port 11334"
c "DNS Server ${DNS_IP}" "dig @${DNS_IP} google.com +short +time=3"
echo "===== ${P} 通過 / ${F} 失敗 ====="
SCRIPT
sudo chmod +x /usr/local/bin/check-mail-prereqs.sh執行檢查(帶入 DNS Server IP):
sudo bash /usr/local/bin/check-mail-prereqs.sh 192.168.11.2 # ← 根據環境修改注意: Port 檢查會排除 Postfix(master)、Dovecot、Rspamd,因為使用
hostNetwork模式時 Container 內的服務會直接綁定主機 Port,這是正常的。檢查目的是確認沒有其他非 Mail Server 的服務佔用這些 Port。 如果 Mail Server 尚未啟動,所有 Port 檢查應顯示 PASS。
環境變數速查表
後續每個步驟的開頭都會列出該步驟所需的環境變數,請根據你的環境修改後再執行。
| 變數 | 範例值 | 說明 |
|---|---|---|
DN | kubeantony.com | 郵件域名 |
MAIL_HOST | mx1 | 郵件主機名稱前綴 |
MAIL_FQDN | mx1.kubeantony.com | 郵件主機 FQDN |
MAIL_IP | 192.168.11.3 | Mail Server IP |
DNS_IP | 192.168.11.2 | 內網 DNS Server IP |
MY_NETWORKS | 127.0.0.0/8,192.168.11.0/24 | 允許 relay 的網段 |
NET_IF | ens18 | Mail Server 網路介面名稱 |
POSTMASTER | bigred | Postmaster 帳號名稱 |
RSPAMD_PW | $2$zmnrfh... | Rspamd Web UI 密碼 hash |
一、建立 Container Image
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名1.1 建立 Dockerfile
sudo mkdir -p /opt/zfs/images/dkmail-rspamd
cat << 'EOF' | sudo tee /opt/zfs/images/dkmail-rspamd/Dockerfile
FROM docker.io/mailserver/docker-mailserver
ARG DN=""
ENV OVERRIDE_HOSTNAME="mx1.${DN}" \
DMS_DEBUG="1" \
POSTMASTER_ADDRESS="bigred@${DN}" \
ENABLE_RSPAMD="1" \
ENABLE_OPENDKIM="0" \
ENABLE_OPENDMARC="0" \
ENABLE_POLICYD_SPF="0" \
ENABLE_AMAVIS="0" \
ENABLE_SPAMASSASSIN="0" \
ENABLE_IMAP="1" \
ENABLE_POP3="1"
RUN apt-get update && apt-get install -y net-tools curl wget nano && \
setup email add bigred@${DN} bigred && \
setup email add rbean@${DN} rbean && \
setup email add gbean@${DN} gbean && \
touch /tmp/docker-mailserver/postfix-main.cf
EOF1.2 Build 映像檔
sudo podman build \
--build-arg DN="${DN}" \
--format docker \
--no-cache \
-t dkmail.rspamd \
/opt/zfs/images/dkmail-rspamd/1.3 標記映像檔(Kubernetes YAML 需要 localhost 前綴)
sudo podman tag dkmail.rspamd localhost/dkmail.rspamd:latest二、產生自簽 TLS 憑證
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export MAIL_HOST="mx1" # 郵件主機名稱前綴
export MAIL_FQDN="${MAIL_HOST}.${DN}" # 郵件主機 FQDN(自動組合)2.1 下載 mkcert 工具
cd /opt
sudo git clone https://github.com/braveantony/mkcert.git
sudo chmod +x /opt/mkcert/certctl2.2 編輯設定檔
cat << EOF | sudo tee /opt/mkcert/config
# CA 相關設定
CA_KEY="ca.key"
CA_CRT="ca.crt"
CA_DAYS=3650
CA_SUBJ="/C=TW/ST=Taipei/L=Taipei/O=${DN}/OU=Mail/CN=${DN} Root CA"
# Server 相關設定
DOMAIN_NAME="${DN}"
SERVER_KEY="\${DOMAIN_NAME}.key"
SERVER_CSR="\${DOMAIN_NAME}.csr"
SERVER_CRT="\${DOMAIN_NAME}.crt"
SERVER_DAYS=3650
SERVER_SUBJ="/C=TW/ST=Taipei/L=Taipei/O=${DN}/OU=Mail/CN=${MAIL_FQDN}"
V3_EXT="v3.ext"
ALT_NAMES=(
"DNS.1=*.\${DOMAIN_NAME}"
"DNS.2=\${DOMAIN_NAME}"
"DNS.3=${MAIL_FQDN}"
)
EOF2.3 產生憑證
sudo /opt/mkcert/certctl2.4 確認產生結果
ls -l /opt/mkcert/${DN}/預期輸出:
ca.crt # CA 根憑證
ca.key # CA 私鑰
<DN>.crt # 伺服器憑證
<DN>.key # 伺服器私鑰三、部署 TLS 憑證與設定檔
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export MY_NETWORKS="127.0.0.0/8,192.168.11.0/24" # 允許 relay 的網段
export RSPAMD_PW='$2$zmnrfhkhbr9sb411b8eykyxgs1do4jeg$3fjncbo78qfsymbzu7nhfi35inhwezqh313trc7if4ie3d6sj1fy' # Rspamd Web UI 密碼 hash3.1 建立目錄結構
sudo mkdir -p \
/opt/zfs/dkmail/data \
/opt/zfs/dkmail/conf/ssl \
/opt/zfs/dkmail/conf/rspamd/override.d3.2 複製憑證
sudo cp /opt/mkcert/${DN}/${DN}.key /opt/zfs/dkmail/conf/ssl/
sudo bash -c "cat \
/opt/mkcert/${DN}/${DN}.crt \
/opt/mkcert/${DN}/ca.crt \
> /opt/zfs/dkmail/conf/ssl/fullchain.pem"
sudo chmod 644 /opt/zfs/dkmail/conf/ssl/fullchain.pem
sudo chmod 600 /opt/zfs/dkmail/conf/ssl/${DN}.key3.3 Rspamd 設定
cat << 'EOF' | sudo tee /opt/zfs/dkmail/conf/rspamd/override.d/options.inc
local_networks = ["127.0.0.1/8"];
EOF
cat << EOF | sudo tee /opt/zfs/dkmail/conf/rspamd/override.d/worker-controller.inc
password = ${RSPAMD_PW}
EOF
cat << 'EOF' | sudo tee /opt/zfs/dkmail/conf/rspamd/override.d/hfilter.conf
enabled = false;
EOF3.4 Postfix 額外設定
重要: docker-mailserver 透過
SSL_TYPE=manual環境變數會自動設定 Postfix TLS(smtpd_tls_chain_files)、 Dovecot TLS、以及 SASL 認證 socket。postfix-main.cf只需放 docker-mailserver 沒有自動處理的額外設定, 不可手動設定smtpd_tls_cert_file/smtpd_tls_key_file,否則會與smtpd_tls_chain_files衝突。
cat << EOF | sudo tee /opt/zfs/dkmail/conf/postfix-main.cf
# Relay 設定(允許內網寄信)
mynetworks = ${MY_NETWORKS}
# 寄出郵件啟用 TLS
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
EOF四、建立 Kubernetes YAML
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export MAIL_HOST="mx1" # 郵件主機名稱前綴
export MAIL_FQDN="${MAIL_HOST}.${DN}" # 郵件主機 FQDN(自動組合)
export DNS_IP="192.168.11.2" # 內網 DNS Server IP
export NET_IF="ens18" # Mail Server 網路介面名稱cat << EOF | sudo tee /etc/containers/systemd/dkmail.yaml
apiVersion: v1
kind: Pod
metadata:
name: dkmail
labels:
app: dkmail
spec:
hostname: ${MAIL_FQDN}
hostNetwork: true
dnsConfig:
nameservers:
- ${DNS_IP}
searches:
- ${DN}
containers:
- name: dkmail
image: localhost/dkmail.rspamd:latest
env:
- name: NETWORK_INTERFACE
value: "${NET_IF}"
- name: SSL_TYPE
value: "manual"
- name: SSL_CERT_PATH
value: "/etc/ssl/mail/fullchain.pem"
- name: SSL_KEY_PATH
value: "/etc/ssl/mail/${DN}.key"
volumeMounts:
- name: mail-data
mountPath: /var/mail
- name: postfix-main-cf
mountPath: /tmp/docker-mailserver/postfix-main.cf
readOnly: true
- name: rspamd-config
mountPath: /tmp/docker-mailserver/rspamd
- name: ssl-certs
mountPath: /etc/ssl/mail
readOnly: true
volumes:
- name: mail-data
hostPath:
path: /opt/zfs/dkmail/data
type: Directory
- name: postfix-main-cf
hostPath:
path: /opt/zfs/dkmail/conf/postfix-main.cf
type: File
- name: rspamd-config
hostPath:
path: /opt/zfs/dkmail/conf/rspamd
type: Directory
- name: ssl-certs
hostPath:
path: /opt/zfs/dkmail/conf/ssl
type: Directory
EOFYAML 與原始 podman run 參數對照
原始 podman run 參數 | YAML 對應欄位 |
|---|---|
--name dkmail | metadata.name: dkmail |
-h ${MAIL_FQDN} | spec.hostname |
--network=host | spec.hostNetwork: true |
--dns ${DNS_IP} | spec.dnsConfig.nameservers |
--dns-search ${DN} | spec.dnsConfig.searches |
-e NETWORK_INTERFACE=${NET_IF} | containers[].env |
-e SSL_TYPE=manual | containers[].env |
-v ...:/var/mail | volumes + volumeMounts |
-v ...:ro | volumeMounts 加上 readOnly: true |
說明: 不需要掛載 Dovecot SSL 設定檔。docker-mailserver 會根據
SSL_TYPE=manual+SSL_CERT_PATH+SSL_KEY_PATH自動設定 Postfix TLS、Dovecot TLS 和 SASL 認證 socket。
五、建立 Quadlet .kube 檔案
cat << 'EOF' | sudo tee /etc/containers/systemd/dkmail.kube
[Unit]
Description=Docker Mail Server (dkmail) with TLS
After=network-online.target
Wants=network-online.target
[Kube]
Yaml=/etc/containers/systemd/dkmail.yaml
Network=host
[Service]
Restart=always
RestartSec=10
TimeoutStartSec=120
[Install]
WantedBy=multi-user.target default.target
EOF.kube 各區塊說明
| 區塊 | 設定 | 說明 |
|---|---|---|
[Unit] | After=network-online.target | 網路就緒後才啟動 |
[Kube] | Yaml=... | 指向 Kubernetes YAML 路徑 |
[Kube] | Network=host | 使用 host 網路(郵件服務需直接綁定 Port) |
[Service] | Restart=always | 異常退出自動重啟 |
[Service] | TimeoutStartSec=120 | 給 Container 足夠啟動時間 |
[Install] | WantedBy=multi-user.target | 開機自動啟動 |
六、啟動服務
# 重新載入 systemd(讓 Quadlet generator 產生 service)
sudo systemctl daemon-reload
# 啟動服務
sudo systemctl start dkmail.service
# 設定開機自動啟動
sudo systemctl enable dkmail.service
# 確認狀態
sudo systemctl status dkmail.service七、驗證 TLS
# ===== 根據環境修改 =====
export MAIL_FQDN="mx1.kubeantony.com" # 郵件主機 FQDN7.1 確認 Pod 與 Container
sudo podman pod ps
sudo podman ps --pod7.2 確認 TLS
# SMTP STARTTLS(Port 587)
openssl s_client -connect ${MAIL_FQDN}:587 -starttls smtp
# SMTPS(Port 465)
openssl s_client -connect ${MAIL_FQDN}:465
# IMAPS(Port 993)
openssl s_client -connect ${MAIL_FQDN}:993
# POP3S(Port 995)
openssl s_client -connect ${MAIL_FQDN}:995正常輸出應包含:
subject: CN = <MAIL_FQDN>
issuer: CN = <DN> Root CA
Verify return code: 21 (unable to verify the first certificate) ← 自簽憑證正常現象八、設定 SPF Record
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export MAIL_IP="192.168.11.3" # Mail Server IP
export DNS_IP="192.168.11.2" # 內網 DNS Server IP透過 nsupdate 將 SPF 記錄新增至內網 DNS(BIND):
nsupdate << EOF
server ${DNS_IP}
zone ${DN}
update del ${DN}. TXT
update add ${DN}. 300 IN TXT "v=spf1 ip4:${MAIL_IP} ~all"
send
EOF驗證 SPF Record:
dig @${DNS_IP} ${DN}. TXT +short預期輸出:
"v=spf1 ip4:<MAIL_IP> ~all"九、設定 DKIM
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export DNS_IP="192.168.11.2" # 內網 DNS Server IP9.1 產生 DKIM Key
sudo podman exec -it dkmail-dkmail setup config dkim domain ${DN}預期輸出:
INFO rspamd-dkim: Creating DKIM keys of type 'rsa' and length '2048' with selector 'mail' for domain '<DN>'
INFO rspamd-dkim: Successfully created DKIM keys
INFO rspamd-dkim: Here is the content of the TXT DNS record mail._domainkey.<DN> that you need to create:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQE...9.2 啟用內網寄信的 DKIM 簽署
重要: docker-mailserver 預設產生的
dkim_signing.conf中sign_local = false, 這會導致從內網直接寄出的郵件不會被 DKIM 簽署。必須改為true。
sudo sed -i 's/sign_local = false/sign_local = true/' \
/opt/zfs/dkmail/conf/rspamd/override.d/dkim_signing.conf驗證修改結果:
grep 'sign_local' /opt/zfs/dkmail/conf/rspamd/override.d/dkim_signing.conf預期輸出:
sign_local = true;9.3 確認產生的檔案
tree /opt/zfs/dkmail/conf/rspamd/預期結構:
/opt/zfs/dkmail/conf/rspamd/
├── dkim
│ ├── rsa-2048-mail-<DN>.private.txt
│ ├── rsa-2048-mail-<DN>.public.dns.txt
│ └── rsa-2048-mail-<DN>.public.txt
└── override.d
├── dkim_signing.conf
├── hfilter.conf
├── options.inc
└── worker-controller.inc9.4 擷取 DKIM Public Key
DKIM_K8S_TXT=$(sed -n 's|.*"\([^"]*\)".*|"\1"|p' \
/opt/zfs/dkmail/conf/rspamd/dkim/rsa-2048-mail-${DN}.public.txt | tr '\n' ' ')
echo $DKIM_K8S_TXT9.5 新增 DKIM TXT Record(以 BIND DNS 為例)
nsupdate << EOF
server ${DNS_IP}
zone ${DN}
update del mail._domainkey.${DN}
update add mail._domainkey.${DN} 3600 IN TXT $DKIM_K8S_TXT
send
EOF9.6 驗證 DKIM Record
dig @${DNS_IP} mail._domainkey.${DN}. TXT +short預期輸出:
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."9.7 重啟 Container 套用 DKIM 設定
sudo systemctl restart dkmail.service十、設定 DMARC Record
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export DNS_IP="192.168.11.2" # 內網 DNS Server IP
export POSTMASTER="bigred" # Postmaster 帳號名稱說明: DMARC 需在 SPF 和 DKIM 都設定完成後再新增。
p=none表示僅監控模式,不影響郵件遞送,待確認運作正常後可改為p=quarantine或p=reject。
nsupdate << EOF
server ${DNS_IP}
zone ${DN}
update del _dmarc.${DN}. TXT
update add _dmarc.${DN}. 300 IN TXT "v=DMARC1; p=none; rua=mailto:${POSTMASTER}@${DN}"
send
EOF驗證 DMARC Record:
dig @${DNS_IP} _dmarc.${DN}. TXT +short預期輸出:
"v=DMARC1; p=none; rua=mailto:<POSTMASTER>@<DN>"十一、測試寄信
重要: 以下測試步驟必須在同一內網的其他機器上執行(不是 Mail Server 本機)。 從其他機器寄信才能正確模擬實際使用情境,驗證
mynetworksrelay 設定、TLS 連線、SMTP 認證、 以及 DKIM 簽署(sign_local是否對內網來源生效)等功能是否正常。
# ===== 根據環境修改(在測試機器上執行)=====
export DN="kubeantony.com" # 郵件域名
export MAIL_HOST="mx1" # 郵件主機名稱前綴
export MAIL_FQDN="${MAIL_HOST}.${DN}" # 郵件主機 FQDN(自動組合)
export MAIL_IP="192.168.11.3" # Mail Server IP
export POSTMASTER="bigred" # Postmaster 帳號名稱11.1 安裝寄信工具(在內網其他機器上執行)
# Debian/Ubuntu
sudo apt install -y s-nail
# Alpine Linux
sudo apk add s-nail11.2 從內網直接寄信測試(不經 SMTP 認證)
echo "Test Mail" | s-nail \
-S mta=smtp://${MAIL_IP} \
-s "Mail Server Test" \
"sreantony@gmail.com"11.3 透過 SMTP 認證寄信測試(msmtp)
在內網其他機器上安裝 msmtp 並建立設定檔(自簽憑證需關閉憑證檢查):
cat << EOF > ~/.msmtprc
account test
host ${MAIL_FQDN}
port 587
from ${POSTMASTER}@${DN}
auth plain
user ${POSTMASTER}@${DN}
password ${POSTMASTER}
tls on
tls_starttls on
tls_certcheck off
logfile /tmp/msmtp.log
EOF
chmod 600 ~/.msmtprc注意: 帳號為
${POSTMASTER}@${DN}(不是${POSTMASTER}@${MAIL_FQDN}), 對應 Dockerfile 中setup email add bigred@${DN}的設定。
寄信測試:
echo -e "To: sreantony@gmail.com\nSubject: Auth Test\n\n認證測試" | msmtp -a test sreantony@gmail.com11.4 驗證 Rspamd 評分
開啟 Rspamd Web UI(http://${MAIL_FQDN}:11334)查看 History,
SPF / DKIM / DMARC 設定正確後,以下 Symbol 應消失或轉為通過:
| Symbol | 修正前 | 修正後 |
|---|---|---|
R_SPF_NA | +1.5(無 SPF) | R_SPF_ALLOW(SPF 通過) |
R_DKIM_NA | +1.0(無 DKIM) | R_DKIM_ALLOW(DKIM 通過) |
DMARC_NA | +0.5(無 DMARC) | DMARC_POLICY_ALLOW(DMARC 通過) |
AUTH_NA | +2.5(未認證) | 消失(經 SMTP 認證寄信) |
十二、日常管理
| 操作 | 指令 |
|---|---|
| 啟動 | sudo systemctl start dkmail.service |
| 停止 | sudo systemctl stop dkmail.service |
| 重啟 | sudo systemctl restart dkmail.service |
| 查看狀態 | sudo systemctl status dkmail.service |
| 查看 log | sudo journalctl -u dkmail.service -f |
| 開機啟動 | sudo systemctl enable dkmail.service |
| 取消開機啟動 | sudo systemctl disable dkmail.service |
| 進入 Container | sudo podman exec -it dkmail-dkmail bash |
| Container log | sudo podman logs -f dkmail-dkmail |
| Postfix log | sudo podman exec -it dkmail-dkmail tail -50 /var/log/mail/mail.log |
注意: Container 名稱為
dkmail-dkmail(Pod 名稱 + Container 名稱)。
十三、客戶端匯入 CA 根憑證
# ===== 根據環境修改 =====
export DN="kubeantony.com" # 郵件域名
export MAIL_IP="192.168.11.3" # Mail Server IP自簽憑證需在每台客戶端匯入 ca.crt:
# 從伺服器下載 ca.crt
scp user@${MAIL_IP}:/opt/mkcert/${DN}/ca.crt ~/Desktop/| 客戶端 | 匯入方式 |
|---|---|
| Thunderbird | 設定 → 隱私與安全 → 憑證 → 匯入 → 選 ca.crt → 勾選「信任此 CA 識別網站」 |
| Windows | 雙擊 ca.crt → 安裝憑證 → 「受信任的根憑證授權單位」 |
| macOS | 雙擊 ca.crt → 加入鑰匙圈 → 設定為「永遠信任」 |
| Linux | sudo cp ca.crt /usr/local/share/ca-certificates/ && sudo update-ca-certificates |
十四、故障排除
Quadlet 沒有產生 service
# 手動執行 generator 檢查錯誤
sudo /usr/libexec/podman/quadlet --dryrun手動測試 YAML 是否正確
# 用 podman kube play 直接測試
sudo podman kube play /etc/containers/systemd/dkmail.yaml
# 測試完畢清除
sudo podman kube down /etc/containers/systemd/dkmail.yaml映像檔找不到
sudo podman images | grep dkmail
# 如果缺少 localhost 前綴,重新標記
sudo podman tag dkmail.rspamd localhost/dkmail.rspamd:latestSMTP 寄信出現 Relay access denied
確認 postfix-main.cf 中 mynetworks 包含發信主機的網段:
sudo podman exec -it dkmail-dkmail postconf mynetworksSMTP 認證失敗(SASL)
確認 Dovecot auth socket 存在:
sudo podman exec -it dkmail-dkmail ls -l /dev/shm/sasl-auth.sock確認 Postfix 指向正確的 socket 路徑:
sudo podman exec -it dkmail-dkmail postconf smtpd_sasl_path注意: docker-mailserver 的 Dovecot auth socket 位於
/dev/shm/sasl-auth.sock, 不是 Postfix 預設的private/auth。不要在postfix-main.cf手動設定smtpd_sasl_path/smtpd_sasl_type,讓 docker-mailserver 自動處理。
TLS 憑證與 docker-mailserver 衝突
重要: 不要在
postfix-main.cf設定smtpd_tls_cert_file/smtpd_tls_key_file。 docker-mailserver 的SSL_TYPE=manual會使用smtpd_tls_chain_files, 兩者同時存在會產生衝突警告且舊的設定會被忽略。
完整目錄結構
/etc/containers/systemd/ # Quadlet 檔案
├── dkmail.kube # Quadlet 單元檔
└── dkmail.yaml # Kubernetes Pod YAML
/opt/zfs/dkmail/ # 資料與設定
├── data/ # 郵件資料(/var/mail)
└── conf/
├── postfix-main.cf # Postfix 額外設定(mynetworks + smtp_tls)
├── ssl/
│ ├── fullchain.pem # 伺服器憑證 + CA 憑證
│ └── <DN>.key # 伺服器私鑰
└── rspamd/
├── dkim/ # DKIM Keys(步驟九產生)
│ ├── rsa-2048-mail-<DN>.private.txt
│ ├── rsa-2048-mail-<DN>.public.dns.txt
│ └── rsa-2048-mail-<DN>.public.txt
└── override.d/
├── dkim_signing.conf # DKIM 簽署設定(步驟九產生)
├── options.inc
├── worker-controller.inc
└── hfilter.conf
/opt/mkcert/ # 憑證產生工具(備份保留)
├── certctl
├── config
└── <DN>/
├── ca.crt
├── ca.key
├── <DN>.crt
└── <DN>.key
/opt/zfs/images/dkmail-rspamd/ # Container Image Dockerfile
└── Dockerfile