SSD Nodes Learn 8GB 記憶體 — 每年 $66
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-01

Listmonk 自架電子報:Ubuntu 24.04 VPS 安裝教學

在 Ubuntu 24.04 安裝 Listmonk v6.2.0,設定 PostgreSQL、config.toml、systemd 與 TLS,再連接 SMTP。安裝約需 1 小時,但建立寄件信譽通常要數週。

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Listmonk 自架電子報的需求

Listmonk 是自架式電子報與郵件清單管理工具:一個 Go 二進位檔、一個 PostgreSQL 資料庫、一個設定檔,以及一個 systemd 單元。小型 VPS 即可輕鬆執行,因為 Listmonk 會儲存訂閱者資料並將行銷活動加入佇列,但不會自行傳送郵件。它會將每封郵件交給 SMTP(簡易郵件傳輸通訊協定)伺服器,因此郵件的遞送率取決於該伺服器的信譽,而不是這套軟體。

本指南會在 Ubuntu 24.04 上安裝 Listmonk v6.2.0,這是截至 2026 年 7 月的目前版本。您需要一台具備公用 IP 位址的 VPS、一個由您控制的網域名稱,以及 PostgreSQL 12 或更新版本。安裝約需 1 小時。建立寄件信譽則需要數週,相關內容會在文末說明。

安裝 PostgreSQL 並建立資料庫

Ubuntu 24.04 在自己的套件庫中提供 PostgreSQL 16,版本遠高於 Listmonk 的需求。

sudo apt update
sudo apt install -y postgresql curl
sudo systemctl enable --now postgresql

在同一個 psql 工作階段中建立角色和資料庫。-v ON_ERROR_STOP=1 會讓 psql 在第一個失敗的陳述式發生時結束,因此即使輸入錯字,也不會留下看似完成但實際只完成一半的設定。

sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL'
CREATE USER listmonk WITH PASSWORD 'pick-a-long-random-password';
CREATE DATABASE listmonk OWNER listmonk;
SQL

OWNER listmonk 並非裝飾。安裝結構描述時會建立資料表、類型、索引和函式,因此該角色必須擁有資料庫。若讓 Listmonk 使用其他角色擁有的資料庫,即使已執行 GRANT CONNECT,安裝仍會因 permission denied 而停止。

繼續之前,先確認資料庫已存在。

sudo -u postgres psql -tAc "SELECT datname FROM pg_database WHERE datname='listmonk';"

這會輸出 listmonk。空白行表示 CREATE 陳述式從未執行,因此請再次查看 psql 輸出。

安裝 Listmonk 二進位檔

Listmonk 會針對每種架構發布靜態二進位檔。請先確認您的架構,因為在 ARM VPS 上使用 amd64 二進位檔時,核心會拒絕執行該檔案。

dpkg --print-architecture
cd /tmp
curl -fsSLO https://github.com/knadh/listmonk/releases/download/v6.2.0/listmonk_6.2.0_linux_amd64.tar.gz
tar -xzf listmonk_6.2.0_linux_amd64.tar.gz
sudo install -m 755 listmonk /usr/bin/listmonk
listmonk --version

在 ARM VPS 上,請將檔名中的 amd64 改為 arm64listmonk --version 能列印版本字串,即可初步證明二進位檔符合該機器的架構。

產生 config.toml 並限制其存取權限

--new-config 會將 config.toml 寫入目前的工作目錄。因此,cd 會放在 sh -c 內,而不是放在 sudo 之前。

sudo install -d -m 750 /etc/listmonk
sudo sh -c 'cd /etc/listmonk && listmonk --new-config'

產生的檔案很短。在 [app] 下,address = "localhost:9000" 只會將 HTTP 伺服器繫結至 loopback,因此在設定 reverse proxy 之前,管理面板無法從網際網路存取。請保留該行不變。在 [db] 下,您會看到 host = "localhost"port = 5432user = "listmonk"database = "listmonk"ssl_mode = "disable"。這些預設值已符合您建立的資料庫,因此只需變更密碼即可。

當 Postgres 在同一部主機的 loopback 上監聽時,ssl_mode = "disable" 設定正確,因為該流量不會離開這部機器。若將資料庫移至其他主機,請將其設為 require,否則密碼會以明文在網路上傳送。

