在 Linux Server 建置 Token Monitor Hub 與 systemd 背景服務
文件日期:2026-08-13
適用情境:以一台持續開機的 Linux Server 作為 Token Monitor Hub,並讓沒有桌面介面的 Linux 主機以 headless agent 回報 Codex 等工具的用量。
本文以 Ubuntu/Debian 類系統與一般使用者帳號為例;所有路徑請換成自己的實際位置。
Token Monitor 是一個本機優先的 AI 工具用量監控器。它可讀取 Codex、Claude Code、Cursor、OpenCode 等工具留在本機的紀錄;在多裝置模式下,每台裝置只處理自己的資料,再將彙整結果送往 Hub。Hub 會把最新的彙整狀態推送給已連線的桌面 widget。
這篇文章建立的架構如下:
Linux agent(讀取 ~/.codex 等本機資料) ──┐ 桌面 Token Monitor widget ─────────────────┼──> Token Monitor Hub ──> 所有已連線 widget 其他裝置的 agent/widget ──────────────────┘
Token Monitor 不會把 prompt、回應內容或原始程式碼同步到 Hub;同步的是用量彙整資料。仍請把 Hub 與 shared secret 視為內部服務來保護。
先決定哪些主機需要跑什麼
Hub 與 agent 的角色不同:
- Hub:集中接收與彙整資料;適合放在持續開機、網路穩定的主機上。
- Headless agent:掃描「該台主機、該登入帳號」的本機紀錄並上傳到 Hub。
- 桌面 widget:已有 Token Monitor 桌面程式的裝置不必另外跑 agent;在設定頁選擇 Connect to a hub 即可自動回報。
因此,若這台 Linux Server 只用來提供 Hub,只需要建立 Hub service;若它自己也執行 Codex CLI,則再建立 agent service。agent 預設可追蹤所有支援的工具;本文示範只追蹤 Codex。
1. 準備 Node.js 與專案
Token Monitor 原始碼建置需要 Node.js 22.13 以上。先確認版本,再以要執行 service 的同一個帳號下載與安裝專案:
node --version git clone https://github.com/Javis603/token-monitor.git ~/TokenMonitor/token-monitor cd ~/TokenMonitor/token-monitor npm install cp .env.example .env
若 node --version 低於需求,先升級 Node.js 後再進行。使用 nvm 沒有問題,但後面的 service 必須明確使用 nvm 安裝的 Node 路徑;systemd 不會讀取互動 shell 的 .bashrc 或 .zshrc。
在專案根目錄建立一組 shared secret:
openssl rand -hex 32 nano .env
至少填入:
# Hub 與所有連線裝置都要使用完全相同的值。 TOKEN_MONITOR_SECRET=請貼上剛產生的隨機字串 # 僅當本機也要作為 agent 上傳資料時才需要。 TOKEN_MONITOR_HUB_URL=http://127.0.0.1:17321 TOKEN_MONITOR_DEVICE_ID=linux-server-01 TOKEN_MONITOR_CLIENTS=codex
TOKEN_MONITOR_DEVICE_ID 可省略,預設會使用主機名稱。TOKEN_MONITOR_CLIENTS 也可省略以追蹤所有支援工具;設為 codex 則可減少不需要的掃描。完整可用的環境變數以專案的 .env.example 為準。
.env包含 secret,請勿提交至 Git,也不要把它貼到 issue、聊天室或截圖中。
2. 先以前景模式驗證 Hub
啟動 Hub:
cd ~/TokenMonitor/token-monitor npm run hub
另開一個 shell,在同一台主機測試 health endpoint:
curl http://127.0.0.1:17321/api/health
確認回應正常後,按 Ctrl+C 停止前景程序。接著在桌面版 Token Monitor 的 Settings → Multi-device Sync → Connect to a hub,填入 Hub 的可達 URL 與同一組 secret。
若透過 Tailscale、ZeroTier 或公司內網連線,填入該網路上的網址,例如 http://100.x.y.z:17321。不要使用 127.0.0.1,因為它只代表「目前這台」電腦。
3. 將 Hub 設為 systemd user service
先查出 service 需要的實際 Node/npm 路徑:
command -v node command -v npm
下列範例假設 nvm 的 Node 24 位於 /home/icebird/.nvm/versions/node/v24.15.0/bin,專案放在 /home/icebird/TokenMonitor/token-monitor。請按自己的帳號、Node 版本與專案路徑調整:
mkdir -p ~/.config/systemd/user nano ~/.config/systemd/user/token-monitor-hub.service
[Unit] Description=Token Monitor Hub After=network-online.target Wants=network-online.target [Service] Type=simple WorkingDirectory=/home/icebird/TokenMonitor/token-monitor Environment=NODE_ENV=production Environment=PATH=/home/icebird/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ExecStart=/home/icebird/.nvm/versions/node/v24.15.0/bin/npm run hub Restart=on-failure RestartSec=10 [Install] WantedBy=default.target
啟用並立刻啟動:
systemctl --user daemon-reload systemctl --user enable --now token-monitor-hub systemctl --user status token-monitor-hub
--user service 預設會隨使用者 session 結束而停止。讓它在 SSH 登出後及重新開機後仍可執行:
sudo loginctl enable-linger "$USER"
查看即時日誌:
journalctl --user -u token-monitor-hub -f
4. 讓 Linux 主機也回報自己的 Codex 用量(選用)
若這台 server 的同一個使用者帳號會執行 Codex CLI,agent 才能讀到其 ~/.codex/ 內的 session 紀錄。先以前景模式確認能連上 Hub:
cd ~/TokenMonitor/token-monitor npm run agent
成功後建立 agent service:
nano ~/.config/systemd/user/token-monitor-agent.service
[Unit] Description=Token Monitor headless agent After=network-online.target token-monitor-hub.service Wants=network-online.target [Service] Type=simple WorkingDirectory=/home/icebird/TokenMonitor/token-monitor Environment=NODE_ENV=production Environment=PATH=/home/icebird/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ExecStart=/home/icebird/.nvm/versions/node/v24.15.0/bin/npm run agent Restart=on-failure RestartSec=10 [Install] WantedBy=default.target
套用設定:
systemctl --user daemon-reload systemctl --user enable --now token-monitor-agent systemctl --user status token-monitor-agent journalctl --user -u token-monitor-agent -f
若 agent 位於另一台主機,將那台機器 .env 的 TOKEN_MONITOR_HUB_URL 改成 Hub 的內網或 overlay-network URL,並填入相同的 TOKEN_MONITOR_SECRET;agent service 其他設定相同。不要在 agent 主機執行 npm run hub,除非它也要作為一個獨立 Hub。
5. nvm 與 systemd 使用錯誤 Node 版本的排查
常見症狀是 service 的 ExecStart 指向 nvm 的 npm,但日誌仍顯示舊版系統 Node,例如 Node.js v18.x,並伴隨相依套件載入失敗。
原因是 npm 的啟動流程仍會從 PATH 尋找 node,而 systemd 不會載入你的 nvm shell 設定。解法就是 service 同時指定:
ExecStart使用 nvm 目錄中的絕對npm路徑。Environment=PATH=...並把同一個 nvmbin目錄放在最前面。
修改 unit 後必須重新載入並重啟:
systemctl --user daemon-reload systemctl --user restart token-monitor-agent journalctl --user -u token-monitor-agent -n 50 --no-pager
確認日誌中不再出現舊版 Node。若專案不使用 nvm,則把範例中的 nvm 路徑換成 command -v npm 的實際結果,並讓 PATH 優先找到同一套 Node。
6. 網路與維運建議
- 優先使用內網、Tailscale 或 ZeroTier。 這通常比直接公開 TCP port 17321 安全且易於管理。
- 若必須跨公開網路連線,請放在 Nginx 或 Caddy 等 reverse proxy 後方,以 HTTPS、嚴格防火牆規則及強 secret 保護;不要直接把 Hub port 裸露到網際網路。
- Hub、agent 與每個同步 widget 的
TOKEN_MONITOR_SECRET必須一致。更換 secret 時,所有客戶端都要同步更新。 - 升級時先停止 service,更新程式與相依套件,再啟動:
cd ~/TokenMonitor/token-monitor systemctl --user stop token-monitor-hub token-monitor-agent git pull npm install systemctl --user start token-monitor-hub token-monitor-agent
- 定期以
systemctl --user status與journalctl --user -u <service>檢查狀態;若有可用性監控系統,也可以定期查詢/api/health。
完成檢查表
- Hub service 顯示
active (running)。 curl http://127.0.0.1:17321/api/health回應正常。- 每台同步裝置的 Hub URL 正確,且使用相同 shared secret。
- 需要回報 Linux 本機用量的主機,agent service 顯示
active (running)。 - SSH 登出與主機重新啟動後,service 仍會自動恢復。
官方設定細節可參考 Configuration 與 Token Monitor README。