SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-07

如何在 VPS 自架 Listmonk 電子報

在 Ubuntu 24.04 安裝 Listmonk v6.2.0,設定 PostgreSQL、config.toml、systemd 與 TLS,再連接 SMTP,了解實際投遞成本與寄件聲譽建立所需數週時間。

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(simple mail transfer protocol)伺服器,因此郵件投遞率取決於該伺服器的聲譽,而不是這套軟體。

本指南將在 Ubuntu 24.04 上安裝 Listmonk v6.2.0,即截至 July 2026 的目前版本。您需要一台具備公開 IP 位址的 VPS、一個由您管理的網域名稱,以及 PostgreSQL 12 或更新版本。安裝約需一小時。寄件聲譽需要數週建立,相關內容會在本文末尾說明。

安裝 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 server 僅繫結至 loopback,因此在設定反向代理之前,管理面板無法從網際網路連線。請不要修改該行。在 [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 status line,表示伺服器正在回應。curl 若失敗並顯示 Connection refused,表示程序在啟動期間終止,journalctl -u listmonk -n 50 --no-pager 會說明原因。請注意,enable --now 才是在重新開機後仍會保留的部分:手動啟動的程序會在下一次核心升級後消失。

在前方配置 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 設定行,以及從 80 埠重新導向的規則:操作步驟請參閱 nginx 的 Let's Encrypt 憑證指南。開放 80 與 443 埠,並保持 9000 埠關閉,因為代理會透過 loopback 連線到該埠。如果防火牆尚未設定,請先從 ufw 防火牆基礎 開始。

接著開啟管理面板,將 Settings 中的根 URL 設為 https://lists.example.com。全新安裝會使用 http://localhost:9000,而 Listmonk 會將該值寫入電子郵件中的每個取消訂閱連結與媒體 URL。變更前先發送 campaign,收件者收到的連結會指向各自的電腦。這些連結對讀者無法使用,對垃圾郵件篩選器而言,也像是寄件者無法正確設定自己的網域。

連接 SMTP;設定不在 config.toml

搜尋 config.toml 後,找不到 SMTP 區段。郵件設定儲存在資料庫的 settings 資料表中,並可在管理面板的 Settings 和 SMTP 中編輯。因此,產生的檔案會維持精簡,而且變更 SMTP 設定不需要重新啟動。

SMTP 伺服器本身有兩個可行選項。自行執行 SMTP 伺服器,這會讓寄件 IP 的聲譽完全由你負責,而且本身就是一個完整的專案:使用 Mailcow 執行自有郵件伺服器 說明其中涉及的工作。或者,將 Listmonk 指向交易型郵件轉送服務,讓服務商負責 IP 聲譽。

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

在信任設定前先進行測試。建立一個清單,將自己的地址加入為訂閱者,然後傳送一封只有一位收件者的行銷郵件。開啟收到的郵件並查看完整標頭。接收端加入的 Authentication-Results 標頭會告訴你 SPF 和 DKIM 是否通過。

可遞送性是整項工作的核心

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

以下四項不可省略:

  • SPF(sender policy framework)TXT 記錄,指定獲准代表網域寄信的主機。
  • DKIM(domainkeys identified mail)金鑰,以 TXT 記錄公開;簽署工作應由郵件伺服器執行,而不是由 Listmonk 執行。
  • DMARC(domain based message authentication, reporting and conformance)記錄,告知收件端在前兩項驗證失敗時應採取的處置方式。
  • 由 Listmonk 讀取的退信信箱,讓拒收郵件的地址從名單中移除,而不是無限次重試寄送。

一開始也應放慢寄送速度。從未寄過郵件的網域若突然在 1 小時內寄出 10000 封郵件,其特徵與遭入侵的帳號完全相同,因此會被套用相同的過濾方式。先寄送給互動程度最高的訂閱者,再在數天內逐步提高寄送量。

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

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

必須將兩項內容移出伺服器:資料庫傾印檔與 config.toml。如果您會將圖片上傳至行銷活動,請一併備份 media 目錄。

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

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

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

為什麼 Listmonk 無法啟動?

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

pq: password authentication failed for user "listmonk" 表示 [db] 中的密碼與 Postgres role 不一致。pq 前綴是 Postgres driver 回報伺服器拒絕要求的訊息,表示設定檔已正確讀取,但憑證不正確。使用 sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" 重設 role,並在檔案中填入完全相同的字串。

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

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

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

管理面板可以使用,但沒有郵件送達。 這不是啟動問題。先檢查 Settings 和 SMTP,再查看管理面板中該行銷活動的專屬日誌;其中會記錄郵件伺服器對每次嘗試回傳的錯誤。

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 顯示 user listmonk 的密碼驗證失敗?

/etc/listmonk/config.toml[db] 區塊中所設定的密碼,與同名 Postgres role 的密碼不一致。日誌中的訊息是 pq: password authentication failed for user "listmonk",而 pq 表示 Postgres driver 正在轉述伺服器的拒絕結果,這代表系統已找到並讀取設定檔。請使用 sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" 重設該 role 的密碼,將完全相同的字串寫入設定檔,然後執行 sudo systemctl restart listmonk