編輯 [db] 下的密碼行,使其符合該角色,然後建立服務帳戶,並禁止所有其他登入帳戶存取該檔案。

sudo useradd --system --home-dir /var/lib/listmonk --create-home --shell /usr/sbin/nologin listmonk
sudo chown -R root:listmonk /etc/listmonk
sudo chmod 640 /etc/listmonk/config.toml

現在,服務帳戶可以讀取該檔案,其他帳戶則無法讀取。

sudo -u listmonk cat /etc/listmonk/config.toml > /dev/null && echo readable
stat -c '%U:%G %a' /etc/listmonk/config.toml

第一個命令會輸出 readable。第二個命令會輸出 root:listmonk 640。任何其他未具備特權的帳戶若嘗試相同的 cat,都會取得 Permission denied。這正是目的所在:此檔案以明文保存資料庫密碼,而伺服器通常不只一個登入帳戶。相同的原則適用於您執行的每項服務,因此請閱讀一次權限最小化的服務使用者,並在所有服務中套用這項原則。

使用 --install 建立結構描述

--install 會建立資料表並寫入預設設定。使用環境變數設定第一個管理員登入資訊,確保控制面板可供存取前,該帳戶已經存在。

sudo -u listmonk env LISTMONK_ADMIN_USER=admin \
  LISTMONK_ADMIN_PASSWORD='another-long-random-password' \
  listmonk --config /etc/listmonk/config.toml --install --yes

--yes 會回應確認提示。自動化前,請先閱讀一次該提示,因為 --install 會執行初次安裝,並刪除現有的 Listmonk 結構描述。在正式資料庫上第二次執行會破壞訂閱者資料。在任何可能執行兩次的指令碼中,請使用 --install --idempotent --yes;如果資料表已存在,該選項不會執行任何動作。新版本發布的結構描述變更,請使用 --upgrade 套用,絕不要使用 --install

請從資料庫端檢查結果,不要透過瀏覽器檢查。

sudo -u postgres psql -d listmonk -c '\dt'
sudo -u postgres psql -d listmonk -tAc "SELECT username FROM users;"

第一個指令會列出 Listmonk 資料表,其中包括 subscriberslistscampaignstemplatesbounces。第二個指令會列印 admin。如果第二個指令輸出空白,表示環境變數從未傳遞至處理程序,因此控制面板會改為要求您在瀏覽器中建立第一個使用者。

在 systemd 下執行 Listmonk

撰寫 /etc/systemd/system/listmonk.service

[Unit]
Description=Listmonk newsletter and mailing list manager
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=listmonk
Group=listmonk
WorkingDirectory=/var/lib/listmonk
ExecStart=/usr/bin/listmonk --config /etc/listmonk/config.toml
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

WorkingDirectory 很重要,因為 Listmonk 會以此為基準解析相對路徑,包括檔案系統媒體上傳路徑。After=postgresql.service 只會下達啟動順序,不會等待 Postgres 接受連線,因此 Restart=on-failure 可處理 Listmonk 過早啟動而無法連線的情況。

sudo systemctl daemon-reload
sudo systemctl enable --now listmonk
ss -ltnp | grep 9000
curl -sI http://127.0.0.1:9000/

ss 應顯示 127.0.0.1:9000 處於 LISTEN 狀態。curl 傳回任何 HTTP 狀態列,都表示伺服器正在回應。curl 若失敗並顯示 Connection refused,表示程序在啟動期間終止,journalctl -u listmonk -n 50 --no-pager 會說明原因。請注意,enable --now 才是在重新開機後仍會保留的部分:手動啟動的程序會在下一次 kernel 升級後消失。

在前端配置 nginx 和 TLS

Listmonk 在 loopback 上使用純 HTTP,因此由 nginx 終止 TLS(傳輸層安全性),再轉送要求。

