安裝與升級疑難排解
安裝程式中斷、升級沒生效,或服務起不來時該怎麼辦。直接搜尋錯誤訊息原文 —— 這裡的每一條都對應安裝程式裡真實存在的失敗路徑,或某個版本實際改變的行為。
從這裡開始
安裝程式中斷了,我該先看哪裡?
安裝程式會印出一行紅色的 ✗,指出失敗的原因。用那一行的文字在本頁搜尋。
如果安裝完成但服務不正常,下一個要看的是服務自己的記錄:
sudo journalctl -u jt-proxense -n 50 --no-pager
確認實際裝上的版本:
jt-proxense version安裝失敗
This installer must run as root
一鍵安裝需要 sudo。它會建立系統帳號、寫入 systemd unit,並安裝到
/opt 底下。
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
注意 sudo 要加在 bash 上,不是加在 curl 上。
No supported package manager (apt / dnf / yum / pacman / zypper) found
安裝程式透過這五種其中之一來裝系統套件。如果你的發行版不在其中,請先手動裝好 前置需求再重跑一次 —— 已經存在的它會略過:
git、python3 (3.10 以上)、python3-pip、python3-venv、systemdPython 3.10+ required (found ...)
最常見於 RHEL/Rocky/AlmaLinux 8,它們的 python3 是 3.6:
sudo dnf install python3.11 python3.11-pip
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
安裝程式會挑它找到的最新直譯器,並讓 systemd unit 指向它,所以你不需要改系統預設值。
/opt/jt-proxense is non-empty but not a git checkout. Refusing to overwrite.
目標目錄裡已經有東西,而且不是安裝程式放的 —— 可能是舊的手動複本,或解壓縮出來的 檔案。它選擇拒絕,而不是刪掉你的檔案。
把它移開再重跑:
sudo mv /opt/jt-proxense /opt/jt-proxense.old
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
或是裝到別的位置:
curl -fsSL … | sudo JT_PROXENSE_INSTALL_DIR=/opt/jtp bash
你的資料不在那個目錄裡 —— 使用者、稽核記錄與設定放在
/var/lib/jt-proxense 與 /etc/jt-proxense,不會受影響。
Smoke test failed — a runtime module did not import
Python 相依套件裝好了,但其中一個載入不了。失敗訊息上一行會指出確切的模組名稱, 然後:
sudo python3 -m pip install --upgrade -r /opt/jt-proxense/requirements.txt
sudo systemctl restart jt-proxense
在 Debian 12 以上/Ubuntu 24.04,系統的 Python 環境被標記為 externally managed
(PEP 668)。安裝程式會自動偵測並加上 --break-system-packages;如果你是
手動安裝,需要自己加同一個旗標。
git clone 或 curl 失敗/主機連不到 GitHub
安裝程式需要連到 github.com 與
raw.githubusercontent.com。在 proxy 後面的話,要把它匯出給整條指令
—— 只設在你自己 shell 裡的 proxy 傳不進 sudo 的環境:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh \
| sudo https_proxy=http://proxy:3128 bash
完全離線的主機,請在別處 clone 下來,複製到 /opt/jt-proxense,
然後在裡面執行 install.sh。
升級失敗
要怎麼升級?git pull 就夠了嗎?
重跑同一行安裝指令。它是冪等的,而且它就是升級路徑:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
單純 git pull 不夠。 它只抓程式碼,不會重新安裝
systemd unit、不會更新 Python 相依套件,也不會套用檔案擁有者與權限的修復 ——
結果是新程式跑在舊的 unit 底下。如果你已經這樣做了,事後補跑一次一鍵指令即可,
其餘它會修好。
安裝程式會裝哪一版?可以指定嗎?
從 v1.1.0 起,它安裝的是最新的發行標籤,而不是 main 的頂端 ——
所以同一行指令在不同兩天執行會得到相同的程式,而且有東西可以回滾。
指定特定版本,或刻意追開發分支:
# 指定某一個發行版
curl -fsSL … | sudo JT_PROXENSE_REF=v1.1.0 bash
# 追開發分支
curl -fsSL … | sudo JT_PROXENSE_REF=main bashYour local changes would be overwritten/dubious ownership
安裝程式會把 checkout 重設到它要安裝的那個版本,所以在
/opt/jt-proxense 裡面的修改是刻意被丟棄的。要保留的設定請放在
config.yaml,那個檔案永遠不會被覆寫。
如果 git 回報 detected dubious ownership,那是因為 checkout 屬於 root (v1.1.0 起刻意如此 —— 服務不該能修改自己的程式碼)。用 root 執行 git,或交給安裝 程式處理:
sudo git -C /opt/jt-proxense status它說升級完成了,但畫面還是舊版本
先確認伺服器實際跑的是什麼:
jt-proxense version
sudo systemctl status jt-proxense --no-pager | head -5
如果那已經是新版,就是瀏覽器還留著舊的 index.html。頁面會偵測到過期的
bundle 並自己重新載入,但強制重新整理可以立刻解決:
Ctrl+Shift+R
(macOS 是 ⌘+Shift+R)。
要怎麼回滾到前一個版本?
安裝先前的標籤即可。你的資料庫與設定在安裝目錄之外,不會被動到:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh \
| sudo JT_PROXENSE_REF=v1.1.0 bash
資料庫 migration 是單向的。跨過有新增 migration 的版本回滾並不支援 —— 如果你想保留
退路,請在重大升級前先複製一份
/var/lib/jt-proxense/jt-proxense.db。
服務起不來
REFUSING TO START: config.yaml could not be parsed
這個檔案不是合法的 YAML。daemon 選擇拒絕啟動,而不是退回預設值,因為那些預設值會 把驗證關掉並綁定所有介面 —— 一個壞掉的檔案絕對不該安靜地把執行個體打開。
還原上一次變更前自動留下的副本:
ls -lt /opt/jt-proxense/config_backups/
sudo cp /opt/jt-proxense/config_backups/config_YYYYMMDD_HHMMSS.yaml \
/opt/jt-proxense/config.yaml
sudo chown jt-proxense:jt-proxense /opt/jt-proxense/config.yaml
sudo chmod 600 /opt/jt-proxense/config.yaml
sudo systemctl restart jt-proxense
這一版不認識的設定欄位不算錯誤 —— 從 v1.1.1 起它會被忽略,並在記錄中具名警告, 周圍的設定都會保留。
systemd: Failed to start/unit 因 ReadWritePaths 失敗
從 v1.1.0 起,unit 會逐一列出可寫入的路徑,而 systemd 會拒絕啟動
ReadWritePaths 指向不存在路徑的 unit。重跑安裝程式就會建立它們:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
那些路徑是 /opt/jt-proxense/config.yaml、
/opt/jt-proxense/config_backups、
/opt/jt-proxense/.ssh、/var/lib/jt-proxense 與
/etc/jt-proxense。會發生這個狀況,通常是 unit 被手動更新而不是透過
安裝程式。
Address already in use/連接埠 8098 被占用
先找出是誰占住的,然後停掉它或改用別的連接埠:
sudo ss -tlnp | grep 8098
要改的話,編輯 /opt/jt-proxense/config.yaml 裡的
server.http_port 再重啟。全新安裝可以一開始就指定:
curl -fsSL … | sudo JT_PROXENSE_PORT=8099 bash頁面載入了,但沒有樣式、版面整個擠成一直排
瀏覽器拿到了 JavaScript 卻沒拿到樣式表,通常是手動複製檔案之後,服務帳號讀不到 那些檔案:
sudo chmod 644 /opt/jt-proxense/dist/index.html \
/opt/jt-proxense/dist/assets/index-*.js \
/opt/jt-proxense/dist/assets/index-*.css
sudo systemctl restart jt-proxense
重跑安裝程式也會修好,而且更安全。
從介面新增叢集時存不起來
服務會寫入 config.yaml 並且先備份一份,所以兩者都必須是服務帳號可寫。
用 root shell 的重導向去改那個檔案會改變它的擁有者:
sudo chown jt-proxense:jt-proxense /opt/jt-proxense/config.yaml
sudo chmod 600 /opt/jt-proxense/config.yaml
sudo chown -R jt-proxense:jt-proxense /opt/jt-proxense/config_backups
sudo systemctl restart jt-proxense無法登入
Too many attempts, please try again later
那個 IP 觸發了登入速率限制:五分鐘內失敗五次。冷卻時間過後會自己解除,或是立即解除:
sudo jt-proxense unlock # 列出目前被鎖的
sudo jt-proxense unlock --all # 解除全部鎖定
這只會清掉計數器,永遠不會更動任何密碼。
忘記 admin 密碼,或是驗證器裝置遺失
CLI 在服務沒有執行的情況下也能用 —— 它存在的目的就是這個:
sudo jt-proxense reset-password admin
sudo jt-proxense user reset-totp admin驗證設定弄錯之後完全被關在外面
先把驗證關掉,修好設定,再打開:
sudo jt-proxense auth disable # 同時只綁定 127.0.0.1
sudo systemctl restart jt-proxense
之後用 sudo jt-proxense auth set-local 重新啟用。
升級到 v1.1.0 之後
所有人在幾次登入失敗後一起被鎖住
升級後最容易遇到的意外。X-Forwarded-For 現在只有來自 loopback 或你
明確指定的位址才會被採信。如果你的反向代理跑在另一台主機上,現在每個請求都帶著
代理的位址,所有使用者因此共用同一個速率限制計數 —— 任何人登入失敗五次,所有人一起被
鎖十五分鐘。稽核記錄也會把代理記成來源。
在 /opt/jt-proxense/config.yaml 裡指定你的代理:
auth:
trusted_proxies:
- 192.0.2.10 # 也可以用 CIDR:192.0.2.0/24
然後 sudo systemctl restart jt-proxense 並執行
sudo jt-proxense unlock --all。發生這個狀況時,記錄裡會對每個來源出現一次
ignoring X-Forwarded-For from …。
從其他來源提供的介面在升級後失效
從 v1.1.0 起,跨來源存取預設關閉。如果你的 SPA 與 API 在不同的主機或連接埠, 請指定該來源:
server:
cors_origins:
- https://ui.example.net
填 * 會被刻意忽略:萬用字元加上憑證,等於你瀏覽過的任何網站都能用你的
工作階段操作這個 API。
如果介面與 API 同源(預設就是如此,因為程式自己提供 SPA),你完全不需要設定這個。
記錄裡出現 ignoring unrecognised setting(s)
這是資訊性訊息。你的 config.yaml 裡有這一版不認識的欄位 —— 通常是打錯
字,或是來自其他版本的選項。該欄位會被忽略,其餘設定照常生效;請對照
config.example.yaml
檢查拼字。
在 v1.1.1 之前,這會讓服務起不來。如果你在 v1.1.0 而 daemon 因為某個關鍵字參數拒絕 啟動,請升級。
先前被拒絕的「單一叢集角色」使用者,現在可以用了
這是預期行為。在 v1.1.0 之前,角色檢查只讀全域 (*) 授權,所以
jt-proxense user grant bob cluster1 operator 在入口處被忽略了。現在它在
該叢集底下的端點會生效。只授予單一叢集的角色,仍然不適用於使用者管理與全域設定。
檢視目前的授權:
sudo jt-proxense user list解除安裝
要怎麼完整移除?
一行。它會停止並停用服務,然後刪除安裝目錄、
/var/lib/jt-proxense(使用者、稽核記錄、叢集密鑰)、
/etc/jt-proxense(主金鑰)以及服務帳號:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/uninstall.sh | sudo bash
它會先要你輸入 remove。在自動化流程裡加 --yes 跳過:
… | sudo bash -s -- --yes。
這是不可逆的。 只要還有一點可能想把執行個體找回來,請先匯出 —— 見下一條。
想移除但保留設定和使用者
解除安裝前先匯出。這個封裝包含 config.yaml、SQLite 資料庫
(使用者、角色、稽核記錄、備註)以及能解密叢集密鑰的主金鑰,全部在一個以通關密語
加密的檔案裡:
sudo jt-proxense export-config /root/jt-proxense-backup.enc
把它複製到主機之外,然後再解除安裝。要在任何機器上還原:
curl -fsSL https://raw.githubusercontent.com/jasoncheng7115/jt-proxense/main/install.sh | sudo bash
sudo systemctl stop jt-proxense
sudo jt-proxense import-config /root/jt-proxense-backup.enc --force
sudo systemctl restart jt-proxense
這個封裝裡有主金鑰,請當成憑證看待,匯入完成後就刪掉它。
解除安裝程式回報:run as root 或 no terminal for confirmation
它需要 sudo,理由和安裝程式一樣。第二種訊息代表它是被管線呼叫的,
沒有終端機可以讀你的確認,這正是 --yes 的用途:
curl -fsSL … /uninstall.sh | sudo bash -s -- --yes解除安裝後還有殘留
解除安裝程式容許缺件,所以不完整的狀態用同樣的指令手動執行即可清乾淨:
sudo systemctl stop jt-proxense; sudo systemctl disable jt-proxense
sudo rm -f /etc/systemd/system/jt-proxense.service /usr/local/bin/jt-proxense
sudo systemctl daemon-reload
sudo rm -rf /opt/jt-proxense /var/lib/jt-proxense /etc/jt-proxense
sudo userdel jt-proxense
如果你裝在別的位置,請代換該路徑 —— 解除安裝程式同樣會遵循
JT_PROXENSE_INSTALL_DIR。
還是卡住
這裡沒有符合的狀況,要怎麼回報?
開一個 issue,附上足以重現問題的資訊:
jt-proxense version
cat /etc/os-release | head -2
python3 -V
sudo journalctl -u jt-proxense -n 100 --no-pager
貼上之前請先遮蔽 PVE 主機名稱與 API token。絕對不要原封不動貼出
config.yaml —— 裡面有憑證。
沒有符合的條目。試試看少打幾個字,或是 開一個 issue.