前言#
在「2024 年了,我的博客有了什麼變化」一文中,我介紹了自己使用 Serverless 平台和一些開源項目搭建的博客系統,也開啟了這個系列教程來記錄搭建和部署過程。
本篇是關於評論系統的解決方案。
評論系統迭代#
我常常覺得評論不僅僅是讀者與作者之間的溝通互動,其內容本身也是文章的一部分,甚至常常有些評論的思考與觀點討論會比文章本身更有價值,所以對於評論系統一直很重視,並不願意信任一些第三方托管的服務,不希望有什麼審查,也想風格盡可能簡約,並與自己的博客風格相符。
在博客發展過程中,評論系統方案也經歷過幾次迭代,關於評論系統的類型和選擇,我很喜歡的開發者 reorx 在「更換博客評論系統」中有詳細的介紹,我不作更多引申了,本文更重個人體驗與詳細的搭建過程。
Disqus#
我最早使用的博客評論系統是萬惡的 Disqus,一個笨重且會收集用戶隱私的知名評論系統,因為加載比較慢,且免費版本經常會附帶一些廣告,實在難以忍受,再加上當時其實也基本上沒什麼評論,並沒有什麼遷移負擔,用了沒多久就直接棄用了。
Utterances#
於是換成了另一個基於 GitHub issues 的評論系統 utterances,它會為每篇文章生成一個 issue,用戶通過授權 GitHub 登錄來對 issue 發表評論。這種方式的好處是只需要授權一個 utterances-bot 來進行管理,無需自己部署服務,維護數據庫等。但是用了一段時間後,覺得有幾點不足:
- 基於 GitHub API 進行評論管理,如之後接口變動或對這類利用 issue 進行評論的方式進行限制,會不太穩定
- 讀者必須要授權 GitHub 登錄,非技術人員或使用移動端閱讀的讀者使用起來很不方便
- 會污染 GitHub 倉庫的 Issues 記錄,也不方便後續遷移到其他系統
Cusdis + Supabase + Vercel#
Cusdis 是 Randy 做的一個注重數據隱私的開源的評論系統,十分輕量,經過 gzipped 後大約只有 5kb,從名字來看也知道是難以忍受 Disqus,自己做了一個替代版,因此它也是支持 Disqus 歷史數據導入的,很貼心。
從 2021 年中就開始使用了,到現在整整三年了,除了最開始的時候因為 Heroku、Railway 相繼收費而折騰了一下部署平台外,一直都穩穩地運行著,不過我在使用中也有遇到一些問題:
- 大概是由於微信內置瀏覽器做了一些魔改,在博客從微信聊天 / 對話打開是看不到評論組件的
- 儘管可以輸入郵箱,但並不支持訂閱評論回覆
- 需要管理員手動審核評論,但評論提醒的 TG Bot 時常失效而錯過評論
不過整體來說時至今日依然是十分值得推薦的方案,輕量,方便自部署,風格也簡約好看,搭建教程參看「輕量級開源免費博客評論系統解決方案 (Cusdis + Railway)」。
鑒於 Railway 從去年 8 月起已經取消了 Free Plan,如果依然想完全免費使用,可以使用 Vercel/Netlify/Zeabur 免費部署主項目,並在 Supabase 上部署一個免費的 PostgreSQL 數據庫實例,把鏈接作為環境變量傳入 Cusdis 服務中即可,其他流程大同小異。
另外因為其核心功能已經許久沒有什麼更新,比起其他較為成熟的評論系統也顯得有些簡陋,不過由於我也秉持著夠用即可的原則,一直沒動遷移 / 更新的念頭,只有在其中一陣子在學前端時還參與了一些 Cusdis V2 版本的開發,不過也沒做多久。
由於四月時 Vercel 部署升級的時候一直失敗,導致接近幾周的時間沒收到評論,再加上確實有了一些功能需求,所以下定決心進行遷移,探究起了新的方案。
Remark42 + fly.io#
調研了一圈後選擇了 reorx 在「更換博客評論系統」一文中最後選定的 Remark42。
單純就配置選項來說比起 Cusdis 還是豐富了不少,目前配置了常用的幾種社交賬號登錄(GitHub、Twitter、Telegram、郵箱)、可以匿名評論、支持郵件訂閱回覆提醒並且也設置了 TG bot 提醒,並且部署在 fly.io,go 單二進制 + 數據庫單文件,很舒服的解決方案,更詳細的 Remark42 的介紹和優勢可以參看上面那篇文章。
雖然 Remark42 提供了一些遷移方案,但本身並不支持我使用的 Cusdis,但好在它是用 Golang 寫的,我自己添加了遷移邏輯,將這些年沉澱下來的 438 條評論數據都無縫遷移過來。
Remark42 + fly.io 部署說明#
Remark42 + fly.io 的方案僅牽扯到單個服務,數據庫使用的是 boltdb 掛載於 volume 中,但所有操作都在 fly.io 的 Free Plan 中。
下面將從零開始介紹如何搭建這個免費評論系統。
Remark42 本身代碼開源 —— 「GitHub - umputun/remark42」,並提供了官方維護的鏡像,文檔清晰易讀,可以根據自己的實際需求進行配置。
安裝 flyctl
命令行工具#
fly.io 與我之前使用的 Railway、Zeabur 等很大的一个不同點是它大部分操作基於命令行與配置文件,而不是在網頁端管理後台進行操作,所以首先需要根據文檔安裝 flyctl
命令行工具。
以 macOS 為例,我使用 brew
進行安裝:
brew install flyctl
授權登錄#
打開終端工具,使用以下命令進行授權登錄:
flyctl auth login
在 Web 端進行賬戶登錄或新建賬號,完成後點擊 Continue as xxx
即完成 flyctl
命令行的授權登錄。
創建應用目錄#
由於我通常會手動進行配置管理,而不是用它官方的模板,所以我會新建一個類似 remark42-on-fly
的目錄,並將所有的配置文件、環境變量等放在這個路徑下。
並使用 VS Code 進行編輯(也可以使用 vim 或者其他編輯器 / IDE)。
配置文件#
fly.io 主要是使用 .toml
格式的配置文件進行服務管理,以下是我部署的服務對應的配置文件:
app = 'yu-remark42-01'
primary_region = 'hkg'
[build]
image = 'umputun/remark42:latest'
[[mounts]]
source = 'remark42_data_01'
destination = '/srv/var'
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ['app']
[env]
REMARK_URL = 'https://yu-remark42-01.fly.dev/'
SECRET = 'remark42-secret'
SITE= 'remark42-demo'
ADMIN_SHARED_ID= ''
[[vm]]
cpu_kind = 'shared'
cpus = 1
memory_mb = 256
這是詳細的配置說明:
app
:應用名稱,這裡我使用了yu-remark42-01
,可以根據自己的實際情況進行修改primary_region
:部署區域,可以從這個列表中選擇自己想部署的區域,我選擇了香港[Build]
,這個部分主要是服務鏡像相關的配置image
:服務鏡像,使用了官方提供的umputun/remark42:latest
,如有需要可以指定 tag 版本
[[mounts]]
,這個部分主要是掛載數據卷的配置,由於 Remark42 使用 boltdb 數據庫,需要持久化存儲source
:數據卷名稱,這裡我使用了remark42_data_01
destination
:掛載目錄,這裡我掛載到了/srv/var
,這個目錄是 Remark42 默認的數據存儲目錄
[http_service]
,這個部分主要是服務相關的配置internal_port
:服務內部端口,使用 8080force_https
:強制使用 HTTPSauto_stop_machines
:設置為false
auto_start_machines
:設置為true
,即自動啟動min_machines_running
:最小運行機器數,設置為 1processes
:服務進程,設置為app
[env]
,配置環境變量REMARK_URL
:Remark42 服務的 URL,這裡我使用了https://yu-remark42-demo.fly.dev/
,這是 fly.io 自動生成的,後續如果有了自定義域名則需要更改SITE
:站點名稱,這裡我使用了remark42-demo
SECRET
:自定義的 JWT Token,這裡我使用了remark42-secret
ADMIN_SHARED_ID
:管理員 ID,這裡我使用了空字符串,即沒有管理員,後續可以補充
[[vm]]
,這個部分主要是機器相關的配置cpu_kind
:CPU 類型,設置為shared
cpus
:CPU 數量,設置為 1memory_mb
:內存,設置為 256MB
創建服務#
完成並檢查配置後,運行以下命令進行服務創建:
flyctl launch
環境變量配置#
目前只是部署了服務,並沒有設置環境變量,因此服務啟動會有問題,接下來我們設置環境變量,放在prod.env
文件中:
AUTH_GITHUB_CID=<your_github_cid>
AUTH_GITHUB_CSEC=<your_github_csec>
AUTH_TWITTER_CID=<your_twitter_cid>
AUTH_TWITTER_CSEC=<your_twitter_csec>
AUTH_ANON=true
AUTH_TELEGRAM=true
TELEGRAM_TOKEN=<your_telegram_token>
NOTIFY_ADMINS=telegram
NOTIFY_TELEGRAM_CHAN=<your_telegram_group>
NOTIFY_USERS=email
AUTH_EMAIL_ENABLE=true
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_TLS=true
[email protected]
SMTP_PASSWORD=<your_password>
[email protected]
[email protected]
環境變量的部分相對比較複雜,具體參數參看文檔。
登錄 / 授權配置#
我配置了匿名評論、GitHub、Twitter 與 Telegram 幾種方式,可以根據自己的情況配置其他登錄方式。
- 匿名登錄
AUTH_ANON
:是否允許匿名評論,我選擇了允許,即用戶可以不登錄評論
- GitHub 登錄
AUTH_GITHUB_CID
與AUTH_GITHUB_CSEC
:GitHub OAuth App 的 Client ID 與 Client Secret
- Twitter 登錄
AUTH_TWITTER_CID
與AUTH_TWITTER_CSEC
:Twitter OAuth App 的 Client ID 與 Client Secret
- Telegram 登錄
AUTH_TELEGRAM
:是否允許 Telegram 登錄TELEGRAM_TOKEN
:Telegram Bot Token,通過botfather
創建
- 郵箱登錄
AUTH_EMAIL_ENABLE
:是否允許郵箱登錄AUTH_EMAIL_FROM
:郵箱登錄的發送郵箱
通知配置#
- Telegram 通知管理員,參看文檔這部分進行 Telegram Bot 的創建和配置
NOTIFY_ADMINS
:通知管理員的方式,選擇 telegramNOTIFY_TELEGRAM_CHAN
:如啟用 telegram 通知管理員,需要配置對應 Channel id,只需要填寫t.me/xxx
後面的 id 部分即可,如pseudoyuchat
- Email 通知用戶,參看文檔這部分進行郵箱 SMTP 等配置
NOTIFY_USERS
:通知用戶的方式,我選擇了 email, 即郵件通知,則需要配置下文的 SMTPNOTIFY_EMAIL_FROM
:郵箱通知的發送地址
郵件 SMTP 配置#
上文的郵箱登錄與郵箱通知都需要配置 SMTP 伺服器,這部分也可以根據自己的郵箱服務商參照文檔進行配置。
SMTP_HOST
:SMTP 伺服器地址SMTP_PORT
:SMTP 伺服器端口SMTP_TLS
:是否啟用 TLSSMTP_USERNAME
:SMTP 用戶名SMTP_PASSWORD
:SMTP 密碼
導入環境變量到服務#
根據以上說明完成環境變量配置後,在配置文件和環境變量文件所在目錄運行以下命令導入環境變量:
fly secrets import < prod.env
執行完成後到 fly.io 控制台查看服務狀態即可,如為 Deployed
狀態即表示部署成功。
配置自定義域名(可選)#
如果你不想使用 fly.io 提供的默認域名,可以配置自定義域名。
進入 fly.io 控制台,選擇剛部署的 yu-remark42-01
服務,點擊左側的 Certificates
選項,然後點擊右上角 Add a Certificate
,按照提示添加自定義域名即可。
點擊 Create Certificate
後,會有一個頁面顯示你所需要添加的 DNS 記錄,按照提示添加即可。
例如我的域名托管在 Cloudflare,我按照提示添加了兩條 DNS 記錄,返回頁面後點擊 Check again
或等待一段時間後刷新查看,都顯示綠色即為配置成功。
此時,我們可以在 fly.toml
中修改 REMARK_URL
為自定義域名,然後執行以下命令重新部署服務即可,之後對配置文件進行任何改動都可以使用該命令進行更新:
fly deploy
博客配置 Remark42#
上文我們完成的 Remark42 服務的部署,現在則需要在我們的博文中加入 Remark42 評論組件,以我使用的 Hugo 博客為例。
定義 Hugo 主題 Comments 組件#
我在 Hugo 博客的 layouts/partials
目錄下新建了一個 comments.html
文件,用於定義 Remark42 評論組件:
<div class="comments">
<div class="title">
<span>Comments</span>
<span class="counter"><span class="remark42__counter" data-url="{{ .Permalink }}"></span></span>
</div>
<div id="remark42">
</div>
</div>
<script>
var remark_config = {
host: 'https://comments.pseudoyu.com',
site_id: 'pseudoyu.com',
components: ['embed', 'counter'],
max_shown_comments: 20,
simple_view: true,
theme: 'light',
}
</script>
<script>
(function () {
// init or reset remark42
const remark42 = window.REMARK42
if (remark42) {
remark42.destroy()
remark42.createInstance(remark_config)
} else {
for (const component of remark_config.components) {
var d = document, s = d.createElement('script');
s.src = `${remark_config.host}/web/${component}.mjs`;
s.type = 'module';
s.defer = true;
// prevent the <script> from loading mutiple times by InstantClick
s.setAttribute('data-no-instant', '')
d.head.appendChild(s);
}
}
})();
</script>
remark_config
中的 host
與 site_id
需要根據自己的實際配置進行修改,其他部分配置可以保持不變,或根據文檔進行調整。
配置好 commnets
組件後,在 layouts/posts/single.html
中文章底部引入:
{{ partial "comments.html" . }}
大體位置如圖所示,如使用的是其他主題或博客系統,則需要找到自己文章對應的模板文件進行修改。
本地預覽 / 部署網站#
此時可以在本地預覽或部署網站以查看評論系統是否正常顯示,至此我們的服務部署完成。
獲取 User ID 並配置 Admin#
登錄授權完成後並測試評論後,可在 Remark42 中點擊頭像打開管理頁面,雙擊後 CMD/Ctrl+C
可以獲取以 github_
或其他平台開頭的 User ID,可以將其配置到 ADMIN_SHARED_ID
中(更改 fly.toml
配置文件並運行 fly deploy
重新部署,即可成為管理員,管理員有權限對其他用戶的評論進行刪除等管理操作。
其他#
我把之前 Cusdis 中的評論數據按照一定條件導出 json 格式的數據,並通過 go 程序進行格式轉換與遷移,因此保留了之前所有的評論。
因為 Cusdis 本身不提供導出功能且遷移的需求太過小眾,我並沒有直接向上游貢獻代碼,也沒有寫成完善的腳本,有類似需求的朋友可以參考這個 PR 進行處理 —— 「feat: add cusdis to remark42 migrator support by pseudoyu · Pull Request #1 · pseudoyu/remark42」。
總結#
以上就是我的博客評論系統的搭建過程,評論系統的搭建與配置相對繁複,且本文的配置方式或許會隨著時間而過時,遇到問題可多參照官方文檔。
這是我的博客搭建部署系列教程之一,如對數據統計系統、博客內搜索等搭建感興趣,請持續關注,希望能對大家有所參考。