server {
    listen 443 ssl;
    server_name lists.example.com;

    client_max_body_size 25m;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

必須提高 client_max_body_size,因為訂閱者匯入和媒體上傳都是檔案 POST,而 nginx 預設會以 413 Request Entity Too Large 拒絕任何超過 1 MB 的內容。使用 certbot 核發憑證;它也會替您寫入 listen 443 ssl 設定行,以及從 port 80 重新導向的設定:步驟請參閱 nginx 的 Let's Encrypt 憑證指南。開放 port 80 和 443,並保持 9000 關閉,因為 proxy 會透過 loopback 連線到該 port。如果尚未設定防火牆,請先參閱 ufw 防火牆基礎

接著開啟管理面板,並在 Settings 下將根 URL 設為 https://lists.example.com。全新安裝會使用 http://localhost:9000,而 Listmonk 會將該值寫入電子郵件中的每個取消訂閱連結和媒體 URL。請在變更設定前先傳送一個行銷活動,否則每位收件者都會收到指向自己電腦的連結。這些連結對收件者無法使用;對垃圾郵件篩選器而言,這看起來像是寄件者無法設定自己的網域。

連線至未寫入 config.toml 的 SMTP

搜尋 config.toml 中的 SMTP 區段,但找不到任何內容。郵件設定儲存在資料庫的 settings 資料表中,您可以在管理面板的「Settings」和「SMTP」下編輯這些設定。因此,產生的檔案會保持簡短,SMTP 設定變更也不需要重新啟動。

SMTP 伺服器本身有兩個可行選項。您可以自行執行 SMTP 伺服器,完全自行負責寄件信譽;這本身就是一項完整的專案:使用 Mailcow 執行自己的郵件伺服器 說明相關工作。或者,將 Listmonk 指向交易型郵件轉送服務,讓服務商負責 IP 信譽。

無論採用哪個選項,請使用搭配 STARTTLS 的連接埠 587,或使用隱式 TLS 的連接埠 465。不要規劃使用對外連線的連接埠 25。大多數 VPS 供應商在新帳戶上預設封鎖此連接埠。連接埠 25 被封鎖時,連線會看起來像是卡住,因為封包會遭到丟棄而不是拒絕。因此,客戶端會等待逾時,而不是立即失敗。

請先進行測試,再正式使用。建立一個清單,將您自己的地址新增為訂閱者,然後傳送一封只有一位收件者的行銷活動郵件。開啟收到的郵件並讀取完整標頭。接收端新增的 Authentication-Results 標頭會告訴您 SPF 和 DKIM 是否通過驗證。

郵件投遞率就是全部工作

Listmonk 負責建立郵件、追蹤清單,並將郵件交給郵件伺服器。郵件是否能抵達收件匣,完全由接收服務商根據寄件 IP 位址與寄件網域決定。新的 VPS IP 沒有任何歷史紀錄,而所有大型信箱服務商都會將沒有歷史紀錄視為具有些許可疑性。

以下四項不可或缺:

  • SPF(寄件者政策架構)TXT 記錄,指定獲准代表您的網域寄送郵件的主機。
  • DKIM(網域金鑰識別郵件)金鑰,以 TXT 記錄發布,且由郵件伺服器完成簽署,而不是由 Listmonk 簽署。
  • DMARC(網域型郵件驗證、報告與一致性)記錄,告知接收端前兩項驗證失敗時應如何處理。
  • Listmonk 讀取的退信信箱,讓拒收郵件的地址從清單中移除,而不是永遠重試寄送。

接著一開始要放慢寄送速度。從未寄送過郵件的網域,若突然在 1 小時內寄出 10000 封郵件,與遭入侵的帳戶完全相似,因此會被以遭入侵帳戶的方式篩選。先寄送給互動程度最高的訂閱者,再在數天內逐步提高寄送量。

每個範本也都需要可正常運作的取消訂閱連結。在 Listmonk 範本中,該連結是 {{ UnsubscribeURL }},而行銷活動內文會插入 {{ template "content" . }} 所在的位置;每個範本必須恰好出現 1 次。沒有取消訂閱連結的行銷活動會引發垃圾郵件投訴,而不是取消訂閱;投訴是最快耗損寄件聲譽的方式,而建立這項聲譽可能已花費數週。

備份,以及實際還原所需的內容

有兩項內容必須移出此伺服器:資料庫傾印和 config.toml。如果您將映像檔上傳至行銷活動,還必須加入媒體目錄。

sudo -u postgres pg_dump -Fc listmonk > listmonk-$(date +%F).dump

該傾印包含訂閱者、行銷活動、範本和所有設定,包括 SMTP 認證資訊。因此請將其加密,並儲存在此伺服器之外。排程備份已有成熟的解決方案:請參閱 使用加密的 restic 備份至遠端儲存空間config.toml 雖然只有幾行內容,但包含資料庫密碼,因此請以相同方式處理。

升級必須依照固定順序進行。停止服務、建立傾印、替換 /usr/bin 中的二進位檔、執行 listmonk --config /etc/listmonk/config.toml --upgrade,然後啟動服務。結構描述遷移只能向前執行,因此該傾印是唯一的回復途徑。

Listmonk 為何無法啟動?

先使用 journalctl -u listmonk -n 50 --no-pager 讀取日誌。幾乎所有啟動失敗都會在 [db] 區塊中以一行訊息呈現。

pq: password authentication failed for user "listmonk" 表示 [db] 中的密碼與 Postgres 角色不相符。pq 前綴表示 Postgres driver 回報伺服器拒絕連線,因此設定檔已正確讀取,但認證資訊錯誤。使用 sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" 重設角色,並在檔案中填入完全相同的字串。

pq: database "listmonk" does not exist 表示 [db] 中的 database 值不是有效的資料庫名稱。sudo -u postgres psql -l 會列出伺服器上實際存在的項目,包括您誤用的拼寫。

--install 期間出現 permission denied,表示該角色可以連線,但不是資料庫擁有者,因此無法在其中建立資料表。使用 sudo -u postgres psql -c "ALTER DATABASE listmonk OWNER TO listmonk;" 修正,然後再次執行安裝。

服務完全沒有啟動,且日誌指出設定檔。listmonk 執行的程序無法開啟權限設為 root:root、模式為 600 的 config.tomlstat -c '%U:%G %a' /etc/listmonk/config.toml 應輸出 root:listmonk 640,而其上層目錄應為 root:listmonk 750

管理面板可正常運作,但沒有收到郵件。 這不是啟動問題。先檢查 Settings 和 SMTP,再檢查管理面板中該 campaign 的專屬日誌;該日誌會記錄郵件伺服器對每次嘗試回傳的錯誤。

FAQ

使用 Listmonk 需要自己的郵件伺服器嗎?

不需要。Listmonk 不是郵件伺服器。它需要可接受並傳送郵件之伺服器的 SMTP 憑證。該伺服器可以是交易型轉送服務,也可以是您自行執行的郵件伺服器。請在管理面板的 Settings 和 SMTP 中設定這些憑證,不要設定在 config.toml 中,因為郵件設定儲存在資料庫內。請使用搭配 STARTTLS 的連接埠 587,或使用隱式 TLS 的連接埠 465,因為大多數 VPS 供應商會封鎖新帳戶的輸出連接埠 25。

為什麼我的行銷活動連結會指向 localhost:9000?

根 URL 設定仍是安裝時的預設值 http://localhost:9000。Listmonk 會在傳送行銷活動時,將該值寫入取消訂閱連結和媒體 URL。請在管理面板中開啟 Settings,將根 URL 設為實際的 HTTPS 位址,然後儲存。已傳送的訊息無法修正,因此請先寄送測試行銷活動給自己,並在寄送給實際名單前,點選其中的取消訂閱連結。

再次執行 --install 會清除我的訂閱者嗎?

會。--install 是首次安裝程式,會刪除現有的 Listmonk schema;--yes 則會移除原本用於警告您的提示。在可能執行兩次的任何指令碼中,請使用 --install --idempotent --yes。當資料表已存在時,該指令不會執行任何動作。若要套用新版本中的 schema 變更,請停止服務、建立 pg_dump,然後執行 --upgrade

為什麼 Listmonk 顯示使用者 listmonk 的密碼驗證失敗?

/etc/listmonk/config.toml[db] 區塊中所設定的密碼,與相同名稱之 Postgres 角色的密碼不一致。日誌中的行是 pq: password authentication failed for user "listmonk"pq 表示 Postgres 驅動程式轉傳伺服器拒絕連線的回應。這表示系統已找到並讀取設定檔。請使用 sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" 重設該角色的密碼,將完全相同的字串寫入設定檔,然後執行 sudo systemctl restart listmonk