系列最後一篇,把 claude_linebot 從零部署起來:申請 LINE channel、設定 .env、用 Cloudflare Tunnel 把本機 webhook 掛上公網(quick tunnel 與 named tunnel 兩種),最後註冊成 macOS LaunchAgent 開機自動跑。(前情提要:動機、架構)
前置需求
- macOS(防睡眠用
caffeinate;Windows 也能跑,自動走 Win32 分支) - Python 3.10+
- 已安裝、登入完成的
claudeCLI - LINE Messaging API channel(下面申請)
cloudflared(brew install cloudflared)
LINE 是 webhook 模式——LINE 的伺服器要能主動連到你的電腦,所以需要一個公開 HTTPS 網址。Cloudflare Tunnel 用一條 outbound 連線解決這件事:不開防火牆 port、不需要固定 IP。
一、申請 LINE channel
- 到 LINE Developers Console 建立 Provider(沒有的話)
- 建立 Messaging API channel
- 記下兩樣東西:Channel secret(Basic settings 分頁)和 Channel access token(Messaging API 分頁,按 Issue)
二、設定並啟動 bot
1 | git clone https://github.com/murmur-wu/claude_linebot.git ~/claude/lineBot |
.env 至少填:
1 | LINE_CHANNEL_SECRET=... |
啟動(首次會自動建 .venv、裝套件):
1 | ./start.sh |
專案路徑建議放
~/claude/這類一般目錄。放在~/Desktop、~/Documents、~/Downloads的話,之後服務化會撞上 macOS 的保護目錄限制(見最後一節)。
三、Cloudflare Tunnel
先用 quick tunnel 打通流程
1 | ./tunnel.sh # 會印出 https://xxxx.trycloudflare.com |
quick tunnel 不用註冊、不用網域,適合驗證整條流程。缺點是網址每次重啟都會變,變了就要回 Console 更新 Webhook URL——所以打通後建議直接升級 named tunnel。
設定 Webhook URL
LINE Developers Console → 你的 channel → Messaging API 分頁:
- Webhook URL 填
https://xxxx.trycloudflare.com/callback - Use webhook 打開
- Auto-reply messages 關掉(不然官方罐頭回覆會跟 bot 打架)
- 按 Verify → 應該回 Success
拿白名單 id
用手機加 bot 好友、傳任意訊息,bot 會直接回你的 userId(一串 U 開頭 33 字)。填進 .env 的 ALLOWED_USER_IDS,./restart.sh 重啟。這是 fail-closed 設計:名單空著時 bot 拒絕所有人,不存在「忘了設定所以全開」的狀態。
升級 named tunnel(固定網址)
前提:你有一個網域託管在 Cloudflare(免費方案即可)。
1 | cloudflared tunnel login # 瀏覽器授權,選你的 zone |
建立 ~/.cloudflared/config.yml:
1 | tunnel: linebot |
把 DNS 指到 tunnel、再啟動:
1 | cloudflared tunnel route dns --overwrite-dns linebot linebot.example.com |
回 Console 把 Webhook URL 改成 https://linebot.example.com/callback,Verify 一次。從此網址固定,重啟也不用再碰 Console。
安全上的細節:bot 的 HOST 預設綁 127.0.0.1,只有 tunnel 進得來,不對區網開放;webhook 已內建 X-Line-Signature HMAC 驗簽,驗不過直接 400。
四、日常操作
1 | ./restart.sh # 改完 .env 重啟(自動判斷 launchd / nohup 模式) |
重啟不會斷對話——session_id 存在 state/sessions.json。改 .env 不用重啟 tunnel(除非改了 PORT)。
五、開機自動啟動(LaunchAgent)
1 | ./services/install-service.sh # 註冊 bot 與 tunnel 兩個 LaunchAgent |
用的是使用者層的 LaunchAgent 而不是系統層的 LaunchDaemon——原因跟 Windows 版不能用 LocalSystem 一樣:claude CLI 的認證在 ~/.claude/,以 root 跑找不到。代價是「登入後」才啟動;要真正開機即跑,到系統設定開自動登入。
macOS 保護目錄的坑
如果專案放在 ~/Desktop、~/Documents、~/Downloads(TCC 保護目錄),launchd 會遇到一連串限制:不能 chdir 進去、不能直接 exec 裡面的執行檔、不能開啟由 Terminal 建立的既有 log 檔——而且失敗時只給 exit code 78 (EX_CONFIG),零錯誤輸出,極難排查。
最陰險的是第三項:你先用 ./start.sh 手動跑過,state/bot.log 的存取權歸屬 Terminal;改成服務後 launchd 開不了那個檔案,服務永遠起不來。
install-service.sh 已經把能繞的都繞了(不設 WorkingDirectory、透過 /bin/sh -c 'exec …' 啟動、自動把舊 log 改名),但「launchd 啟動的程序讀取保護目錄檔案」這關必須手動授權:系統設定 → 隱私權與安全性 → 完全磁碟取用權 → 加入 <專案>/.venv/bin/python。
不想開這麼大的權限?把專案移出保護目錄(例如 ~/claude/lineBot)就完全不需要任何授權——這也是本文開頭建議 clone 到 ~/claude/ 的原因。
常見坑速查
| 症狀 | 原因 |
|---|---|
| Console 按 Verify 回 504 | tunnel 沒跑,或 ingress 沒指到 bot。先 curl 127.0.0.1:8000/healthz 確認本機活著 |
| 自己的測試腳本收到 403 | Cloudflare 擋部分 User-Agent(如 Python-urllib),換個 UA 就好,LINE 本身不受影響 |
| userId 填了還是被拒 | LINE userId 固定 33 字,手抄常漏字——直接從 state/bot.log 的 rejection log 複製 |
| 群組裡 bot 完全沒反應 | 依序查:ALLOW_GROUPS=true 且重啟過、訊息帶 claude 前綴、發話者在白名單 |
改 .env 沒生效 |
bot 不會自動重讀設定,要 ./restart.sh |
| LaunchAgent exit 78 且無 log | 保護目錄問題,見上一節 |
系列回顧
- 第一篇:動機——為什麼是 LINE,三大平台難題
- 第二篇:架構——webhook 管線、回覆經濟學、兩段式附件
- 本篇:部署——LINE channel、Cloudflare Tunnel、LaunchAgent
到這裡,家裡的 Mac 就成了一台隨身可指揮的開發機:LINE 傳個訊息,Claude Code 改 code、跑指令、commit,結果回到手機上。