Bucket & Code Server IDE 使用指南
Bucket & Code Server IDE(QPKG bucketvs)在 QNAP NAS 上保存原始碼與檔案,並在 NAS 上建置軟體。它自帶網頁伺服器、工具與帳號。
本指南說明套件在 NAS 上執行時的樣子。
目錄
- NAS 上執行的元件
- 安裝套件
- 第一次登入
- 在面板中工作
- 帳號
- 資料目錄
- 網路
- 在反向 Proxy(Plesk)後方
- 模組的主機名稱
- 發佈到網際網路(Cloudflare Tunnel)
- 模組
- Git
- CI runner
- SVN 與 Bucket
- 編輯器與 AI 工具
- 工具鏈與環境
- App Builder
- 套件儲存庫
- 核心工坊
- cron 工作與操作
- 備份
- 通知
- 記錄與支援資料包
- 更新
- bvs 指令
- 檔案與資料夾
NAS 上執行的元件
| 元件 | 功能 | 接聽位置 |
|---|---|---|
| nginx | 區域網路上唯一的入口:提供面板,並把每個路徑轉交給對應的模組 | 9950(HTTP)、9951(HTTPS) |
| bvsd | 啟動並監看其他所有程序,保存帳號與設定,執行工作與 cron 工作,回應面板 | /usr/bin/bucketvs/var/run/ 中的兩個 Unix socket |
| Git(Forgejo) | 附網頁介面的 Git 代管服務 | /usr/bin/bucketvs/var/run/forgejo/ 中的一個 Unix socket,以及透過 SSH 使用 Git 的 9952 |
| SVN 與 Bucket(httpd) | Subversion 儲存庫與具備歷史記錄的 WebDAV 資料夾 | 127.0.0.1:9961;其他程式占用時改用下一個可用連接埠 |
| 編輯器(code-server) | 在瀏覽器中執行的 VS Code,每個帳號一個執行個體 | /usr/bin/bucketvs/var/run/ide/ 中每個帳號各一個 Unix socket |
| CI | Forgejo Actions runner | 沒有自己的連接埠;模組開啟時,nginx 在 127.0.0.1:9960 為它接聽,其他程式占用 9960 時改用下一個可用連接埠 |
核心(nginx、bvsd、面板、cron 工作、工具鏈)一律開啟。Git、CI、SVN 與 Bucket、編輯器是由管理員開啟或關閉的模組。在 NAS 的每個位址上,各模組都在自己的路徑下回應:/git/、/svn/、/bucket/、/ide/。面板位於 /,本指南位於 /guide/。
套件執行期間,其程式位於 /usr/bin/bucketvs/bin。套件保存的一切(帳號、設定、儲存庫、環境、記錄)都放在資料磁碟區上的一個資料夾中,也就是資料目錄。
安裝套件
套件需要 QTS 6.0 或 QuTS hero 6.0 以上版本,以及 x86_64 或 ARM 64 位元的 NAS;每種架構各有一個套件(bucketvs_<版本>_x86_64.qpkg、bucketvs_<版本>_arm_64.qpkg)。套件具有程式碼簽署:請從 App Center 安裝(從列出它的儲存庫,或以下載的檔案使用 手動安裝)。App Center 會檢查簽署,不需要允許沒有有效簽署的應用程式。
安裝時會建立服務使用者 bucketvs(供 Forgejo 與 httpd 使用)、指向安裝資料夾的連結 /usr/bin/bucketvs,並啟動 bvsd。系統記錄會寫明資料目錄。
資料目錄的初始位置
第一次啟動時,資料目錄是套件所在磁碟區上的 BucketVS,例如 /share/CACHEDEV1_DATA/BucketVS(QTS)或 /share/ZFS2_DATA/BucketVS(QuTS hero)。之後可以從面板把它搬到其他磁碟區(搬移資料目錄)。
套件把資料目錄記在 /etc/config/bucketvs-data-root,這個檔案在移除套件後仍會保留。移除套件時,資料目錄與這個檔案都會保留,因此移除後重新安裝,會以相同的資料與相同的帳號啟動。啟動絕不依賴不存在的資料夾。當資料目錄已不存在(已被刪除、所在的硬碟已更換,或所在的磁碟區當時離線)時,啟動會在套件所在磁碟區建立 BucketVS。除非那裡已有同名的資料夾,否則這是一個新資料夾;在新資料夾上,第一次登入會設定管理員的密碼。重新安裝後與已安裝的套件都是如此,NAS 開機時也一樣。系統記錄會留下一則警告,.prev 檔案則保留舊的路徑:/etc/config/bucketvs-data-root.prev,已安裝的套件還有安裝資料夾中的 etc/data-root.prev。如果舊資料夾所在的磁碟區當時只是離線,請讓磁碟區重新上線、停止套件,把該檔案複製覆蓋到安裝資料夾中的 etc/data-root(例如 /share/CACHEDEV1_DATA/.qpkg/bucketvs/etc/data-root),再啟動套件:它會重新使用舊的資料。
從 App Center 開啟面板
在 App Center 中對套件按 開啟,會以連接埠 9950(HTTP)或 9951(HTTPS)開啟面板。在面板中變更連接埠後(連接埠),套件會在下次啟動時把新的連接埠告知 App Center。
從 SSH 工作階段設定自動啟動
只要套件在 App Center 中的開關是開啟的,NAS 開機時就會啟動套件。在 NAS 的 SSH 工作階段中,管理員可以用服務指令碼設定同一個開關:
/etc/init.d/bucketvs.sh disable # 下次啟動會被拒絕,開機時也一樣
/etc/init.d/bucketvs.sh enable # 套件會再次隨開機啟動
這兩個指令都只寫入開關(/etc/config/qpkg.conf 中的 Enable),會顯示設定了什麼,並把同一行寫入系統記錄。執行中的套件在 disable 之後會繼續執行,enable 也不會啟動任何東西:啟動與停止由 start 和 stop 負責,套件停用期間 start 會拒絕執行。status 會顯示 bvsd 是否在執行。
第一次登入
以 https://<NAS 位址>:9951/ 或 http://<NAS 位址>:9950/ 開啟面板。HTTPS 位址一開始使用自我簽署憑證,因此在裝置信任它之前,瀏覽器會顯示警告;比對憑證指紋的方法請見憑證一節。
新的安裝沒有任何帳號。在第一位管理員設定密碼之前,面板只會開啟一個畫面「設定管理員密碼」,用於帳號 administrator。請輸入密碼兩次:至少 10 個字元,最多 72 位元組。儲存後就會建立帳號並登入。
套件啟動後 60 分鐘內,這個畫面接受密碼。之後畫面會表示設定時段已結束;在 App Center 重新啟動 Bucket & Code Server IDE,會重新開放 60 分鐘。
它只接受來自區域網路的密碼:來自 NAS 本身,或來自私有範圍的位址(
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16、fc00::/7、fe80::/10)。畫面開啟期間,QTS 系統記錄會為 NAS 的每個區域網路位址寫入一筆資訊記錄,例如:
bucketvs: no administrator yet: open https://192.168.1.20:9951/ within 60 minutes to set the administrator's password經由 Proxy 送來的請求(帶有
X-Forwarded-For、X-Forwarded-Host、X-Forwarded-Proto、X-Real-IP或Forwarded)一律拒絕,即使 Proxy 位於區域網路也一樣:請從區域網路中的電腦直接開啟面板來設定密碼。
在 NAS 的 SSH 工作階段中執行 /usr/bin/bucketvs/bin/bvs user password administrator,會在尚無帳號時建立帳號並印出隨機密碼;之後第一次登入時,面板會要求您設定自己的密碼(管理員被鎖在外面時)。
首次登入後,總覽頁面會顯示目前只有核心在執行。每個模組的圖塊會說明該模組的用途,並有開啟它的按鈕,例如 開啟 Git:開啟您需要的模組(模組)。
在面板中工作
面板的操作方式類似程式碼編輯器:每個頁面在分頁中開啟,命令選擇區可依名稱找到頁面與動作。
- 活動列(左側的圖示)。每個圖示會開啟對應頁面,並在側邊欄顯示其樹狀結構:模組、儲存庫與 bucket、應用程式、套件、環境、工作與備份。圖示上的圓點表示有問題的模組、失敗的建置或失敗的備份。按一下目前頁面的圖示會隱藏側邊欄;Ctrl+B 也一樣。
- 分頁。以單擊開啟的頁面是預覽,以斜體顯示:下一個開啟的頁面會取代它。編輯頁面或按兩下分頁即可保留。重新載入後,分頁會依瀏覽器與帳號分別還原。在寬度至少 1280 像素的視窗中,把分頁移到另一側(
Ctrl+\)可以並排顯示兩個頁面。 - 物件與其選單。在側邊欄的列、表格的列或卡片上按一下,即可開啟該物件:其頁面移到前方,物件以綠框標示,或開啟其詳細資料。網址會指出該物件,因此上一頁、下一頁與複製的連結都會回到這裡。按兩下會保留分頁。按右鍵、Shift+F10,或在觸控螢幕上長按,即可開啟物件的選單:開啟方式(在此分頁、在保留的分頁、在另一側、在瀏覽器的新分頁),其頁面能對它執行的動作,以及複製名稱與網址。分頁的選單可關閉該分頁、其他分頁、右側的分頁或全部分頁。只有標示 ↗ 的項目會離開面板。管理 圖示會開啟系統頁面。
- 命令選擇區。Ctrl+Shift+P(或 Ctrl+K、F1)會列出您的角色可執行的指令:開啟頁面、建置或發佈應用程式、執行備份、重新啟動模組、在環境中開啟 shell。Ctrl+P 只要輸入名稱的幾個字母,就能前往頁面、應用程式、儲存庫、環境或套件。
- 底部面板(Ctrl+J)。工作 顯示執行中與最近的工作,以及其進度與記錄。問題 列出模組回報的事項:失敗的建置、已停用的備份目標、有問題的模組、即將到期的憑證,以及 ELF 檢視器對目前應用程式的發現。輸出 追蹤您最後啟動的工作。
- 移動與調整大小。拖曳邊界可改變它所相鄰部分的大小:側邊欄、底部面板、並排的兩個頁面,或頁面中並排的兩個部分,例如精靈與其摘要,或專案的檔案清單與檔案。按兩下邊界會讓它還原。拖曳對話框的標題可移動它,拖曳邊緣或右下角可調整大小;按兩下標題會讓它回到中央。若要把底部面板放到頁面旁邊,請把面板的標題列拖到編輯器的右邊緣,或按一下 × 旁的按鈕;拖到下邊緣或再按一次按鈕即可放回下方。分頁可以拖到分頁列的其他位置,或拖到另一側。面板會在這個瀏覽器中為您的帳號保留每個大小與位置,重設版面配置(在命令面板中,或在活動列底部您帳號的按鈕裡)會全部還原。使用鍵盤時,方向鍵可移動焦點所在的邊界(按住 Shift 一次移動較多,Home 會還原),Ctrl+Shift+左右鍵可移動焦點所在的分頁;對話框上方有一條橫桿、右下角有一個握把,可用方向鍵移動和調整大小。在手機上,對話框與底部面板維持原狀。
- 狀態列。模組狀態、執行中的工作、問題、資料磁碟區的可用空間、憑證、已登入的帳號、語言(編輯器會在下次啟動時採用此語言,瑞典文與荷蘭文則維持英文;Git 也會跟著套用,除非您在其中另選語言)、主題(深色、淺色、跟隨系統、深藍、石墨或紙張;主題屬於您的帳號,編輯器與 Git 也會跟著套用,除非您在其中另選主題)與版本。每個項目都會開啟可進一步查看的地方。
- 鍵盤。Ctrl+/ 或 ? 列出快速鍵。瀏覽器分頁會自行保留 Ctrl+W 與 Ctrl+Tab,因此面板以 Alt+W 關閉分頁,以 Alt+PageDown 與 Alt+PageUp 切換分頁。
- 在手機上,前幾個活動位於底部,更多 會開啟含其餘項目的側邊欄,已開啟的頁面則以清單顯示在頂端。
帳號
面板有自己的帳號。QTS 帳號無法登入面板。
角色
| 角色 | 可以做的事 |
|---|---|
| viewer | 讀取面板;備份、儲存空間、使用者與記錄頁面僅限管理員。在 Forgejo 中不能建立、分叉或匯入儲存庫,不能建立組織,也永遠不能推送;可讀取有權限的 SVN 儲存庫和 Bucket,但不能寫入任何一個 |
| member | 可讀取 viewer 能讀取的內容,並且可以寫入:推送到獲得寫入權限的 Git 儲存庫,寫入有讀寫權限的 SVN 儲存庫和 Bucket,並在其中還原檔案的舊版本。在 Forgejo 中不能建立、分叉或匯入儲存庫,也不能建立組織;無法推送到由低於 developer 的帳號擁有或管理的儲存庫;CI 模組開啟時,也無法推送到已開啟 Actions 的儲存庫。不能使用編輯器、cron 工作或建置 |
| developer | 另外還能開啟編輯器、讀取已安裝工具鏈的 bvs use 行、建立、變更與執行自己的 cron 工作、建立與建置應用程式、把套件發佈到儲存庫(由管理員列出)、檢查核心模組,並在 CI 模組開啟時建立其工作流程會在 NAS 上執行的 Git 儲存庫 |
| admin | 全部:帳號、設定、儲存空間、網路、模組、工具鏈、環境、所有 cron 工作、啟用應用程式、載入核心模組、在儲存庫中列出套件 |
developer 角色在 NAS 上等同 root:它的 cron 指令以 root 執行,其編輯器的終端機也是;CI 模組開啟時,它能推送的儲存庫的工作流程也是。請只把這個角色交給您願意告知 NAS admin 密碼的人。只需要寫入儲存庫的人,member 角色就足夠。
每個人都可以在 您的帳號 中看到自己的角色及其允許的操作,並有連到本節的連結。超出角色的頁面會說明需要哪個角色,而只有管理員能變更的項目,會在顯示之處註明。網路、Git 與 CI 會以數值向其他角色顯示其設定,空白的值顯示為「未設定」。
工作流程會以 root 身分在 NAS 上執行,因此 bvsd 會讓 member 或 viewer 擁有或能寫入的每個 Git 儲存庫保持 Actions 關閉:給予這類帳號某個儲存庫的寫入權限,該儲存庫的 Actions 會在一分鐘內關閉,Git 頁面會為管理員列出這些儲存庫。若要在其中使用 Actions,請先在 Forgejo 移除該寫入權限,或把這類帳號擁有的儲存庫移轉到 developer 的帳號。
建立與變更帳號
管理員在使用者頁面管理帳號。
- 新帳號一開始是 viewer 角色。developer 與 admin 要刻意選擇:developer 角色就是 NAS 上的 root(見上文)。
- 新帳號一開始沒有任何 cron 工作,即使先前有同名帳號擁有過工作也一樣。
- 名稱為 2 到 32 個字元:第一個是小寫英文字母,之後可用小寫英文字母、數字、
.、_或-。連續兩個.、_、-,或以其中之一結尾,都會被拒絕。Forgejo 保留的名稱(admin、api、user等)、bucketvs(套件的系統使用者)、cli與system(兩者都由 bvsd 自己使用)也會被拒絕。 - 「首次登入時必須設定自己的密碼」會讓帳號必須先設定自己的密碼,才能做其他任何事。
- 停用帳號會立即結束其工作階段並停止其 API 權杖。資料會保留。其cron 工作也會保留,但在停用期間不會執行,正在進行的執行會被停止。
- 將帳號改為 member 或 viewer 角色時,其 cron 工作也是如此:工作會保留,在角色低於 developer 期間不會執行,正在進行的執行會被停止。
- viewer 永遠不會推送到 Git,即使在 Forgejo 中獲得了寫入權限也一樣。需要推送的帳號請給予 member 角色。
- 刪除帳號會連同其工作階段與 API 權杖一起移除。其家目錄會移到資料目錄中的
trash/home/<名稱>-<時間>,7 天後由工作「清空資源回收筒」移除;其tmp/tmux-<名稱>資料夾會被移除。其 cron 工作會連同執行與記錄一起刪除。 - 最後一位已啟用的管理員不能被降級、停用或刪除。
- 「設定新密碼」會結束該帳號的工作階段並撤銷其 API 權杖。
密碼與工作階段
- 密碼至少 10 個字元,最多 72 位元組。
- 變更自己的密碼(在「您的帳號」中)會結束您的其他工作階段並撤銷您的 API 權杖。用來變更密碼的工作階段仍保持登入。
- 工作階段在最後一次請求後 12 小時結束,且無論如何都在登入後 7 天結束。每個帳號最多保有 32 個工作階段;再登入一次會結束最久未使用的那一個。
- 工作階段 Cookie 為
HttpOnly與SameSite=Lax。瀏覽器直接或經由信任的 Proxy 以 HTTPS 連到 NAS 時,Cookie 會標記為Secure。
密碼錯誤
- 同一位址在 15 分鐘內登入失敗 5 次,該位址會被鎖定 15 分鐘,即使密碼正確也一樣。IPv6 用戶端以其 /64 網路計算。
- 同一位址對同一帳號失敗 5 次,會鎖定該帳號從該位址登入 15 分鐘。
- 來自許多位址對同一帳號的失敗會讓之後的登入變慢:失敗一次後延遲 125 毫秒,之後加倍,最多 2 秒。來自區域網路的失敗絕不會鎖定帳號。
- 從網際網路(區域網路以外的任何位址),自上次成功登入起對同一帳號登入失敗 20 次,無論來自哪些位址,都會鎖定該帳號從網際網路登入,此時連正確的密碼也會被拒絕。帳號仍可從區域網路登入。管理員可在「使用者」頁面(解除鎖定)或用
bvs user unlock <名稱>解除鎖定,或給它新密碼。次數在「使用者」頁面的 來自網際網路的登入 設定;0 關閉此鎖定。 - 這些計數保存在記憶體中,因此重新啟動 bvsd 會清除它們;鎖定會一直保留到被解除為止。
在 Proxy 後方時,計算的是 Proxy 回報的位址,但前提是該 Proxy 是信任的 Proxy。否則每個用戶端都會被算成 Proxy 本身的位址,任何人輸錯 5 次密碼,就會把所有人鎖在外面 15 分鐘。
兩步驟驗證
每個帳號在「您的帳號」中自行開啟:用驗證器 App 掃描 QR code(或輸入金鑰),再輸入 App 顯示的 6 位數代碼。之後,登入時會在密碼之後要求輸入代碼。
- 代碼遵循 RFC 6238:6 位數,每 30 秒產生新代碼。早或晚 30 秒的代碼也會接受。同一組代碼絕不會接受兩次。
- 如果剛產生的代碼無法通過,手機時鐘可能不準;請把它設為自動校時。
- 關閉兩步驟驗證需要帳號密碼。
- 手機遺失時,由管理員在使用者頁面將其關閉。之後只要密碼即可登入。
API 權杖
指令碼與 CI 使用 API 權杖代替密碼。在「您的帳號」中,「新權杖」會建立一個權杖:
- 格式為
bvs_加上 40 個十六進位數字,只顯示一次。bvsd 只保存其雜湊。 - 指令碼以
Authorization: Bearer bvs_...傳送。 - 權杖的範圍為
read、write與admin,分別對應角色 viewer、developer 與 admin。權杖以其最高範圍運作,但絕不超過擁有者目前的角色,因此降級帳號也會降級其權杖。沒有對應 member 的範圍:member 只能建立read權杖。 - 設定新密碼會撤銷擁有者的所有權杖。已停用擁有者的權杖將無法使用。
- 權杖不能變更密碼或兩步驟驗證,也不能建立或刪除權杖:這些都需要已登入的工作階段。因此外洩的權杖無法把擁有者鎖在外面。
管理員被鎖在外面時
NAS 管理員可以從 NAS 上的 SSH 工作階段重設任何帳號。bvs 指令透過只有 root 能開啟的 socket(/usr/bin/bucketvs/var/run/bvsd-cli.sock,模式 600)與 bvsd 通訊:
/usr/bin/bucketvs/bin/bvs user list
/usr/bin/bucketvs/bin/bvs user password administrator
/usr/bin/bucketvs/bin/bvs user totp-reset administrator
/usr/bin/bucketvs/bin/bvs user unlock administrator
bvs user password <名稱>設定一組 20 個字元的新隨機密碼並印出。該帳號下次登入時必須設定自己的密碼。其工作階段會結束,API 權杖會被撤銷。在尚無任何帳號的新安裝上,bvs user password administrator會建立該帳號。bvs user totp-reset <名稱>關閉該帳號的兩步驟驗證。bvs user unlock <名稱>解除帳號因來自網際網路的錯誤密碼過多而被鎖定的狀態。
該 socket 上的每個請求都以內建管理員 cli 的身分執行,並寫入資料目錄的 log/audit.log。執行這些指令時 bvsd 必須在執行中。
資料目錄
資料目錄是存放套件所保存一切內容的資料夾。其路徑是 /usr/bin/bucketvs/etc/data-root 中唯一的一行。儲存空間頁面會顯示它、它所在的磁碟區,以及該處的可用空間。
只有當資料目錄是實體磁碟區上的資料夾時,bvsd 才會啟動。套件的啟動程序會先檢查這一點:資料夾不存在,或位於 tmpfs 或 ramfs 上時,會依資料目錄的初始位置所述,在安裝所在的磁碟區建立新的資料目錄。離線的磁碟區會在 NAS 的 RAM 中留下空的掛載點資料夾,寫在那裡的設定會在下次重新開機後消失。bvsd 本身只有在被手動啟動時才會拒絕這樣的資料夾,原因會寫入 QTS 系統記錄。
bvsd 給每個程序的環境
QTS 把 /tmp 放在小型 RAM 磁碟中,把 /root 放在重新開機就會清空的 RAM 磁碟上。因此,bvsd 啟動的每個程序(模組程式、cron 工作、安裝)都會在資料目錄中取得暫存檔案與家目錄:
| 變數 | 值 |
|---|---|
HOME | <資料目錄>/home/<使用者> |
TMPDIR | <資料目錄>/tmp |
XDG_CACHE_HOME、XDG_CONFIG_HOME | 該家目錄中的 .cache 與 .config |
npm_config_cache | 該家目錄中的 .npm |
PATH | ~/.local/bin、~/.npm-global/bin,接著是套件的 bin、sbin 與 node/bin,再來是系統資料夾 |
SSL_CERT_FILE、GIT_SSL_CAINFO、CURL_CA_BUNDLE | 套件的 CA 憑證包 /usr/bin/bucketvs/etc/ssl/cacert.pem |
TZ | QTS 中設定的 NAS 時區 |
SHELL、EDITOR | 套件的 bash 與 nano |
LANG、LESSCHARSET | C.UTF-8 與 utf-8,讓含有中文等字元的檔名照原樣顯示 |
搬移資料目錄
儲存空間頁面可以把整個資料目錄搬到 /share 下的其他資料夾。選擇共用資料夾或磁碟區後,資料會放進其中名為 BucketVS 的新資料夾。若要直接使用某個資料夾,請開啟一個名為 BucketVS 的空資料夾。共用資料夾在 QTS 中建立(控制台、共用資料夾);在共用資料夾或磁碟區內,此頁面可以建立新資料夾。選擇視窗會在資料目前所在的位置開啟並註明這點;請從那裡開啟要移往的共用資料夾或磁碟區。
開始搬移前,頁面會檢查目標,並列出拒絕的所有理由:
- 路徑必須位於
/share之下,且不能是/share本身; - 路徑的任何部分,以及連結所指向的路徑,都不能含有
:、&、|或控制字元; - 不能是目前的資料目錄、其中的資料夾,或包含它的資料夾;
- 必須是新資料夾或空資料夾;
- 檔案系統必須保留 Unix 擁有者與權限(FAT、exFAT 與 NTFS 會被拒絕:Forgejo 與 SVN 需要擁有者與模式);
- 磁碟區必須以建置環境所需的
exec、dev與suid掛載; - 必須可寫入,且可用空間足以容納資料再加 10 %。
搬移進行期間:
- Git、CI、SVN 與 Bucket、編輯器不會回應。面板繼續運作並顯示進度。
- 不會開始新的 cron 執行。已在進行的執行會繼續。
- 在搬移結束前,開啟或關閉模組都會被拒絕。
切換後,bvsd 會停止並以新的根目錄重新啟動自己,因此面板會暫時無法使用幾秒鐘。
搬移失敗時,會繼續使用舊的資料目錄,模組也會重新啟動。工作的錯誤訊息會說明哪裡出錯,以及副本的處理方式:
- 磁碟區已滿或取消時,會移除搬移所建立的內容。
- 其他任何失敗(複製、檢查、寫入磁碟)都會保留副本,並以名為
INCOMPLETE的檔案標記,在儲存空間頁面的「搬移失敗後遺留的副本」下列出。 - 搬移期間套件停止時,舊的根目錄仍是資料目錄。下次啟動時,bvsd 會在系統記錄中回報未完成的搬移,並列出該副本。
舊副本與遺留的副本
搬移成功後,舊的資料目錄仍留在原處,其中有一個名為 MOVED-TO 的檔案。沒有任何東西使用它。儲存空間頁面上的「移除舊副本」會刪除它,「移除此副本」會刪除搬移失敗後遺留的副本。兩種移除都只在同一個檔案系統內進行,絕不跟隨連結。若資料夾是掛載點或共用資料夾本身的資料夾,則只清空內容並保留資料夾。
網路
網路頁面包含連接埠、一般 HTTP 的處理方式、模組的主機名稱、信任的 Proxy、公開 URL 與憑證。儲存時會重新啟動變更所需的部分,並列出它們。
連接埠
| 設定 | 預設值 | 說明 |
|---|---|---|
| HTTPS | 9951 | 透過 TLS 的面板與模組 |
| HTTP | 9950 | 透過一般 HTTP 的面板與模組 |
| 透過 SSH 使用 Git | 9952 | 透過 SSH 使用 Git |
| 複製 URL 中的 SSH 連接埠 | 0 | SSH 複製位址中顯示的連接埠;0 表示使用上方的 SSH 連接埠。當路由器把其他連接埠轉送到 NAS 時請設定此項。 |
| 複製 URL 中的 SSH 主機 | 空的 | SSH 複製位址中顯示的名稱或位址。空的表示使用 Git 主機名稱,沒有時使用公開 URL 的主機,再沒有時使用 NAS 的區域網路位址;對透過 Cloudflare Tunnel 發佈的名稱,則使用區域網路位址與「透過 SSH 使用 Git」的連接埠。請設為僅 DNS 的名稱,或在路由器轉送 SSH 連接埠時設為路由器的位址。 |
連接埠範圍為 1024 到 65535,且彼此不能相同。127.0.0.1 上的模組連接埠(9960 與 9961)會被拒絕;當其他程式占用 9960 或 9961 時,httpd 或 CI runner 伺服器改用的連接埠也會被拒絕(訊息會指出該連接埠)。若因無法使用新連接埠而讓 nginx 在儲存後仍停留在舊連接埠,通知會說明原因。NAS 具備 IPv6 時,nginx 也會在 IPv6 上接聽。
一般 HTTP
- 「直接提供」(預設):面板與模組也會以一般 HTTP 回應。當區域網路上的 Proxy 以一般 HTTP 連到連接埠 9950 時,請保留此設定。
- 「重新導向到 HTTPS」:一般 HTTP 的請求會收到導向 HTTPS 連接埠的重新導向(307)。來自信任的 Proxy、且表示其用戶端使用 HTTPS 的請求,會以一般 HTTP 回應,避免這類 Proxy 陷入迴圈。
登入頁面經由一般 HTTP 開啟時會顯示警告:此時密碼會以可讀的形式在網路上傳送。
憑證
第一次啟動時,bvsd 會為下列名稱建立自我簽署憑證(ECDSA P-256):
- NAS 的主機名稱、模組的主機名稱與
localhost; - NAS 的區域網路位址與
127.0.0.1。
有效期為 825 天,這是 Apple 裝置可接受的上限,即使是手動信任的憑證也一樣。bvsd 在啟動時與每天一次檢查憑證,當剩餘 30 天以下、名稱組合改變或金鑰不相符時,會建立新憑證。建立新憑證時會送出通知。網路頁面會顯示其名稱、有效期間與 SHA-256 指紋:在裝置信任它之前,請先比對指紋。
「新增自己的憑證」接受 PEM 格式的憑證鏈及其私密金鑰:
- 先放伺服器憑證,再放中繼憑證;
- 金鑰不能有密碼(nginx 需要無人值守啟動);
- 金鑰必須屬於第一張憑證,每張憑證都必須由下一張簽署,任何一張都不能過期,且第一張必須以主體別名(SAN)列出其主機。
這組憑證與金鑰以模式 600 儲存在資料目錄的 etc/tls/。當上傳的憑證過期或不再通過這些檢查時,nginx 會改用自我簽署憑證,並以通知說明原因。上傳的憑證剩餘 30 天以下時也會送出通知。「新的自我簽署憑證」會建立一組新的自我簽署憑證並切換回它。
經由 Proxy 連線的用戶端看到的是 Proxy 的憑證,而不是這張憑證。
「網路」頁面上的 下載憑證 會把面板提供的憑證(不含金鑰)存成 <名稱>.crt。把它加入裝置的受信任憑證後,該裝置的瀏覽器就會信任面板;編輯器的擴充功能檢視需要這一點(擴充功能)。新的自我簽署憑證需要重新信任。
信任的 Proxy
IP 位址或 CIDR 範圍的清單,例如 NAS 前方 Proxy 的位址 192.168.1.5。只有 TCP 連線來自其中之一的請求,nginx 才會採用:
X-Forwarded-For中的用戶端位址;X-Forwarded-Proto中用戶端使用的協定(只接受http或https)。
來自其他位址的請求一律視為直接來自其用戶端,nginx 會以自己的值取代其 X-Forwarded-* 標頭。指定範圍時,範圍內的每台主機都會受到信任,都能設定用戶端位址與協定,因此請填入 Proxy 本身的位址。涵蓋所有位址的範圍(0.0.0.0/0、::/0)會被拒絕。
公開 URL
只填位址,例如 https://git.example.com,不含路徑。各模組的章節會說明哪些連結以它開頭。
在反向 Proxy(Plesk)後方
常見的做法是由具有公開憑證的 Proxy 處理 TLS,再由它以一般 HTTP 連到區域網路上的連接埠 9950。以下範例以 bvs.example.com 作為公開名稱,192.168.1.20 為 NAS,192.168.1.5 為 Plesk 伺服器;請換成您自己的值。
在 NAS 上
- 在網路頁面上,把 Plesk 伺服器的位址(以 NAS 看到的為準)加入信任的 Proxy。
- 一般 HTTP 可以維持「直接提供」。Plesk 伺服器成為信任的 Proxy 後,「重新導向到 HTTPS」也能正常運作。
在 Plesk 中
把下列指令放進網域的 Apache 與 nginx 設定中,「其他 nginx 指令」欄位(英文介面為「Additional nginx directives」):
location ~ ^/ {
proxy_pass http://192.168.1.20:9950;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket:編輯器及其終端機
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
# 大型推送與上傳:不限大小、串流傳輸、允許一小時無資料
client_max_body_size 0;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location ~ ^/ 是正規表示式 location。nginx 會優先採用相符的正規表示式,而不是一般的 location /(Plesk 會自己寫一個),因此這個區塊會處理網站的每個路徑,而不帶路徑的 proxy_pass 會把請求路徑原封不動地轉交。請在同一個設定頁面關閉「由 nginx 直接提供靜態檔案」:若開啟,Plesk 會從網域自己的資料夾回應 .js、.css 與圖片檔案的請求,面板將無法載入。
在網域的代管設定中,開啟從 HTTP 到 HTTPS 的永久 SEO 安全 301 重新導向(英文介面為「Permanent SEO-safe 301 redirect from HTTP to HTTPS」)。其他 nginx 指令也會套用到網域在連接埠 80 上的一般 HTTP 網站;沒有重新導向時,網站在那裡也會回應,密碼將以未加密的方式在網際網路上傳送。
每一行的作用:
| 指令 | 缺少時的問題 |
|---|---|
Host $http_host | NAS 上的 nginx 依 Host 選擇伺服器區塊,因此模組的主機名稱永遠不會相符。bvsd 會比對頁面的 Origin 與 Host(包含連接埠),因此面板中的每項變更都會以 403 csrf 失敗;使用 $host 會丟掉 443 以外的公開連接埠,同樣會失敗。 |
X-Forwarded-For | 每個用戶端都被算成 Plesk 伺服器:一個人輸錯 5 次密碼,就會把所有人鎖在外面 15 分鐘 |
X-Forwarded-Proto $scheme | 工作階段 Cookie 不會標記為 Secure,且在「重新導向到 HTTPS」模式下,每個請求都會被送到公開名稱的連接埠 9951 |
Upgrade、Connection | 編輯器的頁面能開啟,但編輯器及其終端機永遠連不上 |
client_max_body_size 0、proxy_request_buffering off、逾時設定 | 大型推送與上傳會受到 Proxy 本身的大小限制與逾時影響 |
只有當 Plesk 伺服器列在信任的 Proxy 中時,X-Forwarded-For 與 X-Forwarded-Proto 才會生效。否則 NAS 上的 nginx 會忽略它們。
透過 SSH 使用 Git
HTTP Proxy 不會轉送 SSH。透過 SSH 使用 Git 時,請直接連到 NAS 的連接埠 9952,或經由路由器的 TCP 連接埠轉送。網路頁面上的「複製 URL 中的 SSH 連接埠」設定複製位址所顯示的連接埠;公開名稱只能到達 Proxy 時,「複製 URL 中的 SSH 主機」設定其名稱或位址。
檢查設定
- 面板可在
https://bvs.example.com/開啟,且能登入並儲存設定。 - 瀏覽器的開發人員工具顯示工作階段 Cookie
bvs_session帶有Secure旗標。 - 記錄頁面顯示
nginx-access:每一行的第一個欄位是用戶端自己的位址,而不是 Plesk 伺服器的位址。
模組的主機名稱
模組可以有自己的主機名稱(網路頁面,主機名稱)。此時 nginx 會在該名稱的根目錄只提供這個模組。該名稱必須指向 NAS,或指向 NAS 前方的 Proxy。在 Proxy 上,每個主機名稱都需要一個自己的網站,並使用與上方相同的指令。
| 模組 | 在其主機名稱的根目錄 | 同時提供 |
|---|---|---|
| Git | Forgejo | 其他所有名稱上的 /git/ 會以相同的路徑、查詢字串與連接埠回應 302,導向 Git 主機名稱 |
| 編輯器 | code-server | 面板的登入頁面與 /api/,讓使用者可以在該名稱上登入 |
| SVN 與 Bucket | httpd | 儲存庫仍位於 /svn/<名稱>,bucket 仍位於 /bucket/<名稱> |
關閉的模組會在其路徑與主機名稱上回應 503,並附上一句說明。
所有主機名稱共用一次登入
工作階段 Cookie 屬於設定它的那個名稱,除非設定 network.cookie_domain 指定了所有模組主機名稱的上層網域。設為 example.com 時,在 bvs.example.com 登入後,也能用於 git.example.com 與 ide.example.com。bvsd 會拒絕公開尾碼(com、com.pl、co.uk、myqnapcloud.com)、不是所有模組主機名稱上層的網域,以及在尚未設定任何模組主機名稱時的任何網域。該網域下的每個網站都會收到這個 Cookie,因此請設定範圍最小的共同上層網域。
網路頁面不會顯示這個設定。NAS 管理員透過 CLI socket,用套件的 curl 設定:
/usr/bin/bucketvs/bin/curl --unix-socket /usr/bin/bucketvs/var/run/bvsd-cli.sock \
-X PUT -H 'Content-Type: application/json' \
-d '{"network":{"cookie_domain":"example.com"}}' \
http://bvsd/api/v1/settings
設為空值("")時,Cookie 會再次只屬於各自的名稱。
發佈到網際網路(Cloudflare Tunnel)
發佈 頁面(管理,僅限管理員)會以 DNS 位於 Cloudflare 的網域名稱,把套件發佈到網際網路。套件內附的 cloudflared 從 NAS 主動連到 Cloudflare:不需要開啟路由器的連接埠,名稱的憑證由 Cloudflare 持有。每個請求都會經過套件的 nginx:面板及其 API 需要登入,沒有帳號時只能開啟您設為公開的內容(公開儲存庫、其網頁檢視、套件庫)。
名稱分為兩種,每種最多一個:
| 類型 | 範例 | 提供的內容 |
|---|---|---|
| 主要主機名稱 | code.example.com | 面板及其 API、位於 /git/ 的 Forgejo、位於 /svn-web/ 與 /bucket-web/ 的網頁檢視、位於 /repo/ 的套件儲存庫(唯讀)與本指南。/svn/ 與 /bucket/ 在那裡回應 404,/ide/ 在您發佈編輯器之前也是(見下文) |
| 套件主機名稱 | qpkg.example.com | 只有 /repo/ 的 GET 與 HEAD,供其他 NAS 的 App Center 使用;其他一切回應 404 |
權杖需要的權限
在 dash.cloudflare.com(My Profile、API Tokens)為名稱所在的區域建立具有下列權限的 API 權杖:
- Account、Cloudflare Tunnel、Edit
- Zone、DNS、Edit
- Zone、Cache Rules、Edit
- Zone、Cache Purge、Purge
套件把權杖保存在 NAS 上只有 root 能讀取的檔案中,之後不會再顯示。
如果權杖設有 Client IP Address Filtering,請在其中填入 NAS 的兩個公開位址,IPv4 與 IPv6:NAS 有 IPv6 位址時會透過 IPv6 連線到 Cloudflare。否則發佈頁面會以 token_ip_filter 拒絕,並指出 Cloudflare 看到的位址。
發佈
輸入名稱與權杖,然後按 發佈。套件會先在 Cloudflare 檢查一切,任何檢查失敗時都不會在那裡變更任何東西;訊息會說明要修正什麼:
- 權杖缺少的權限,並指出其名稱;
- 位於權杖看不到的區域中的名稱;
- 名稱已有的 DNS 記錄(其類型與指向):請在 Cloudflare 刪除它,或改用其他名稱;
- 公開瀏覽(Git 頁面)關閉時的主要主機名稱,因為其訪客沒有帳號;
- 分屬兩個 Cloudflare 帳號區域的名稱。
接著它會建立通道(除非您指定名稱,否則命名為 bucketvs-<NAS 名稱>;Cloudflare 上已有同名的通道則會接手),以經過代理的 CNAME 記錄讓每個名稱指向它,加入快取規則並啟動 cloudflared。以相同的值 重新發佈 不會改變任何東西。請把公開 URL(網路)設為主要主機名稱的 https:// 位址,讓 Forgejo 的連結與 HTTPS 複製位址使用它;兩者不同時,頁面會提醒您。
透過 SSH 使用 Git 不會經過通道:Cloudflare 對已發佈的名稱只傳送 HTTP。因此 SSH 複製位址是 NAS 的區域網路位址及其「透過 SSH 使用 Git」的連接埠(9952),在面板與 Forgejo 自己的複製欄位中都是如此,Git 頁面與總覽會顯示「透過 SSH 複製只能在區域網路使用;從網際網路請透過 HTTPS 複製。」若要從網際網路使用 SSH,請在路由器上轉送 SSH 連接埠,並把 複製 URL 中的 SSH 主機(網路)設為路由器的公開位址或指向它的僅 DNS 名稱;路由器使用其他連接埠時,再設定 複製 URL 中的 SSH 連接埠。
在管理員於 發佈 頁面開啟 把編輯器發佈在主要主機名稱 之前,主要主機名稱的 /ide/ 回應 404。編輯器的終端機是 NAS 上的 root shell,任何從網際網路在那裡以開發者或管理員身分登入的人都能使用,所以請先為這些帳號開啟兩步驟驗證。開關開啟時,編輯器經過與區域網路相同的登入,連接埠代理(/ide/proxy/<port>/)在那裡保持關閉,Cloudflare 也從不快取它的頁面。開啟期間,總覽會顯示 編輯器在網際網路上。
CI 模組開啟期間,推送到此 Forgejo 任何儲存庫的工作流程,都會透過 NAS 自己的執行器在 NAS 上以 root 執行,無論是從網際網路或從區域網路推送:與編輯器的終端機相同的權限。發佈 頁面在 網際網路可存取的範圍 下也這麼說。只把推送權限給您願意告知 NAS 管理員密碼的人。
快取
開啟 快取預設 時,Cloudflare 會快取套件(*.qpkg)一年、圖示一天、repo.xml 5 分鐘、面板的檔案一年;絕不快取 API、Forgejo 的頁面、登入頁面或網頁檢視。發佈到套件儲存庫時,會立即從 Cloudflare 的快取清除 repo.xml(以及變更的圖示或已刪除版本的檔案)。套件把自己的規則加在區域快取規則的最後,絕不變更其他規則。
從網際網路登入
第一組密碼絕不能透過已發佈的名稱設定:首次設定只接受本機用戶端。密碼錯誤依網際網路用戶端分別計算,與區域網路相同。以 git 傳送給 Forgejo 的密碼也會計算;Forgejo 存取權杖照常可用。Cloudflare 接受最大 100 MB 的請求,因此較大的推送或上傳請改用區域網路位址。
停止與移除
停止 會結束 cloudflared;此時名稱會顯示 Cloudflare 自己的錯誤頁面,Cloudflare 上不會有任何變更。從 Cloudflare 移除 會刪除套件建立的 DNS 記錄、快取規則與通道(接手的通道會保留),並忘記權杖。名稱發佈期間,總覽會顯示帶有通道狀態的 網際網路 標記。
模組
總覽頁面會顯示每個模組及其程序、記憶體與 CPU,並可開啟或關閉模組(僅限管理員)。關閉的模組會說明其用途;管理員可在其圖塊或其頁面以其按鈕(開啟 Git、開啟 編輯器 等)開啟它,編輯器模組也可在「編輯器」分頁中開啟。
- 開啟模組會執行一個工作:模組完成準備、儲存開關狀態,然後啟動其程序。工作最多等候程序 30 秒。
- CI 需要 Git:CI 開啟時無法關閉 Git。 Git 關閉時,CI 的按鈕為 開啟 Git 和 CI,會先開啟 Git。
- 關閉的模組不執行任何程序,也不使用記憶體。
- 核心一律開啟。
| 狀態 | 意義 |
|---|---|
| 執行中 | 模組的每個程序都在執行 |
| 啟動中 | 有程序在不到一秒前啟動 |
| 運作異常 | 有程序在等待重新啟動、模組的檔案無法寫入,或其健康檢查失敗 |
| 不斷重新啟動 | 某個程序在 10 分鐘內結束了 5 次;bvsd 每 15 分鐘重新啟動它一次,並已送出一則通知 |
| 已停止 | 模組的程序未在執行(資料搬移停止了它們,或它們無法啟動) |
| 關閉 | 模組已關閉 |
結束的程序會在 1 秒後重新啟動,之後依序為 2 秒、4 秒,以此類推,最長 60 秒。程序執行滿 10 分鐘後,等候時間會從 1 秒重新計算。不斷重新啟動的程序,在其模組關閉再開啟時會立即啟動。
Git
Git 模組執行 Forgejo,這是具備議題、合併請求、發行版本、Wiki、LFS、鏡像與 Webhook 的 git 儲存庫網頁介面。管理員在總覽頁面或 Git 頁面以 開啟 Git 開啟它。工作會在 <資料>/forgejo 中準備 Forgejo 的資料夾與資料庫,把面板的每個帳號加入 Forgejo,然後啟動它。之後 Forgejo 會在面板位址的 /git/ 開啟;若設定了 Git 主機名稱,則在該名稱的 / 開啟(請見模組的主機名稱)。
Git 頁面上的 新增儲存庫(尚無儲存庫時,總覽頁面的 Git 圖塊上也有)會開啟 Forgejo 建立儲存庫的表單。面板只對 developer 以上的角色顯示此按鈕與 遷移或鏡像儲存庫:Forgejo 不允許 viewer 或 member 建立儲存庫。
儲存庫與帳號
- 只需登入一次。 Forgejo 沒有自己的登入:
/git/user/login會轉到面板的登入(帳號有驗證碼時也會要求),完成後再回到 Forgejo。 - 帳號來自面板。 面板的每個帳號在 Forgejo 中都有同名、同密碼的帳號。
admin角色在 Forgejo 中是網站管理員。已停用的帳號,或必須先變更密碼的帳號,也無法登入 Forgejo。面板中的變更會在幾秒內反映到 Forgejo。使用者頁面與 Git 頁面會顯示每個帳號在 Forgejo 中的狀態,Git 頁面上的 立即同步所有帳號 會重新執行同步。 - 刪除帳號 時,面板會停用其 Forgejo 帳號:它無法再登入,其權杖與 SSH 金鑰會被移除,但其儲存庫會保留。在管理員於 Forgejo 的網站管理(使用者帳號)中重新命名或刪除舊的 Forgejo 帳號之前,這個名稱不能給新的面板帳號使用。
- 在 Forgejo 中直接建立的帳號 面板絕不會變更。同名的面板帳號會顯示原因,並等到其中之一改名為止。
- 兩步驟驗證與 git。 對開啟兩步驟驗證的帳號,Forgejo 不接受密碼。此時透過 HTTP 或 HTTPS 使用 git,需要以 Forgejo 存取權杖(Forgejo 的 設定、應用程式)代替密碼。SSH 金鑰照常可用。
- 儲存庫 的建立、匯入與鏡像都在 Forgejo 自己的頁面中進行。預設允許從區域網路上的位址匯入(設定:
git.allow_local_networks),因為 NAS 通常從自己的網路鏡像。
透過 HTTPS 與 SSH 複製
在 Git 頁面上,複製儲存庫 會為擁有者與儲存庫寫出兩種指令:
| 方式 | 位址 | 登入 |
|---|---|---|
| HTTPS(或 HTTP) | https://<NAS 位址>:9951/git/<擁有者>/<儲存庫>.git | 面板的使用者名稱與密碼,或存取權杖 |
| SSH | ssh://git@<NAS 位址>:9952/<擁有者>/<儲存庫>.git | 在 Forgejo 的 設定、SSH / GPG 金鑰 中新增的 SSH 金鑰 |
- 設定了公開 URL 時(在 Proxy 後方,公開 URL),HTTPS 位址會使用它;有 Git 主機名稱時,路徑是該名稱上的
/<擁有者>/<儲存庫>.git。 - SSH 連接埠是
network.ssh_port(9952),或在路由器轉送其他連接埠到它時使用network.public_ssh_port。Proxy 不會轉送 SSH:請在路由器上轉送連接埠(請見透過 SSH 使用 Git)。 - 透過 Cloudflare Tunnel 發佈的名稱不承載 SSH,因此 SSH 複製位址會改用 NAS 的區域網路位址,除非
network.public_ssh_host(網路,「複製 URL 中的 SSH 主機」)填入僅 DNS 的名稱或路由器的位址。 - 大型推送不會被截斷:nginx 不對
/git/設定內容大小上限。
讓沒有帳號的人檢視儲存庫
Git 頁面上的 公開瀏覽 讓任何能連到 Forgejo 的人不需帳號即可閱讀其公開儲存庫。在 Forgejo 中,每個儲存庫都是公開或私人(其 設定、可見性)。開關開啟時,沒有帳號的訪客可以:
- 開啟公開儲存庫、其資料夾與檔案,並原樣下載檔案;
- 閱讀歷史記錄、開啟提交及其差異(也可以
.diff或.patch檔案形式),並比較兩個提交; - 查看其發行版本、下載封存檔,並透過 HTTP 複製(
git clone https://<NAS 位址>:9951/git/<擁有者>/<儲存庫>.git); - 在 探索 與擁有者的個人資料中找到公開儲存庫。
私人儲存庫仍然隱藏:其位址會回應「找不到」。開關開啟期間,Forgejo 也不會列出任何帳號(探索的 使用者 分頁與使用者搜尋都會關閉,已登入的使用者也一樣),因此訪客無法收集帳號名稱。推送、議題、合併請求與設定仍需要帳號。開關關閉時,每個頁面都會先要求訪客登入。
若要分享儲存庫,請在 Forgejo 中將它設為公開,開啟 公開瀏覽,再送出位址。在 Git 主機名稱上,位址為 https://<Git 主機名稱>/<擁有者>/<儲存庫>。
新專案
新專案 是一個頁面,會一步一步把專案從零帶到已建置、已發行的第一個版本。可從命令面板(Ctrl+Shift+P,新專案)、編輯器側邊欄頂端、Git 側邊欄標題、Git 頁面與「專案」頁面在專屬分頁中開啟;「範例」頁面上 編輯器專案 中的範例有 以此建立新專案。需要 developer 角色、Git 與編輯器模組,以及您在 Forgejo 的帳號(Git 頁面會顯示同步狀態)。Git 或編輯器關閉時,頁面會在步驟上方說明,管理員可在那裡用一個按鈕開啟它們。
- 範本。 範本分組列出:程式(C、使用 CMake 的 C++、Go、Rust、Node、Python、Java)、QTS 套件(QPKG 套件、App Builder 應用程式、從原始碼建置的套件)、核心(核心模組、USB 序列驅動程式 ch341)、網站(靜態網站:
src/中的頁面、建置public/的 Makefile、以make test檢查連結)與範例。每張卡片說明建置會產生什麼,並標出此 NAS 尚缺的項目(QDK、建置環境、已關閉的模組),附上新增它的頁面連結。 - 名稱與可見性。 名稱即儲存庫與資料夾
projects/<名稱>的名稱;輸入時頁面就會檢查。接著是擁有者(您的帳號,或 Forgejo 允許您建立儲存庫的組織)、私人或公開,以及需要時的說明。App Builder 應用程式還要選擇起始的預設與目標。 - 服務(QPKG 套件與從原始碼建置的套件):以區塊組成套件的啟動與停止方式。選擇一個預設(命令列工具將程式連結到
/usr/bin;背景服務加上帳號、磁碟區上的資料存放資料夾、以該帳號啟動的程式、等待其連接埠,以及有逾時的停止;網頁應用程式再加上 App Center 的「開啟」按鈕;空的只有動作),然後修改其區塊。每個區塊的卡片會在您輸入時顯示它寫入腳本的行,被拒絕的值會標示在欄位下方。啟動絕不會開啟 App Center 的 Enable,停止也絕不會改動它。之後可在專案檢視中修改區塊。 - 建置。 專案建置所用的環境,會為專案保留(之後可在專案檢視變更),也可選擇不指定,由 bvsd 在每次建置時挑選。這一步會先提供 bvsd 自己會挑選、
bvs qbuild與 CI 也用來建置的環境:Ubuntu 24.04 builder,沒有時為 Debian 12 builder,再沒有時為其他 Debian 或 Ubuntu 環境。若該範本的 Makefile 以 ENV 行指定每個應用程式的環境,這一步會說明這點而不詢問環境,專案也不保留任何環境。對從原始碼建置的套件,這一步也會說明入門配方的來源網址與 sha256 是暫用的:在配方寫上您程式真正的來源與該檔案的 sha256 之前,第一次建置會失敗。頁面會顯示 CI 每次推送時執行的工作流程。建立後立即建置 預設開啟,除非您關閉它;從原始碼建置的套件則預設關閉,您可以自行開啟。若 NAS 上沒有 Debian 或 Ubuntu 環境,這一步會說明這點:管理員可在此用 建立此環境 建立建置環境,之後這一步就會提供它;否則請關閉 建立後立即建置,之後再建置專案。 - 發佈(QPKG 套件、App Builder 應用程式或網站):在此 NAS 上測試部署(管理員,僅限已簽署套件;應用程式則為 在此 NAS 上啟用)、發佈到此 NAS 的 App Center 儲存庫,以及 發佈到我的網頁伺服器(管理員,發佈到下方「自己的網頁伺服器(網頁目標)」之一);新增目標 可在此保存新的目標。每一項都是選用的。發佈的選擇也會成為專案的開關 發佈到 App Center 儲存庫(專案檢視的「設定」):開啟時,專案的 CI 每次執行都會發佈到那裡。
- 檢閱 列出所有答案與將執行的步驟。建立專案 會送出它們。
- 進度 追蹤每個步驟的工作:儲存庫與第一個提交、第一次建置,接著依序是測試部署、發佈到 App Center 與發佈到網頁。每一列顯示其狀態與記錄的結尾;點一下可顯示記錄。失敗的步驟會說明原因並提供 重試,之後的步驟會等待。最後提供 開啟專案、在編輯器中開啟 與 在 Forgejo 中開啟。重新載入頁面或回到其分頁時,會重新讀取工作,不會重複送出任何步驟。離開頁面會停止鏈;專案檢視也有相同的步驟。
當 bvsd 拒絕建立專案(名稱已被資料夾、應用程式或儲存庫使用,或您無法在該擁有者下建立),頁面會回到含有該答案的步驟,在欄位下方顯示原因,並保留其他所有答案。模組已關閉(管理員可從頁面開啟)、尚無 Forgejo 帳號、App Builder 應用程式沒有 Debian 或 Ubuntu 環境,會在「檢閱」中說明。
第一個工作會:
- 以您的身分建立儲存庫,除非您選擇公開,否則為私人。
- 在資料資料夾中建立
projects/<名稱>資料夾並做第一個提交:範本的所有檔案與工作流程.forgejo/workflows/build.yml,位於main。提交屬於您(資料夾中以您的名稱與位址設為作者),範本的指令碼在其中可執行。它以您的身分將此提交推送到儲存庫。origin是儲存庫的 HTTPS 位址,因此您的下一次推送會送到那裡。提交也包含 AI 助理用的技能(.claude/skills/qnap-dev/與AGENTS.md)。資料夾位於編輯器的共用資料夾中:無論儲存庫是私人或公開,每位 developer 的編輯器都會開啟projects/。 - 為專案保留所選的環境(若該範本的 Makefile 已指定每個應用程式的環境則不保留)。若是 App Builder 應用程式,會以預設的配方建立與專案同名的應用程式並將它與專案綁定,因此該應用程式也能建置您加入專案
recipes/資料夾的配方。也會在工作流程第一次執行讀取之前,把您的發佈選擇保留為專案的開關「發佈到 App Center 儲存庫」。
CI 模組開啟後,工作流程會在每次推送時於 NAS 的 runner 上、在工作流程指定的環境中執行。QPKG 工作流程會將套件發佈到套件儲存庫,該儲存庫只接受已程式碼簽署的套件。若儲存庫建立後第一個提交或其推送失敗,工作會移除資料夾、再次刪除儲存庫並說明原因。專案的開關 發佈到 App Center 儲存庫 關閉時,工作流程中的 bvs repo publish 不會發佈,而是顯示一則通知,執行則繼續進行。
專案檢視
資料資料夾中 projects/ 的每個資料夾都有自己的頁面:精靈建立的專案、「編輯器專案」中範例的複本,或您複製到那裡的儲存庫。可從編輯器側邊欄的 專案 分支、「專案」頁面、新專案結束時的 開啟專案,以及命令面板(開啟專案 …,或 Ctrl+P 加上名稱)開啟。需要開發者角色。「專案」頁面上專案的選單也有建置、重新建置、發佈與發佈到網頁目標。同一個選單也能開啟或關閉 CI 發佈到 App Center。
頁面只讀取資料夾,不會自行變更其中任何內容。它從檔案判斷專案類型:與資料夾同名的 App Builder 應用程式、頂層的 qpkg.cfg(QPKG 套件)、頂層的 Makefile,或以上皆非(此時由專案的 CI 工作流程建置)。即使有與資料夾同名的 App Builder 應用程式,頂層有 qpkg.cfg,或有 Makefile 與 qpkg/ 中 qpkg.cfg 的專案,仍保有自己的建置方式,測試部署與發佈也仍取用其 QPKG。
頂端的條列出各步驟。無法執行的步驟會保留按鈕但停用,並在旁邊與條下方說明原因。 專案根本無法進行的步驟會離開這一條,並在條下方以一句話說明專案產生什麼、建置結果會到哪裡:程式在專案資料夾,核心模組在「核心」頁面,只建置 App Builder 應用程式的 Makefile 則在各應用程式的頁面。
- 建置 以工作的形式在底部面板中執行。QPKG 套件以 QDK 的
qbuild建置,Makefile 專案以make建置,兩者都在專案的建置環境中執行。記錄會列出建置寫入build/的每個.qpkg及其是否有程式碼簽章。App Builder 應用程式的建置方式與其自身頁面相同。當 Makefile 的預設目標只執行./bvsapp.sh create與./bvsapp.sh build這兩種行時,建置會透過 App Builder 做同樣的事:先建立create行所指、尚不存在的每個應用程式,再逐一建置這些應用程式。create行的格式為./bvsapp.sh create NAME RECIPES-FILE [ENV] [LINK] [TARGET] [OTHERS]。這種 Makefile 會在.PHONY中列出其預設目標與該目標的先決條件,且只含簡單的指派(每個變數只設定一次)與簡單的規則;含有其他內容(條件、include)的 Makefile 以 make 建置。TARGET 為native、aarch64或armv7,因此一次建置即可產生此 NAS 用與 ARM 64 位元用的應用程式。OTHERS 指靜態應用程式如何處理無法靜態連結的配方(refuse或bundle)。以此方式建立的應用程式也會使用專案自己recipes/中的配方,除非資料夾名稱不是專案名稱(例如含有空格的名稱)。若同名的應用程式已以其他目標存在,或在資料夾有自己的配方時屬於其他專案,建置會保持停用並說明如何修正。第一次建置之前,這一步會列出它要建置的應用程式。 套件位於qpkg/的 Makefile 專案,會在編輯器的終端機以make qpkg產生套件檔;在套件檔出現之前,測試部署、發佈與發佈到網頁會顯示「需要套件檔」。 - 重新建置 從頭建置:先
make clean再make;QPKG 套件會先移除build/中舊的.qpkg。沒有clean目標的 Makefile 無法重新建置,頁面會說明。App Builder 應用程式沒有重新建置,只建立並建置 App Builder 應用程式的 Makefile 也沒有。 - 匯出為 QPKG(管理員)適用於 App Builder 應用程式,與應用程式頁面相同。 發佈會如同應用程式頁面一樣等待匯出,標題中的 開啟應用程式 會開啟該頁面。
- 測試部署 供管理員使用。它以
qpkg_cli將最新的.qpkg安裝到此 NAS,如同 App Center 安裝檔案,工作會等到 App Center 確認為止。在您於 App Center 中移除之前,套件會一直保持安裝。沒有程式碼簽章的套件會被拒絕:測試部署只安裝已簽署的套件,也絕不略過 App Center 的簽章檢查(在 App Center 本身,NAS 的擁有者可以允許沒有簽章的應用程式;此頁面不會這樣做)。請以檔案形式的憑證簽署(QPKG 的程式碼簽署 的情況 1)。Bucket & Code Server IDE 本身的套件會被拒絕,因為安裝它會取代正在執行的套件。對 App Builder 應用程式而言,測試部署會在此 NAS 上啟用其建置。 - 發佈 依套件儲存庫的規則把最新的
.qpkg放入其中:管理員的發佈會成為列出的版本,開發者的發佈要等管理員,沒有程式碼簽章的套件會被拒絕,除非儲存庫接受未簽署的套件。其下方的一行會說明專案的 CI 是否也會發佈到 App Center 儲存庫;這個按鈕無論如何都會發佈。 - 發佈到網頁(管理員)會將最新的
.qpkg,或網站資料夾public/(否則dist/)複製到網頁目標,並透過目標的公開位址讀回。 若是精靈建立的網站,此步驟會等待寫入public/的第一次建置。
Makefile 專案可在 建置 旁選擇目標(除非選擇其他目標,否則為 make 的預設,也就是第一個目標);CMake 專案可只建置,或建置並執行測試。核心模組專案在核心工坊中執行中核心的工作區內建置,此建置由管理員執行。執行中的步驟有 取消,工作通常會立即結束。當工作流程有 workflow_dispatch 觸發條件時,執行工作流程 會手動執行專案的 CI 工作流程;否則按鈕會停用,頁面會說明原因。 每個範本的工作流程都有這個觸發條件。已安裝在此 NAS 列出此專案的測試部署所安裝的套件,管理員可使用 從此 NAS 移除。刪除專案(位於標題按鈕旁的選單,或「專案」頁面上專案的選單)供管理員或其 Forgejo 帳號擁有該儲存庫的開發者使用。須先輸入專案名稱;資料夾會被刪除,Forgejo 儲存庫、同名的 App Builder 應用程式與已安裝的套件會保留。頁面接著會提供儲存庫的連結。
設定 顯示 bvsd 在資料夾之外為專案保留的內容。Makefile、CMake 或 QPKG 專案會顯示建置與重新建置所用的環境,並可變更。對於只建立並建置 App Builder 應用程式的 Makefile,會列出每個應用程式及其在 Makefile 中那一行所指定的環境。產生套件的專案,或工作流程會執行 bvs repo publish 的專案,有開關 發佈到 App Center 儲存庫:開啟時,專案 CI 中的 bvs repo publish 會把其套件加入儲存庫;關閉時,CI 執行會略過該步驟並顯示通知。沒有保留選擇的專案(範例的複本或複製的儲存庫)開關為開啟。Git 顯示分支、依上次 fetch 的結果領先或落後遠端多少(頁面本身從不 fetch)、最新的提交與變更的路徑。檔案 一次列出一個資料夾;選擇檔案即可閱讀,.qpkg 則會下載。編輯在編輯器中進行,.git 資料夾不會列出。
配方 會為擁有自己 recipes/ 資料夾的專案,列出其應用程式使用的配方:每個配方附上版本、若與配方庫中的配方同名則附上它取代的配方庫版本,並在下方列出配方檢查找到的問題與其檔案和行。bvsd 略過的配方有一列說明原因;以相同原因略過的超過三個時,其餘的以一列計數。檢查對整個 recipes 資料夾找到的問題有自己的一列。點一下會在編輯器中開啟配方的資料夾;選單也能複製在 NAS 終端機執行同樣檢查的指令:附上專案資料夾的 bvs recipe lint。當專案的 recipes 是連結、檔案、bvsd 無法讀取的資料夾,或只有連結的資料夾時,也會顯示此卡片,並說明為何不讀取其中任何配方。
服務與套件(QPKG 套件,或像從原始碼建置的套件那樣在 qpkg/ 中有套件的 Makefile 專案)包含以區塊組成的套件啟動與停止腳本、其 qpkg.cfg 的欄位(套件),以及由它們寫出的檔案(腳本)。儲存會先顯示每個檔案的差異,再提交到專案的儲存庫;若專案在這期間有變更,請重新規劃。手動編輯會停用區塊,改由您在編輯器中編輯腳本;重新連結區塊會顯示重新寫入將取代的內容。更新函式庫會將此 Bucket & Code Server IDE 的 bvs-qpkg.sh 連同差異放入套件。在區塊之前建立的專案會提供為此腳本使用區塊。
版本 列出專案可切換的目標,切換到此版本 會執行切換:
| 版本 | 切換時的動作 |
|---|---|
build/ 中的 .qpkg,或 App Builder 的匯出 | 對該檔案進行測試部署(管理員) |
| App Builder 的建置 | 啟用它(管理員);App Builder 只保留一個建置 |
| 套件儲存庫中的版本 | 設為列出的版本(管理員) |
| git 標籤 | 在資料夾中 checkout 該標籤 |
點一下可選取版本;其選單也能測試部署、發佈、發佈到網頁目標或下載 .qpkg。標籤會以 detached HEAD 的方式 checkout,Git 卡片中的 回到 main 會回到分支。資料夾有尚未提交的變更時會拒絕切換,訊息會列出這些變更;請先在編輯器中提交或 stash。勾選兩個版本並按 比較兩者,會列出一方有而另一方沒有的檔案,以及變更過的檔案。兩個標籤或兩個套件以內容比較;套件與提交只以大小比較。在「套件」頁面上,管理員也能將儲存庫的版本安裝到此 NAS(安裝到此 NAS),並套用測試部署的檢查。
自己的網頁伺服器(網頁目標)
網頁目標是管理員將套件或網站發佈到自己網頁伺服器的位置:此 NAS 的資料夾(由 QTS 的 Web Server 提供的 QTS Web 共用,或其他共用資料夾),或 rclone 遠端(SFTP、FTP、WebDAV、S3,在備份的 rclone.conf 中設定),並附上提供服務的公開位址。它們位於「發佈」頁面的 網頁目標 區段:新增目標、變更、移除 與 測試;測試會複製一個小檔案到那裡,從公開位址取回,然後再刪除。
資料夾目標是共用資料夾中專屬的資料夾(/share/Web/mysite,絕不能是整個共用資料夾或磁碟區),位於資料資料夾之外,因為網站發佈會從目標中移除網站已不再包含的內容。位址以 http:// 或 https:// 開頭,不含使用者名稱或密碼。
每次發佈都會透過公開位址讀回檔案:套件的 .qpkg 及其 .sha256 以 sha256 比較,網站的 index.html 則逐位元組比較。當位址提供的不是所複製的內容時,工作會以 web_check: 與兩個值失敗。
CI runner
CI 模組執行 Forgejo Actions:儲存庫 .forgejo/workflows/ 中的工作流程檔案,會在有內容推送時於 runner 上執行。它需要 Git 模組。管理員在 模組、CI、啟用 開啟它。工作會向 Forgejo 註冊 NAS 自己的 runner,以開啟 Actions 的方式重新啟動 Forgejo,並啟動 runner;runner 連上 Forgejo 時工作即結束。
NAS 上的 runner
- 其標籤 為
bucketvs、qnap-x86_64(或qnap-aarch64)與self-hosted,再加上管理員在 CI 頁面設定的額外標籤。runs-on指定其中之一的工作會在這裡執行,例如runs-on: bucketvs。 - 它在 NAS 本身以 admin 身分執行每個工作,不使用容器。工作可使用套件的工具(git、curl、make 等)、執行
actions/checkout等 JavaScript action 的 Node,以及在環境中建置用的bvs env run <env> -- <command>。因此,能把工作流程推送到儲存庫的人,就能在 NAS 上以 admin 身分執行指令。member 與 viewer 在 Forgejo 中不能建立、分叉或匯入儲存庫,也不能建立組織;developer 與 admin 可以。viewer 永遠不能推送。CI 開啟時,member 推送到已開啟 Actions 的儲存庫會被拒絕並說明原因,以部署金鑰推送也一樣。member 推送或以部署金鑰推送到由低於 developer 的帳號擁有或管理的儲存庫,同樣會被拒絕,即使 CI 關閉也一樣:這類帳號可以自行開啟 Actions。bvsd 會在一分鐘內關閉 member 或 viewer 擁有或能寫入的每個儲存庫的 Actions,開啟 CI 時也會在 runner 啟動前關閉。 - 剩下的 是 developer 或 admin 自己的操作:在 member 先前寫入過的儲存庫開啟 Actions 或觸發工作流程,或給予這類帳號對其先前寫入過的儲存庫的管理權限。合併或建置 member 提交的 developer,也會以 admin 身分執行這些程式碼。
- 同時執行的工作數 為
ci.capacity(預設 1)。沒有線上 runner 能接手的工作會在 Forgejo 中等候。 - 在 CI 開啟前建立的儲存庫 其 Forgejo Actions 為關閉,因此推送的工作流程不會啟動任何東西:請在儲存庫的 設定、單元(Actions)中開啟。CI 開啟期間建立的儲存庫則已開啟。
actions/checkout@v4等 Action 會從https://data.forgejo.org下載,因此使用它們的工作流程需要 NAS 能連上網際網路。runner 沒有快取:actions/cache找不到任何東西,工作會繼續進行。- 成品(
actions/upload-artifact)會上傳到 Forgejo 自己的位址(Git 頁面上顯示的那個),因此 NAS 必須能連到該位址,且在 HTTPS 時信任其憑證。 - runner 的狀態 位於
<資料>/runner;其記錄是 記錄 下的 runner。關閉模組會停止 runner,並在 Forgejo 中關閉 Actions。
外部 runner
其他地方的建置機器(伺服器、VM)也可以從這個 Forgejo 接手工作。在 CI 頁面的 註冊外部 runner 下,管理員為它命名,即可取得 Linux x86_64 與 aarch64 用的指令。這些指令會從 code.forgejo.org 下載 forgejo-runner 13.2.0、檢查其 sha256、把 runner 的權杖保存在 runner-token(只有擁有者可讀取),並以標籤 linux-amd64(或 linux-arm64)啟動 runner。runner 會立刻出現在清單中,在指令執行之前顯示為離線。權杖只在此時顯示。這類 runner 在自己的機器上、以啟動它的使用者身分執行工作,並透過公開位址連到 Forgejo。
SVN 與 Bucket
SVN 與 Bucket 模組在 /svn/<名稱> 提供 Subversion 儲存庫,在 /bucket/<名稱> 提供 bucket。bucket 是一種網路磁碟機(WebDAV),每個儲存的檔案都會成為一個修訂版本,因此可以讀取或放回檔案的任何舊版本。管理員在 模組 開啟這個模組後,SVN 與 Bucket 頁面即可建立、列出與刪除這兩種項目。
- 帳號 就是面板的帳號。權限依儲存庫設定:對每個帳號設定讀寫、唯讀或無,另外再為未列出的帳號設定預設值。管理員一律可讀寫;member 與 developer 在有讀寫權限的地方可以寫入;viewer 最多只能讀取。新的儲存庫在管理員設定權限之前(該列的人物圖示,
<name>的權限),除管理員外沒有任何人有權限。低於 admin 的角色在頁面上會看到自己對每個儲存庫與 bucket 的權限。 - 密碼錯誤 的計算方式與面板登入相同:15 分鐘內輸錯 5 次密碼,會把該帳號從該位址鎖定 15 分鐘,該位址本身也會被鎖定。
- 兩步驟驗證。 開啟兩步驟驗證的帳號不以密碼使用 SVN 或 WebDAV,而是在其帳號頁面(WebDAV 和 SVN 用的應用程式密碼)建立一組 應用程式密碼:25 個隨機字元,只顯示一次。建立新的會取代舊的;變更密碼或關閉兩步驟驗證會移除它。
- 刪除 儲存庫會把它移到
<資料>/trash,7 天後由trash工作移除。
SVN 儲存庫
svn checkout "https://<NAS 位址>:9951/svn/<名稱>"
svn commit -m "…"
頁面會顯示含儲存庫位址的 checkout 指令。在 Proxy 後方時,位址會依照公開 URL;有 SVN 主機名稱時,則是該名稱上的 /svn/<名稱>。儲存庫的 歷史記錄 列出其修訂版本;檔案可以在任何修訂版本中讀取、與其他版本比較,並以新的修訂版本放回(還原此版本,限具讀寫權限的帳號)。
Bucket
- 儲存就是提交。 用戶端儲存檔案時,會以帳號名稱與時間建立一個修訂版本;該修訂版本會標記為經由 WebDAV 建立。許多用戶端會先寫入空檔案再寫入資料,因此一次儲存可能產生兩個修訂版本。
- macOS 檔案。 以 拒絕 macOS 的 ._\* 和 .DS_Store 檔案(預設)建立的 bucket,不會儲存 Finder 寫在所複製內容旁的
._*與.DS_Store檔案。用戶端不會收到錯誤,但檔案永遠不會成為修訂版本。可以刪除這類檔案。 - 回到舊版。 bucket 的歷史記錄會顯示每個檔案的各個版本;還原此版本 會把舊內容儲存為新的修訂版本,因此不會遺失任何東西。
WebDAV 用戶端與其限制
| 用戶端 | 連線方式 | 備註 |
|---|---|---|
| macOS Finder | 前往、連接伺服器、https://<NAS 位址>:9951/bucket/<名稱> | Finder 寫入檔案時會鎖定它;bucket 會回應 WebDAV 鎖定 |
| rclone | 設定 vendor = other 與 bucket 位址的 webdav 遠端 | 適合以指令碼複製 |
| davfs2(Linux) | mount -t davfs https://<NAS 位址>:9951/bucket/<名稱> /mnt/<資料夾> | 面板的使用者名稱,以及密碼或應用程式密碼 |
| Cyberduck、WinSCP | 以 WebDAV(HTTPS)連到連接埠 9951,路徑 /bucket/<名稱> | |
| curl | curl -T file -u <使用者> https://<NAS 位址>:9951/bucket/<名稱>/file | 一次上傳,一個修訂版本(或兩個,見上方) |
| Windows 檔案總管 | 連線網路磁碟機 | Windows 的 WebClient 只會透過使用 Windows 信任憑證的 HTTPS 傳送密碼:請把 bucket 放在具有正式憑證的 Proxy 後方(在反向 Proxy 後方);自我簽署憑證不夠 |
- 大型檔案不會被截斷:nginx 不對
/bucket/設定內容大小上限,並在上傳資料抵達時直接轉送。 - 對 bucket 拒絕儲存的檔案(上述的 macOS 檔案),WebDAV 伺服器仍會回應
201,因此用戶端不會顯示錯誤;但該檔案並不在 bucket 中。
讓沒有帳號的人檢視儲存庫或 bucket
管理員可以在 SVN 與 Bucket 頁面的該列上,以開關(網頁公開)公開 SVN 儲存庫或 bucket。任何知道位址的人都能以瀏覽器閱讀,不需帳號:
| 位址 | 顯示內容 |
|---|---|
https://<NAS 位址>:9951/svn-web/<名稱>/ | SVN 儲存庫 |
https://<NAS 位址>:9951/bucket-web/<名稱>/ | bucket |
該列的 在網頁上檢視 連結會開啟這個頁面。頁面列出最新或較舊修訂版本的檔案與資料夾,以行號顯示文字檔(最多 1 MiB)或顯示圖片,並提供每個檔案的下載。歷史記錄 列出修訂版本及其作者、訊息與變更的檔案。修訂版本頁面會顯示其變更的每個檔案的差異(最多 20 個、每個最多 1 MiB 的檔案;其餘為連結);任何檔案都能在兩個修訂版本之間比較。
- 唯讀。 這些頁面無法變更任何內容。WebDAV 用戶端與
svn仍需要帳號,公開儲存庫也一樣。 - 只顯示公開內容。 未公開的儲存庫與不存在的名稱,都會回應「There is no public repository at this address」,因此頁面不會透露哪些名稱存在。
- 限制。 一個位址一次最多開啟 60 個頁面,之後每秒 2 個,並同時下載 2 個檔案;超過時頁面會請您稍後再試。差異超過 2 MiB 會被截斷。
- 搜尋引擎 會被要求不要索引這些頁面。頁面為英文。頁面採用面板的外觀,依訪客瀏覽器的設定顯示深色或淺色。
- 在 Proxy 後方或有 SVN 主機名稱時,位址會依照儲存庫本身的位址(公開 URL,或路徑相同的 SVN 主機名稱)。
編輯器與 AI 工具
編輯器模組為每個 developer 與 admin 帳號執行瀏覽器中的 VS Code(code-server)。管理員在 模組 開啟它。每個帳號都有自己的執行個體,在帳號開啟編輯器時啟動,並在一段時間沒有流量後停止。
編輯器的終端機是 NAS 上的 root shell。 在 QTS 上,除了 Forgejo 與 httpd,套件的程序都以 admin(uid 0)執行。請只把 developer 角色交給您願意告知 NAS admin 密碼的人。
開啟編輯器
- 「編輯器設定」頁面上的 開啟編輯器(或面板位址的
/ide/,或編輯器主機名稱)會在新分頁開啟工作台。第一個請求會啟動執行個體;沒有工作階段時,會先顯示面板的登入。 - 透過已發佈的主要主機名稱,只要編輯器尚未在那裡發佈,「編輯器設定」頁面、「編輯器」分頁、總覽與 開啟 shell 會說明編輯器只能從區域網路開啟,並連到它的區域網路位址(
https://<NAS 位址>:<HTTPS 連接埠>/ide/);對管理員也會連到 發佈 頁面的開關。 - 編輯器會開啟
<資料>/projects,「編輯器專案」中的範例會把專案放在這裡。帳號的設定、擴充功能與終端機歷史記錄保存在<資料>/ide/<帳號>,家目錄在<資料>/home/<帳號>。 - 終端機的
PATH最前面是套件的工具:git、svn、node、npm、rsync、curl、bash 等。bvs env shell <名稱>會進入工具鏈的環境,eval "$(bvs use <id>)"會設定好工具鏈或執行環境。工具鏈頁面上的 開啟 shell 會開啟編輯器,且終端機已位於該環境中。 - 編輯器 活動與命令選擇區可以開啟編輯器,並直接進入環境中的 shell 或應用程式的資料夾。編輯器顯示在面板的「編輯器」分頁中;在手機上則在自己的瀏覽器視窗中開啟。只有面板本身位址的頁面才能在頁面中顯示編輯器:套件在編輯器的每個回應中都會這樣告知瀏覽器,因此其他網站無法把編輯器的 root 終端機嵌入自己的頁面。
- 閒置時間(預設 30 分鐘)會停止沒有瀏覽器流量的執行個體,但只要從其終端機啟動的程式、擴充功能啟動的 AI 代理(Claude Code for VS Code 的
claude、Codex、Gemini CLI),或從那裡留著執行的程式仍在執行,就不會停止。設為 0 會關閉閒置停止。帳號可以在「編輯器設定」頁面停止自己的執行個體;管理員可以停止任何執行個體。 - 「編輯器設定」頁面的 記憶體與程序 顯示執行個體執行的東西,以及它相對於 NAS 記憶體所佔用的記憶體,標出讓它繼續執行的程序,用 結束 結束單一程序,並說明上次停止的原因與它結束了什麼。在提示字元等待輸入的 AI 代理也會讓執行個體繼續執行:不再需要時,就在那裡結束它。
- VS Code 的 Ports 檢視可透過
/ide/proxy/<port>/連到 NAS 上的開發伺服器;套件自己的 loopback 連接埠在此會被拒絕。 - 在 Explorer 中專案的
recipes資料夾或其中配方資料夾的選單裡,New recipe 會詢問名稱,並在那裡以套件的入門配方寫入新的配方:recipe.json與build.sh。在命令選擇區中它是 Bucket: New recipe,只要開著某個有recipes資料夾的專案中的檔案就能使用。每次儲存配方中的檔案時,編輯器會以bvs recipe lint檢查專案的配方,並在 Problems 檢視中列出結果。在您填入來源真正的 sha256 之前,它會對入門配方的 sha256 發出警告。
編輯器只回應自己的頁面。其他頁面帶著帳號的工作階段送出的 WebSocket、表單或指令碼請求,無論來自其他網站或 NAS 的其他連接埠,都會得到 403 且不會啟動任何執行個體,因此其他頁面也無法觸及 Ports 檢視背後的開發伺服器。
擴充功能
- 在編輯器的 Extensions 檢視(Ctrl+Shift+X)中安裝擴充功能。擴充功能來自 Open VSX:瀏覽器在 open-vsx.org 搜尋,並從 openvsx.eclipsecontent.org 顯示每個擴充功能的頁面與圖示,擴充功能本身則由 NAS 從 open-vsx.org 下載。因此瀏覽器與 NAS 都需要連得上網際網路。
- 每個發行者的第一個擴充功能會詢問「Do you trust the publisher …?」。Trust Publisher & Install 會安裝它;在那之前擴充功能顯示「Installing」。
- 每個帳號的擴充功能保存在
<資料>/ide/<帳號>/extensions,套件更新後仍會保留。 - 套件附帶一組擴充功能與格式化工具,編輯器會在每個帳號第一次啟動時安裝,套件更新帶來新的一組時也會再安裝。有了它,編輯器會為 Markdown、shell 指令碼、C、C++、Rust、Go、Pascal、Python、Perl、PHP、JSON、YAML、TOML、nginx 設定、CSS、HTML、JavaScript 與 TypeScript 上色並格式化(命令選擇區中的 Format Document)。ShellCheck 會標出 shell 指令碼中的問題,systemd 單元檔有上色與自動完成,專案的
.editorconfig決定縮排,#ff8800或rgb(0, 128, 0)這類色碼在任何檔案中都以其顏色顯示,命令選擇區中的 Hex Editor: Open Active File in Hex Editor 會顯示檔案的位元組。 - 在工具鏈頁面安裝 Rust 執行環境,且帳號的編輯器重新啟動後,Rust 才能格式化;在那之前,於 Rust 檔案中執行 Format Document 會顯示要求失敗。
- 在 ARM 架構的 NAS(aarch64 套件)上,Pascal、Perl 與 PHP 只會上色、不會格式化:套件沒有為它建置的 Free Pascal、Perl 或 Mago。
- 帳號在 Extensions 檢視中移除的這組擴充功能會保持移除,套件更新後也一樣;帳號自行更新的則保留較新的版本。為某個語言選定的預設格式化工具(Format Document With…,再選 Configure Default Formatter…)仍是帳號自己的選擇。
- 所有
.conf檔案都會以 nginx 設定開啟。按狀態列上的語言名稱,可把檔案切換成其他語言。 - 格式化 Python 的 Ruff 會提示一次:沒有安裝 Python 環境的擴充功能。沒有它也能格式化。
- 在編輯器的終端機中執行
code-server --install-extension <發行者.名稱>,也會從 Open VSX 安裝擴充功能。 - 有些擴充功能會繪製自己的檢視,例如 Claude Code for VS Code 的面板、十六進位編輯器與 Markdown 預覽。只有瀏覽器信任面板的憑證時,才會顯示這些檢視。若自我簽署憑證只是在瀏覽器的警告頁面上接受,這些檢視會保持空白,「編輯器」分頁與「編輯器設定」頁面會說明這一點。以下任一方式都能解決:
- 在裝置上信任 NAS 的憑證:在「網路」頁面或該通知中按 下載憑證,再把它加入系統或瀏覽器的受信任憑證(憑證);
- 由管理員在「網路」頁面新增 NAS 名稱的憑證;
- 管理員在已發佈的主要主機名稱上發佈編輯器後,經由該主機開啟編輯器。
- Claude Code for VS Code(發行者 Anthropic)可從 Extensions 檢視安裝,它的面板會詢問如何登入 Anthropic。命令選擇區中的 Claude Code: Open in Terminal 會在終端機中執行 Claude Code,這在任何憑證下都能運作。VS Code 自己的聊天功能一開始是關閉的(
chat.disableAIFeatures);這個設定不會影響這個擴充功能。
Claude Code、Gemini CLI 與 Codex CLI
在「編輯器設定」頁面的 AI 命令列工具 下,每個帳號可為自己安裝、更新與移除這些工具:
| 工具 | 安裝方式 | 指令 |
|---|---|---|
| Claude Code | Anthropic 的安裝程式(claude.ai/install.sh),失敗時改用 npm | claude |
| Gemini CLI | npm install -g @google/gemini-cli | gemini |
| Codex CLI | npm install -g @openai/codex | codex |
- 工具會安裝到帳號的家目錄(
~/.local/bin、~/.npm-global/bin),這些位置在終端機的PATH中;其他帳號看不到它們。 - 每次安裝都是一個工作,其記錄可在工作頁面查看。登入各工具(帳號或 API 金鑰)是在編輯器的終端機中、於工具本身內完成。
與 AI 助理一起寫程式
新專案 建立的每個專案都帶有給 AI 助理的技能:.claude/skills/qnap-dev/ 以及指向它的 AGENTS.md。這個技能以英文寫成,包含與 QNAP NAS 相關一切事項的準則:它在 shell 中是什麼樣子(RAM 磁碟上的根目錄、BusyBox、沒有 systemd 也沒有套件管理員、getcfg 和 setcfg)、儲存與路徑、如何用本套件建置、簽署和發布(bvs env run、bvs ldd、bvs qbuild、App Builder、核心工坊、套件儲存庫)、連接埠、備份,以及它不可以建議的事,例如在 NAS 上用 apt,或在 App Center 中允許未簽署的應用程式。它清楚寫明,用硬體權杖簽署不受支援也未經測試。
- 請在專案的資料夾中啟動助理(
cd <資料>/projects/<名稱>),而不是在projects/中:每個工具都會在它啟動的資料夾中尋找。 - Claude Code 會在工作需要時從
.claude/skills/載入技能。Codex CLI 會讀取AGENTS.md。Gemini CLI 在專案的.gemini/settings.json含有{"context": {"fileName": ["AGENTS.md", "GEMINI.md"]}}之後就會讀取AGENTS.md。 - 套件把目前的技能保存在
/usr/bin/bucketvs/share/skills/qnap-dev。在套件具備技能之前建立的專案,或從範例庫複製的專案,只要把這個資料夾複製到專案的.claude/skills/即可取得。 - 關於 NAS 有什麼、缺什麼,技能引用 QNAP Club Poland 的知識庫(forum.qnap.net.pl)。
- 套件的建置也會把技能寫成
qnap-skill-<版本>.zip,內容是相同的檔案,可在編輯器之外使用:解壓到專案的.claude/skills/或~/.claude/skills/。技能的文字以 CC BY 4.0 授權(見其LICENSE):只要附上「QNAP guidelines skill by QNAP Club Poland / qnaputilities.com, CC BY 4.0」這行署名,就可以分享和改作。
工具鏈與環境
工具鏈頁面會下載在 NAS 上建置軟體所需的內容:
| 類型 | 說明 | 範例 |
|---|---|---|
| 根檔案系統 | 可解壓縮到環境中的 Linux 系統 | Debian 12 與 13、Ubuntu 22.04 與 24.04、Alpine 3.22 |
| 交叉工具鏈 | 為其他處理器建置的編譯器 | 適用 aarch64、x86-64 與 armv7 的 Bootlin 工具鏈,搭配 glibc 或 musl |
| 執行環境 | 程式語言或建置工具 | Python、Go、Node.js、Zig、Rust、CMake、Ninja、Java(JDK) |
| QNAP | QNAP 自己的工具 | QDK 2.5.0,供 bvs qbuild 與匯出為 QPKG 使用 |
| 核心原始碼 | 供核心工坊使用的 Linux 核心樹 | 來自 kernel.org 的 Linux 6.6.129;QNAP 針對 QTS 5.2.3 發佈的 GPL 核心 |
其他處理器的項目預設隱藏;「顯示其他處理器的項目」會列出它們,但無法安裝。Bootlin 工具鏈在 x86_64 上執行,因此 ARM 的 NAS 沒有交叉工具鏈。
目錄
套件內建一份目錄。位於 https://pub.qnaputilities.com/bucketvs/catalog.json 的已簽署遠端目錄,可以在不更新套件的情況下新增項目。只有當其 ed25519 簽署與套件內建的金鑰相符,且不比目前使用的目錄舊時,bvsd 才會使用它。「重新整理目錄」會立即取得它,內建的 cron 工作「重新整理工具鏈目錄」每天 04:15 取得它。
安裝與移除
安裝由管理員進行,其進度顯示在工作頁面:
- 封存檔會下載到資料目錄的
toolchains/cache/。中斷的下載會在重新開始安裝時續傳。 - 以目錄檢查其 sha256。不相符時會刪除該檔案。
- 交叉工具鏈或執行環境會解壓縮到
toolchains/<kind>/<id>,並刪除其封存檔。根檔案系統或核心原始碼會保留為封存檔;每個環境或核心工作區都會解壓縮自己的副本。QNAP 把其 GPL 核心分成兩部分發佈:兩部分都會下載,各自以自己的 sha256 檢查後再合併。
磁碟區已滿時,安裝會以「no space left on」與該磁碟區的掛載點失敗。
「移除」會刪除已安裝的項目。從根檔案系統建立的環境是副本,會保留。
使用工具鏈或執行環境
bvs use <id> 會印出讓已安裝的交叉工具鏈或執行環境可在 shell 中使用的 export 行(例如 PATH):
eval "$(bvs use bootlin-aarch64-glibc-stable)"
工具鏈頁面也會在每個已安裝項目的「bvs use」下顯示相同的行。
環境
環境是從根檔案系統解壓縮到資料目錄 envs/<名稱> 的 Linux 系統。它可以變更:在 Debian 或 Ubuntu 環境中可以執行 apt install build-essential,安裝的內容會保留在其中。
- 「新環境」(管理員)會在根檔案系統尚未安裝時先下載它,再解壓縮。
- 在還沒有任何環境時,清單會以一個按鈕提供應用程式範例建置所用的 Ubuntu 24.04 builder(管理員):其工作會顯示在清單中,工作完成後環境就會出現。不會自動建立任何環境。
- 名稱為 1 到 64 個字元:小寫英文字母、數字、
.、_或-,以字母或數字開頭。 - 範例庫中的預設組合,會在環境出現前以 apt-get 安裝套件:含 App Builder 建置工具與 patchelf 的 Ubuntu 24.04 建置器(預設建置器)與 Debian 12 建置器(兩者皆為完整版),以及 Clang/LLVM(LLVM 18)、Fortran(gfortran 13)、Kernel builder、.NET 8 SDK 與 Kotlin(Kotlin 1.3.31),這些全都在 Ubuntu 24.04 上。每個預設組合的 glibc 都不高於 2.39,因此在其中建置的東西可以在套件能執行的每一台 NAS 上執行(應用程式能在哪些 NAS 型號上執行)。apt-get 失敗時不會留下環境。從 shell 執行:
bvs env create <名稱> --from <rootfs-id> --package <名稱> --package <名稱>。 - 「複製」會以新名稱建立完整副本,例如在不動到原始環境的情況下試驗變更。
- 「匯出」會把環境打包成
toolchains/exports/<名稱>-<時間>.tar.zst。 - 「刪除」會移除環境。環境中有 shell 或程序執行時,bvsd 會拒絕。
projects/中的檔案不屬於環境,會保留。
在環境中:
- 資料目錄的
projects/會以/projects出現,shell 從那裡開始; HOME是環境的/root,LANG是C.UTF-8;- 會掛載
/proc、唯讀的/sys與一個自己的小型/dev,並把 NAS 的resolv.conf與hosts複製進去; - 這些掛載屬於 shell 自己的掛載命名空間,shell 結束時就會消失,因此 NAS 上不會留下任何掛載。
從 shell 做同樣的事(範例直接以名稱呼叫 bvs;套件執行期間,cron 工作和 NAS 上的 SSH 工作階段都可以這樣呼叫):
bvs env list
bvs env create deb12 --from debian-12-x86_64
bvs env shell deb12
bvs env run deb12 -- make -C /projects/hello
bvs env shell 與 bvs env run 會在您執行它們的資料夾中開始。資料目錄 projects/ 下的資料夾,就是環境中 /projects 下的同一個資料夾。其他任何資料夾(CI 工作的 checkout、共用中的資料夾)會掛載到 /work,指令從那裡開始。從 / 執行時,會從 /projects 開始。
用 bvs qbuild 建置 QPKG
bvs qbuild 會從您執行它的資料夾(含有 qpkg.cfg 的資料夾,例如新專案的 QPKG 範本所建立的資料夾)建置 QPKG。它在 Debian 或 Ubuntu 環境中執行 QNAP 的 qbuild。qbuild 以完整路徑呼叫系統程式,而在環境中,這些路徑指向環境的程式,而不是 NAS 本身的程式。套件會產生在資料夾的 build/ 中。
bvs tc install qdk-2.5.0-x86_64 # 只需一次;ARM 的 NAS 用 qdk-2.5.0-aarch64
cd /share/CACHEDEV1_DATA/BucketVS/projects/MyTool
bvs qbuild # --env <名稱> 選擇環境
它使用環境 ubuntu2404-builder(範例「Ubuntu 24.04 builder」),沒有時使用 debian12-builder,再沒有時使用其他 Debian 或 Ubuntu 環境,且其中需要 rsync。缺少某些東西時,它會停止並指出加入它的指令,例如 bvs env run ubuntu2404-builder -- apt-get install -y rsync。bvs qbuild 之後的參數會交給 qbuild。除非資料夾中有 certificate 與 private_key 檔案(可選 ca_certs),否則套件沒有程式碼簽署:有這些檔案時,QDK 的 qbuild 會用 openssl 簽署,因此環境需要 openssl。請勿把這些檔案放進 git。
環境有自己的檔案與工具。其中的一切都以 root 執行,看得到 NAS 上的每個程序,並使用 NAS 的網路。
QPKG 的程式碼簽署
App Center 安裝套件時會檢查它的程式碼簽章。簽署需要 QNAP 發給您的程式碼簽署憑證。bvs qbuild 會在第一行說出三種情況之一,例如 bvs: code signing, case 1 (a certificate as files): …:
| 情況 | 資料夾中有 | 會發生什麼 |
|---|---|---|
| 1,檔案形式的憑證 | certificate 和 private_key,可另加 ca_certs(憑證鏈) | qbuild 用 openssl 簽署套件;環境需要 openssl 和 bsdextrautils |
| 2,硬體權杖上的憑證 | certificate_hsm | 不支援也未經測試:bvs qbuild 會在建置任何東西之前停止 |
| 3,沒有憑證 | 以上檔案都沒有 | 套件以未簽署的方式建置 |
- 情況 1。 把三個檔案放在
qpkg.cfg旁邊。環境缺少程式時,bvs qbuild會說出指令,例如bvs env run ubuntu2404-builder -- apt-get install -y openssl bsdextrautils。它會拒絕只有certificate和private_key其中之一的資料夾(qbuild 會發出警告並建置未簽署的套件),以及其中任一檔案為空的資料夾。請讓這些檔案不進 git:QPKG 範本的.gitignore已列出它們。在 CI 中,把它們存成儲存庫的 secrets,只在建置期間寫入資料夾。 - 情況 2。 qbuild 會從變數讀取金鑰在權杖上的位置,但這些變數在環境中傳不到它,而且本套件沒有用權杖測試過。請不帶
certificate_hsm建置,再到持有權杖的電腦上用 QDK 自己的工具簽署套件;給 AI 助理的 QNAP 技能(references/signing.md)說明了 QDK 的做法,本套件從未執行過。 - 情況 3。 在一台 QTS 6.1 的機器上,對未簽署套件執行
qpkg_cli -m沒有安裝任何東西,而在共用資料夾中執行sh <檔案>.qpkg則安裝並啟動了它。套件儲存庫只有在管理員允許未簽署套件時才接受它;另一台 NAS 上的 App Center 只有在該 NAS 的擁有者允許沒有有效數位簽章的應用程式時才會安裝它,本套件從不建議這樣做。匯出為 QPKG 一律屬於這種情況。 qbuild --sign會加上 GnuPG 簽章,這不是 App Center 和儲存庫讀取的程式碼簽章。
App Builder
App Builder 在環境中把選定的程式編譯到單一資料夾,也就是應用程式的前綴(預設為 /usr/app/my_app_prefix)。
應用程式 的 範例 分頁有現成的應用程式、環境、CI 工作流程、cron 工作與編輯器專案。卡片上的 檢視程式碼 會在使用前顯示範例會建立的內容,任何角色都能用:編輯器專案的檔案、工作流程檔、cron 工作的命令,應用程式則是依建置順序列出的配方,以及每個配方的 build.sh 與 recipe.json。檢視器為唯讀,只顯示文字檔;環境沒有檔案,所以它的卡片沒有這個按鈕。使用範例需要 developer 角色,環境則需要 admin 角色:developer 看到的環境卡片沒有 使用此範例。
配方
每個程式都從一個配方建置。配方會寫明其原始碼與 sha256、所依賴的配方、環境所需的建置工具,以及證明結果可用的檢查(例如 bin/bash --version)。現有的配方包括函式庫(zlib、openssl、ncurses、readline 等)、shell(bash、zsh、busybox)、工具(coreutils、curl、git、jq、rsync、tmux、htop、nano 等)、伺服器(nginx、redis、openssh、dropbear)與一種程式語言(lua)。
- 配方只會在其所依賴的配方之後建置。
- 只要配方的輸入不變(原始碼、配方、其相依項目、環境的編譯器與 C 函式庫、前綴,以及動態或靜態連結),且其安裝的每個檔案仍在前綴中,重新建置時就會沿用配方的結果。
- 連結方式決定程式如何找到其函式庫。動態 會給每個程式
<prefix>/lib的 RUNPATH。relocatable 以相對於程式本身資料夾的方式寫入($ORIGIN/../lib),因此這個樹狀結構放在任何資料夾都能找到函式庫;但編譯進程式的路徑(例如 terminfo 資料夾)仍指向前綴。bundle 除了 relocatable 之外,還會把程式從建置環境載入的函式庫(例如 libstdc++)複製到lib,因此應用程式只需要 NAS 的 C 函式庫。靜態 會以靜態方式連結支援的配方。在動態、relocatable 與 bundle 之間切換不會重新建置任何東西。 - 靜態應用程式會拒絕無法靜態連結的配方(openssh、dropbear 與 tmux),並逐一說明原因,除非應用程式設定為以 bundle 建置它們。新應用程式頁面與 變更 提供全部四種方式,靜態應用程式還能設定該選項。
- 查詢使用者、群組或主機名稱的靜態程式,無論
/etc/nsswitch.conf如何設定,都只會從 NAS 本身的/etc/passwd、/etc/group、/etc/hosts與 DNS 讀取,因此不認得網域或 LDAP 的帳號。需要這些帳號時,請以動態方式建置這類程式。靜態應用程式包含這類程式時,面板會顯示警告。 - 最後一個配方完成後,會在完成的前綴上再次執行每個配方的檢查。
- 前綴
etc/下的設定檔在重新建置後仍會保留:編輯過的檔案會保留,新的預設檔案則以<file>.bvs-new放在旁邊。
配方更新
新的和更新過的配方也會以簽署過的目錄形式從 pub.qnaputilities.com 提供,因此不必等下一個 Bucket & Code Server IDE 版本就能送到 NAS。 bvsd 每天檢查一次是否有更新的目錄。只有在簽章與內建於 bvsd 的金鑰相符、每個檔案都與目錄的清單相符、且配方比隨套件提供 的更新時,才會使用;未通過檢查的目錄永遠不會被使用。目錄使用中時,新應用程式的配方清單會把目錄帶來的配方標示為 目錄新增 或 目錄更新。
應用程式頁面的 配方庫 卡片會顯示建置使用哪個配方庫(附套件版本的 套件配方庫,或附目錄版本的 目錄),以及 上次檢查和結果。管理員在那裡有兩個按鈕(第二個只在目錄使用中時出現):
- 檢查配方更新 立即檢查,不必等每天的檢查。
- 使用套件的配方庫 回到隨 Bucket & Code Server IDE 提供的配方。目錄會被擱置,直到有更新的目錄;之後建置就使用較新的那一個。
切換之後重新建置時,檔案沒有變動的配方都會重複使用。每次建置前,bvsd 都會再次檢查目錄的檔案。若有檔案在 NAS 上被改動, 建置會在執行任何東西之前停止,之後的建置改用前一個目錄或套件配方庫。
建置應用程式
應用程式、新應用程式(developer 角色)會詢問名稱、前綴(除非另選,否則為 /usr/app/<名稱>)、應用程式建置所在的環境(Debian 或 Ubuntu 環境;範例庫可建立「Ubuntu 24.04 builder」,頁面會優先選擇它)、目標(這台 NAS 的架構,或以交叉建置產生 aarch64 或 armv7)、應用程式能執行的 NAS 型號、連結方式與配方。它們所依賴的配方會依建置順序加入。
應用程式也可以使用一個擁有自己 recipes/ 資料夾的專案的配方。在 套件 步驟的 專案的配方 中選擇該專案。專案的配方會列在最前面,位於專案名稱之下並標示 專案,之後才是配方庫的配方。與配方庫中某個配方同名的專案配方,會在此應用程式中取代該配方,並顯示它取代的配方庫版本。專案略過的配方會連同原因列出。已選的配方若不在專案的清單中,會在選單下方列出並從應用程式中略過;選擇含有它的清單後,它會再回來。應用程式頁面會顯示專案名稱,開發者可從該名稱開啟專案檢視。viewer 會看到應用程式上次建置的配方,依其記錄列出的順序,各附狀態與記錄;第一次建置之前沒有可顯示的順序。
每種連結方式都是一張卡片,附有程式在哪裡找到函式庫的圖示、該方式在大小、更新與應用程式執行位置上的代價,以及支援它的配方。在您選擇配方之前,卡片計算的是整個配方庫;回到第一步時,則計算您這次建置的配方。對靜態應用程式,您要選擇無法靜態連結的配方如何處理:以 bundle 建置,或不納入。
- 建置(或 重新建置)會執行一個工作:下載每個原始碼並檢查其 sha256,在環境中安裝配方所需的建置工具,在應用程式上一次建置的副本中建置,並檢查每個程式。
- 失敗、取消或中斷的建置會讓應用程式維持原狀:啟用、下載與匯出會繼續使用最新一次成功的建置。
- 一個應用程式一次只執行一個建置;使用中應用程式的程式在執行時,建置會等候(請先停止它們)。
- 應用程式頁面會顯示建置順序、每個配方的狀態與記錄、前綴下的檔案,以及最新一次成功建置的封存檔(下載,一個
.tar.zst)。 - 應用程式頁面上的 變更 可以設定其他環境、應用程式能執行的 NAS 型號、連結方式、取用配方的專案或配方;下一次建置會套用。
- 相依性 是應用程式頁面的一個分頁,顯示最新建置中每個 ELF 檔案需要什麼,以及 NAS 的載入器在哪裡找到它,全程只讀取、不執行任何東西。缺少的函式庫、函式庫未定義的版本,或指向應用程式外部的 RUNPATH,都會以附修正方式的發現列出。developer 可用按鈕執行修正:加入 … 並建置、切換為 … 並建置、再次建置、修補 RUNPATH、設定直譯器、選擇其他環境 或 只為這台 NAS 建置。沒有按鈕的修正(在環境中安裝套件、為其他機器建置)是說明該怎麼做的句子。發現下方以圖(程式、應用程式的函式庫、NAS 的函式庫與缺少的函式庫分欄排列;虛線表示函式庫缺少的版本,點線表示到處都找不到的函式庫)或樹狀結構畫出每個檔案及其需求;選擇檔案即可查看詳細資料。在 NAS 上,
bvs deps <app>會印出相同的內容。 - ELF 檢視器(工具鏈,developer 角色)檢查單一檔案:來自應用程式的建置、專案資料夾或環境的檔案,管理員則可檢查 NAS 上的任何檔案,並依它在這台 NAS 上或環境中執行的情況檢查。
bvs ldd <file>在 NAS 上做同樣的事(環境用--env <name>)。 - 每次建置 都會在取代應用程式前對結果執行相同的檢查;若有會讓程式無法在這台 NAS 上執行的問題,或有程式需要比應用程式允許的更新的 glibc,建置即失敗,問題與修正方式會寫在工作的訊息中。
- 修補工具(相依性分頁)會以環境的 patchelf,為最新建置中選定的檔案設定 RUNPATH(應用程式的
lib、$ORIGIN形式或應用程式的某個資料夾)或程式直譯器;操作在副本上進行,只有成功時才取代建置。預覽 會顯示每個檔案修改前後的樣子,以及新的 RUNPATH 在應用程式中找不到的函式庫;套用修補 會執行它。下一次建置會再以應用程式的連結方式寫入 RUNPATH。
Qt 的建置會執行 Qt 自己的工具(moc、rcc,以及翻譯用的 Linguist lrelease)。因此在交叉建置中,Qt 的配方(qtbase、qttools)會先為這台 NAS 把這些工具建置到前綴下的 host/,再為目標建置 Qt;以 Qt 建置的配方會從那裡執行這些工具。目標上沒有任何東西會執行 host/。它是應用程式建置的一部分,因此封存檔與 匯出為 QPKG 也會包含它。
自己的配方
當配方庫沒有某個程式的配方時,專案可以帶著自己的配方。配方放在專案的 recipes/ 資料夾中,格式與配方庫相同,只有指定該專案的應用程式才會建置它們。以這種方式製作套件共有五個步驟:
- 建立專案。 在 新專案 中,範本 Package from source(從原始碼建置的套件)會建立一個資料夾,內含以專案命名的入門配方、一個用於兩個應用程式(一個給這台 NAS 的處理器,一個給 aarch64,在 x86_64 的 NAS 上為交叉建置)的 Makefile,以及由 服務 步驟產生的套件啟動與停止腳本。
- 撰寫配方。 編輯器中的 New recipe 會從同一個入門配方再新增一個配方(開啟編輯器)。在
recipe.json中填入程式來源真正的位址與其 sha256(在編輯器的終端機執行curl -fsSL <位址> | sha256sum會印出該值),並把建置步驟寫進build.sh。配方資料夾只放recipe.json、build.sh,以及recipe.json指定的 vendor 檔案,因此修補要以 here-document 的形式寫進build.sh。 - 檢查。 每次儲存配方中的檔案,都會檢查專案的配方,並在 Problems 檢視中列出結果;終端機中的
make lint與 專案檢視 的 配方 卡片會得到相同的結果。檢查只讀取recipe.json,並以bash -n剖析build.sh,從不執行配方。 - 建置。 專案檢視中的 建置 會在兩個應用程式不存在時建立它們,再依序建置。建置在開始時只讀取一次專案的配方,因此之後才儲存的檔案要等下一次建置。與配方庫中某個配方同名的專案配方,只會在此專案的應用程式中取代該配方,建置記錄會註明這一點。
- 打包並安裝。 在編輯器的終端機執行
make qpkg,會以工具鏈中的 QDK 把每個應用程式最新的成功建置打包成套件,沒有成功建置的應用程式則略過。若程式碼簽署檔案放在qpkg.cfg旁的qpkg/中,或放在QPKG_CERT_DIR指定的資料夾中,套件就會被簽署(QPKG 的程式碼簽署),而專案檢視中的 測試部署(admin)會把它安裝到這台 NAS。
專案的配方有幾條規則:
- 專案略過的配方(資料夾中多出的檔案、連結、超過大小上限的檔案)會在配方卡片與檢查結果中連同原因列出,需要它的建置會被拒絕。
- 專案資料夾被改名或刪除後,它的應用程式就無法建置:建置會回應「沒有專案『…』」,直到在應用程式頁面的 變更 中設定專案的新名稱或 無:僅配方庫。
- 專案的配方與配方庫的配方一樣,在建置環境中以 root 執行。任何開發者都能撰寫並建置它們,就像任何開發者都能透過建置執行專案的 Makefile。viewer 只會在建置記錄中看到應用程式的配方名稱,看不到配方檔案。
- 專案的配方留在它的專案中。只有經過審閱、對 Bucket & Code Server IDE 本身的修改,才會讓它進入配方庫,以及每台 NAS 都會取得的已簽署目錄。
- 建置需要 npm、Go 或 Cargo 套件的配方,會在 vendor 檔案中列出它們。這份清單由
/usr/bin/bucketvs/share/bucketvs/tools/中的npm-vendor.py、go-vendor.py與cargo-vendor.py寫出;它們需要 工具鏈 中的 Python 執行環境。
應用程式能在哪些 NAS 型號上執行
以 glibc 建置的程式,只能在 glibc 至少與程式要求的最新版本一樣新的 NAS 上啟動。套件假設它能執行的每一台 NAS(QTS 6.0、QuTS hero 6.0 及更新版本)都有 glibc 2.39 或更新版本:這是它的 glibc 下限。2.39 是 Ubuntu 24.04 與 QuTS hero 6.0.1 的 glibc,從該韌體本身的 /lib/libc.so.6 讀取而得;QNAP 沒有公布 glibc 版本,而 QNAP 的版本資訊中沒有 QTS 6.0。執行 QTS 6.1.0 與 QuTS hero 6.1.0 的測試 NAS 為 2.43。
新應用程式與 變更 中的 執行於 可選擇以下兩者之一:
- 套件能執行的每一台 NAS(預設):任何程式都不能需要高於 2.39 的 glibc。請在 glibc 為 2.39 或更舊的環境中建置這類應用程式,例如 Ubuntu 24.04 builder(2.39)或 Debian 12 builder(2.36)。匯出為 QPKG 與套件儲存庫請選擇此項。
- 只有這台 NAS:程式可以需要這台 NAS 的 glibc,適用於需要較新 glibc 的軟體。這類應用程式會為這台 NAS 的架構建置,且永遠不會匯出為 QPKG。
交叉建置(aarch64 或 armv7)一律適用於每一台 NAS。當所選環境的 glibc 超出應用程式允許的範圍時,新應用程式會發出警告。每次建置後,bvsd 會讀取每個程式與每個函式庫要求的 glibc 版本,交叉建置也一樣。超過上限的檔案會讓建置失敗,並會指出修正方式:其他環境(選擇其他環境)、連結方式 static,或 只為這台 NAS 建置。應用程式頁面會說明其最新一次成功的建置需要哪個 glibc,而 相依性 分頁會列出每個超過上限的檔案。
在 NAS 上,bvs tree-deps <前綴> --tree <資料夾> --glibc-max 2.39 會對任何應用程式樹執行相同的檢查。
在 NAS 上啟用應用程式
啟用(管理員)會把前綴設為指向應用程式最新一次成功建置的連結,讓其程式在 NAS 上從 /usr/app/<名稱>/bin 執行。啟用絕不取代不是它自己建立的東西:前綴位置上已有資料夾、檔案或其他連結時,會拒絕並說明原因。QTS 的系統磁碟在每次開機時都會重建,因此套件每次啟動都會重新建立連結。停用(管理員)會移除連結;刪除應用程式時會先停用,再把它移到資源回收筒保留 7 天。developer 只能在應用程式未啟用時刪除它。為其他架構建置的應用程式無法在這裡啟用;請下載其封存檔,供該類 NAS 使用。
匯出應用程式
匯出為 QPKG(管理員)會把最新一次成功的建置打包成獨立的 QPKG,可以在沒有此套件的其他 NAS 上安裝該應用程式。它會拒絕只為這台 NAS 建置的應用程式;若建置中的程式需要高於 2.39 的 glibc,它會在打包前停止(參見應用程式能在哪些 NAS 型號上執行)。這需要 QDK:請在工具鏈頁面的 QNAP 分頁安裝「QNAP QDK 2.5.0」。在安裝 QDK 之前不會顯示該按鈕,應用程式頁面會說明取得方式。匯出會在應用程式的環境中執行 qbuild,方式與 bvs qbuild 相同。每次建置都會在該環境安裝 rsync;對最後一次以較舊版本套件建置的應用程式,拒絕訊息會指出加入它的指令。匯出的套件在啟動時建立其前綴的連結,停止時移除。它沒有程式碼簽章:工作的記錄會寫出情況 3,按鈕下方的一行也是。在 SSH 工作階段中,/etc/init.d/<名稱>.sh disable 與 enable 會設定匯出套件在 App Center 中的開關,前綴的連結保持不變。匯出的套件每次啟動時,也會在 /etc/profile 與 /root/.profile 加入一行,把應用程式的 bin 與 sbin 放到 SSH 登入的 PATH 中、排在 NAS 本身的指令之後,admin 與其他可登入的帳號都適用;移除套件時會一併拿掉這一行。
套件儲存庫
此套件維護一個 App Center 儲存庫:發佈到其中的 QPKG 套件,可以像任何儲存庫的應用程式一樣,從其他 NAS 的 App Center 安裝。
- 位址。
bvs repo list(以及GET /api/v1/repo)會印出位址:<base>/repo/repo.xml,其中<base>在套件發佈到網際網路期間為已發佈的套件主機名稱(沒有時為已發佈的主要主機名稱)(發佈到網際網路),否則在設定了公開 URL 時為該 URL,再否則為http://<NAS 位址>:9950(一般 HTTP 僅做重新導向時為https://…:9951)。在另一台 NAS 上:App Center、設定、應用程式來源、新增,再輸入這個位址。 - 發佈。 使用
bvs repo publish <file.qpkg>(在 NAS 上以 root 執行),或以檔案作為內容呼叫POST /api/v1/repo/packages(developer 角色)。架構由 QDK 檔名<name>_<version>_<arch>.qpkg(x86_64、arm_64、arm-x41)或--arch決定。名稱、版本、說明與作者取自套件本身;PUT /api/v1/repo/packages/<name>/meta與…/icon(PNG,管理員)可以變更 App Center 顯示的內容。套件不能命名為default:那是儲存庫本身圖示的名稱。 - 只接受已簽署的套件。 沒有程式碼簽署的套件會被拒絕,因為 App Center 只會在設定為允許這類套件的 NAS 上安裝它們。當套件的程式碼簽署區塊是包含憑證與簽署者的 PKCS#7 簽署時,儲存庫即視其為已簽署。儲存庫不會把該簽署或其憑證與 QNAP 的比對;那是 App Center 安裝套件時的工作。在已知情況的網路中,管理員可以在設定中開啟
repo.accept_unsigned;這類套件會在說明中加上標記。App Builder 匯出的套件沒有簽署,因此需要這個設定。 - 版本。 每個版本都能下載,但 App Center 每個套件只會看到一個版本,也就是管理員列出的那個。管理員發佈的套件第一版會立即列出;之後的版本要等管理員移動它(
POST /api/v1/repo/packages/<name>/latest,或bvs repo publish --latest)才會列出。developer 發佈的版本,包括新套件的第一版,在管理員把某個版本設為最新之前都不會列出:因為每台加入此儲存庫的 NAS,都會以 root 安裝列出的版本。刪除版本(管理員)會移除其所有架構;若它是列出的版本,在管理員選擇其他版本前不會列出任何版本。 - 上傳。 同時最多複製兩個上傳;若上傳會讓資料磁碟區的可用空間少於 256 MiB,儲存庫會拒絕。儲存庫不包含在備份中:還原後請重新發佈套件。
- 在面板中。 套件 頁面顯示要複製的地址、套件及其版本,以及是否已簽署;開發者在那裡上傳 QPKG,管理員把某個版本列為最新並刪除版本。它的 程式碼簽署 卡片顯示三種情況、有多少列出的版本沒有簽章,以及管理員針對未簽署套件的開關,開啟前會先詢問。應用程式頁面會顯示其流程(建置、匯出為 QPKG、發佈)與 發佈 按鈕。
核心工坊
核心工坊為 NAS 正在執行的核心建置核心模組,逐一與該核心比對,並載入它們。QNAP 尚未公開其目前核心的原始碼(其 GPL 發佈止於 QTS 5.2.3),因此工坊會讀取執行中的核心顯示的自身資訊,並據此設定一棵相符的核心樹。
需要的東西
- 範例庫中的 Kernel builder 環境(含 GCC 13 與核心建置工具的 Ubuntu 24.04)。模組必須以與核心相同的 GCC 主要版本建置;工坊會比對兩者。
- admin 角色,以及終端機中的 root:
bvs kernel指令會使用 bvsd 的 CLI socket 或載入模組。
設定檔
bvs kernel profile 會顯示執行中核心的資訊:其版本(6.6.129-qnap)、QNAP 建置它時使用的編譯器、QNAP 自己模組的 vermagic、這些模組中 struct module 的大小與 init、exit 的位置、模組是否必須簽署,以及核心樹為了相符而取得的設定。
工作區
bvs kernel prepare 會在資料資料夾的 kernels/<release> 中建立執行中核心的工作區:
- 它採用目錄中對應此版本的核心原始碼(
bvs kernel sources):QNAP 有發佈時使用 QNAP 自己的 GPL 核心樹,否則使用 kernel.org 的核心樹,後者缺少 QNAP 自己的修改。--source可選擇其他來源。 - 它設定核心樹:若是 QNAP 的核心樹,使用 QNAP 針對此型號的設定;否則使用設定檔中的設定。
--option NAME=m可加入設定,例如某個驅動程式。 - 它為建置模組準備核心樹(
--full則會建置整個核心,所需時間長得多,但能讓檢查看到核心匯出的符號)。 - 它確認核心樹建置出的正是執行中核心的版本。
它會以工作的形式在工作頁面執行。prepare 失敗時會保留上一次的核心樹。
建置模組
- 您自己的模組是
projects/中含Kbuild檔案的資料夾。在該資料夾中執行bvs kernel make(或bvs kernel make --project <folder>)即可建置。範例「Kernel module」就是這樣的專案。 - QNAP 未隨附的核心驅動程式,從核心樹中其所在目錄建置:
bvs kernel make --dir drivers/usb/serial。範例「USB serial driver ch341」就是以這種方式建置 ch341 驅動程式;其設定要先以bvs kernel prepare --option USB_SERIAL=m --option USB_SERIAL_CH341=m加入。
建置產生的模組保存在 kernels/<release>/modules/。QNAP 已為此核心隨附的模組不會保存:載入的仍是 QNAP 自己的那一份。bvs kernel make --build-only 不會在那裡保存任何東西:模組留在建置的位置。新專案核心範本的 CI 工作流程就是這樣建置。
檢查與載入
bvs kernel check <module> 會把模組與執行中的核心比對:vermagic、struct module 的大小以及其中 init 與 exit 的位置(與 QNAP 自己的模組比對)、是否需要簽署、所依賴的模組,以及需要的每個符號。每項發現都會說明哪裡不相符,以及該怎麼做。結束狀態 3 表示該模組不得載入。
bvs kernel load <module> 會再次執行檢查並載入模組,先載入其所依賴的模組(NAS 上 QNAP 自己的,或您的)。檢查有錯誤的模組絕不會被載入。bvs kernel unload <module> 會移除模組;使用中的模組會保持載入。每次載入與卸載都會寫入 log/kernel-modules.log。
QNAP 的核心不會列出其資料符號,因此檢查無法查詢 jiffies 等符號,只會以警告列出。若其中任一個缺少,核心會在載入時拒絕該模組。
應用程式中的模組
應用程式可以指定工作區中的模組。啟用應用程式時,會在建立其連結前載入這些模組;套件每次啟動、面板可用之後,也會再次載入它們;仍在進行中的載入會顯示在核心頁面上。停用時會先卸載它們;有模組在使用中時,應用程式會保持啟用。
- 若 NAS 在載入模組期間重新啟動,下一次啟動不會載入任何模組,並顯示通知:請手動載入,或再次啟用應用程式。
- 若 NAS 在套件已載入模組的那次開機中,未經套件的正常停止就停止運作(當機、斷電或強制重設),下一次啟動不會載入那些模組,因為其中之一可能就是當機的原因。通知與核心頁面會列出它們。手動載入其中之一,或再次啟用其應用程式,啟動時就會再次載入它。NAS 正常關機或重新啟動會按順序停止套件,不會改變任何事。
- 啟動永遠無法結束的模組(例如在等待硬體的驅動程式)不會影響面板運作。一分鐘後會有通知指出它;其他載入與卸載會等待它,重新啟動 NAS 可結束它。
QTS 更新到其他核心後,必須在新核心的工作區中重新建置模組。還原到其他資料資料夾後也一樣:kernels/ 不包含在備份中。
在面板中
核心 頁面會顯示執行中核心的設定檔、目錄中的核心原始碼、工作區及其模組。管理員在此準備工作區(來源、環境、額外設定、是否建置整個核心),並從專案資料夾或核心樹的目錄建置模組;兩者都以工作的形式執行。檢查(developer)會顯示每項發現及其修正方式;載入 與 卸載(管理員)的作用與 bvs kernel load 與 unload 相同,被拒絕的載入會顯示擋下它的檢查結果。資料資料夾下任何位置的 .ko 檔案都能以其路徑檢查。
cron 工作與操作
工作頁面有兩個清單:排程工作(cron)與操作(bvsd 執行的長時間工作,例如安裝與搬移)。
排程工作
developer 建立並變更自己的工作;管理員可變更所有工作。工作包含:
- 排程:五個 cron 欄位(
0 3 * * *)、以秒為首的六個欄位,或描述符(@daily、@hourly、@every 6h)。前綴CRON_TZ=<zone>可選擇其他時區;沒有前綴時,工作以頁面頂端顯示的 NAS 時區執行。 - 指令:由套件的
bash -lc以 root 執行。多行會作為一個指令碼執行,其輸出成為該次執行的記錄。 - 執行位置:在 NAS 上,或在環境中(使用環境的
bash,沒有時使用/bin/sh)。 - 工作資料夾:相對於資料目錄的
projects/,或完整路徑。在環境中只看得到projects/,也就是/projects。 - 逾時:以秒為單位(0 表示無)。超過時間仍在進行的執行會被停止,並標記為逾時。
- 執行進行中時:略過下一次執行,或讓它等候(最多一個等候)。
- 失敗時:失敗或逾時的執行會送出通知。
每個工作保留最近 100 次執行及其輸出的結尾(4 KB)。每次執行的完整記錄保留 30 天。
工作代替其擁有者以 root 執行,並以擁有者的家目錄作為 HOME,因此只有在擁有者是已啟用的 developer 或 admin 時才會執行。擁有者停用或為 member 或 viewer 角色期間,工作的每個時間點都會記錄為一次已略過的執行並說明原因,例如「its owner ola is disabled」;立即執行 也會以相同原因拒絕。不會送出通知。擁有者被停用或改為低於 developer 的角色時正在進行的執行會被停止。帳號重新啟用或再次成為 developer 後,工作就會再度執行。刪除帳號會刪除其工作。內建工作無論帳號發生什麼事都會執行。
指令結束時,它在背景啟動的程序會繼續執行。發生逾時、刪除工作或停止套件時,該次執行的整個程序群組會收到 SIGTERM,5 秒後再收到 SIGKILL。
在調整時鐘的夜晚(日光節約時間),工作會遵循 Debian cron 的規則。分鐘或小時欄位以 * 開頭(包含 */N)、@hourly 或 @every 的工作依經過的時間執行:秋季會在重複的那一小時的兩次經過中都執行,春季則不會執行被跳過的那一小時。其他工作的每個時間點都只執行一次:落在重複那一小時的時間點只執行一次,落在被跳過那一小時的時間點則在時間調整後立即執行。
每個已登入的帳號(包括 viewer)都能讀取工作的指令與其執行輸出。不要把密碼或權杖寫進指令:讓指令從 <data>/etc 下只有 root 能讀的檔案(chmod 600)讀取。
內建工作
| 工作 | 時間 | 內容 |
|---|---|---|
| 維護 | 每天 03:30 | 從資料目錄的 tmp/ 移除 10 天未變更的內容;log/audit.log 超過 10 MB 時進行輪替 |
| 清空資源回收筒 | 每天 03:45 | 移除移到資料目錄 trash/ 超過 7 天的內容(例如已刪除帳號的家目錄) |
| 重新整理工具鏈目錄 | 每天 04:15 | 取得已簽署的工具鏈目錄 |
| 輪替 nginx 記錄 | 每小時第 7 分鐘 | nginx-access.log 或 nginx-error.log 超過 20 MB 時改名為 .1(保留五個舊檔),並通知 nginx 重新開啟其記錄 |
管理員可以變更內建工作的排程、逾時、執行中的處理方式與通知,也可以關閉它。其名稱與指令不變。
操作
安裝、環境工作、資料搬移與開啟模組都以操作的形式執行。清單顯示最近 50 個,最新的在前,並附上進度與記錄。操作及其記錄保留 30 天。套件停止時仍在執行的操作會顯示為 interrupted。developer 可以取消自己的操作;管理員可以取消任何操作。
備份
備份 頁面(管理員)設定要備份什麼、何時備份、副本送往何處,以及保留多少份。按下 立即備份 可隨時執行備份。新安裝時排程備份為關閉;開啟 排程備份 後,預設每天執行一次備份(內建 cron 工作 backup)。它會保留最近 7 天、4 週與 6 個月中每一段的最新一次執行,並一律保留最新一次成功的執行。同一時間只會執行一個備份、驗證、還原或刪除。
同一天的兩次執行算作一天:較新的一次完成時,會移除當天較早的那一次。因此下午的 立即備份 會取代當天早上的排程執行;若當天早上的狀態很重要,請先把該次執行複製到別處。
備份的內容
一次執行就是一個資料夾 <資料>/backups/<id>/,其中的 manifest.json 列出每個檔案及其 sha256:
| 部分 | 內容 |
|---|---|
| 設定 | etc/:設定、帳號、TOTP 密鑰、TLS 金鑰、備份金鑰 |
| Git | Forgejo 的 dump:儲存庫、Wiki、LFS 物件、附件及其資料庫 |
| SVN、bucket | 每個儲存庫的副本,以遞增方式建立:已複製過的修訂版本不會再複製 |
| VS Code 設定 | 每個帳號的 VS Code 設定、按鍵繫結、程式碼片段與擴充功能清單(不含擴充功能的檔案:擴充功能檢視會重新安裝它們) |
| 環境 | 工具鏈的環境(預設關閉:可以重新建立) |
| 專案 | 每個專案資料夾,包含其 Git 歷史與尚未提交的檔案,不含 node_modules |
| HOME 資料夾 | 每個帳號的 HOME 資料夾,不含快取和 AI 工具本身的安裝(它們的安裝按鈕會放回) |
| App Builder | 每個應用程式的設定與建置歷史;建置會重新產生應用程式的檔案 |
| 套件儲存庫 | 已發布的套件、它們的圖示,以及 App Center 讀取的索引 |
無論頁面上勾選了什麼,這四個部分都會在每次備份中。自上次備份以來未變更的資料夾會連結到該次備份的副本,不佔用空間。
只有在每個部分都寫入並檢查完成後,該次執行才會出現;失敗或磁碟區已滿時,會移除未完成的資料夾,並保留先前的執行不變。驗證 會完整讀回一次執行:每個封存檔的 sha256、每個修訂版本的 svnadmin verify、每個儲存庫的 git fsck,以及 Forgejo 資料庫的完整性檢查。
目標
每次執行都會複製到頁面上的每個目標:
- 這台 NAS 上的 本機資料夾:照原樣保存該次執行,未變更的檔案以連結指向上一份副本,因此每份副本只佔用變更的部分。不加密。它與資料位於同一組磁碟上,能防範操作失誤,但無法防範磁碟區故障。
- 透過 SSH 的 rsync(
user@host:path)。使用套件的備份金鑰登入:頁面會顯示要加入另一台機器authorized_keys的公開金鑰。 - rclone(
remote:path,即<資料>/etc/rclone.conf中的遠端):雲端儲存空間,以及 rclone 能連到的任何地方。
離開 NAS 的副本(rsync、rclone)必須加密:請開啟 加密離開 NAS 的副本 並按 建立金鑰。副本會以 age 對金鑰的公開部分加密;私密部分只顯示一次,bvsd 不會保存。沒有它,任何 NAS(包括這一台)都無法還原加密的副本:請把它保存在這台 NAS 以外的地方。新金鑰只會加密此後的執行;較舊的副本需要舊的私密金鑰。
失敗的目標會列在該次執行的結果中;執行本身仍然有效。
rclone.conf 存有遠端的認證資料。在副本或 測試 使用它之前,若它(以及備份金鑰)並非只有 root 能讀,bvsd 會把它設為只有 root 能讀(模式 600),並在工作的日誌中說明。
還原
對某次執行按 還原,可以放回全部、一個儲存庫(SVN 儲存庫、bucket 或 Git 儲存庫),或一個專案資料夾:
- 在檢查之前不會取代任何東西:每個封存檔依其 sha256 檢查,每份 SVN 副本以
svnadmin verify檢查。任何副本未通過時,還原會在變更使用中的資料前停止。 - 被取代的使用中資料會移到
<資料>/trash保留 7 天,因此還原本身也可以復原。 - 一個儲存庫 或 一個專案資料夾 的還原在模組持續運作時進行。誤刪的專案資料夾會連同其歷史與尚未提交的檔案一起回來。
- 全部 會停止模組、交換資料,並以還原的設定重新啟動 bvsd:所有工作階段都會結束,帳號與密碼會是備份中的內容。備份之後建立的專案或 HOME 資料夾會保留。
通知
bvsd 會把每則通知寫入 QTS 系統記錄。它也能透過 shoutrrr URL 把通知送到聊天與郵件服務(Telegram、Discord、Slack、電子郵件、通用 Webhook 等)。
| 通知 | 時機 | URL 開關 |
|---|---|---|
| 工作失敗 | 設定為失敗時通知的工作,其 cron 執行失敗或逾時;操作失敗 | notify.on_job_failure |
| 備份 | 每次備份、驗證與還原的結果,包括成功的;無法開始的排程備份 | notify.on_backup |
| 不斷重新啟動 | 某個程序開始不斷重新啟動 | notify.on_crashloop |
| 憑證 | 上傳的憑證剩餘 30 天以下;nginx 改回使用自我簽署憑證;已建立新的自我簽署憑證 | notify.on_cert_expiry |
| 系統 | 啟動時拒絕設定、發現未完成的資料搬移、結束殘留的程序、無法寫入設定檔 | 一律送出 |
- 開關只決定哪些通知送往 URL。系統記錄會收到每一則通知。
- 相同的通知每 10 分鐘最多送出一次。之後的下一則會說明有幾則被暫緩。
- 每個 URL 各自執行一次
shoutrrr send,限時 10 秒。失敗時只記錄 URL 的協定,因為 URL 的其餘部分含有其權杖。
URL 與開關位於系統頁面的 通知;開關預設為開啟。管理員在該處變更。其他帳號只看得到開關與每個 URL 的協定,因為 URL 的其餘部分含有其權杖。NAS 管理員也可以透過 CLI socket 設定:
/usr/bin/bucketvs/bin/curl --unix-socket /usr/bin/bucketvs/var/run/bvsd-cli.sock \
-X PUT -H 'Content-Type: application/json' \
-d '{"notify":{"shoutrrr_urls":["telegram://<token>@telegram?chats=<chat id>"]}}' \
http://bvsd/api/v1/settings
記錄與支援資料包
每個記錄都是資料目錄中的 log/<name>.log。bvsd 及其監看的每個程序的記錄會在 20 MB 時輪替,並保留五個舊檔。nginx-access.log 與 nginx-error.log 的上限相同,會在 bvsd 每次啟動時與每小時由工作「輪替 nginx 記錄」檢查,因此其中一個最多可能超過 20 MB 一小時的流量。工作「維護」會在 audit.log 超過 10 MB 時輪替,並保留三個舊檔。記錄頁面(管理員)會顯示任何記錄的最後幾行、加以篩選,並在新行出現時持續追蹤:
| 記錄 | 寫入者 |
|---|---|
bvsd | bvsd 本身:啟動、停止、套用的設定、問題 |
nginx | nginx 本身的輸出 |
nginx-access、nginx-error | 每個請求,以及 nginx 的錯誤 |
audit | CLI socket 上的每個請求 |
| 每個模組程序各一個 | 各模組的程式 |
系統頁面會顯示版本、平台、時區,以及 bvsd 監看的每個程序。「下載支援資料包」(管理員)會為錯誤回報建立一個封存檔:
- 設定,其中 SMTP 密碼與每個 shoutrrr URL 都已遮蔽;
- 產生的
nginx.conf、不含金鑰的憑證詳細資料、磁碟區; - 每個模組、程序與最近操作的狀態;
- 每個記錄的最後 2000 行,其中每個查詢字串都以
?(query removed)取代。
它絕不包含密碼、工作階段、權杖或金鑰。
更新
bvsd 在啟動時與每 24 小時讀取 https://pub.qnaputilities.com/bucketvs/latest.json。當其中列出較新的版本時,系統頁面會顯示該版本,並附上摘要提供的連結。bvsd 只會告知有新版本:它絕不下載或安裝套件。檢查失敗不會改變面板中的任何內容。
安裝新版本
從 App Center 或以 手動安裝,把新套件安裝在舊套件上。安裝會停止 bvsd、取代程式檔案,然後重新啟動它;資料目錄、設定、帳號與每個儲存庫都會保留,面板的工作階段也是。編輯器執行個體會隨 bvsd 停止,因此編輯器中開啟的終端機會結束;帳號再次開啟編輯器時,執行個體會重新啟動。
從使用連接埠 6050、6051 與 6052 的版本升級。 較早的版本在 6050(HTTP)、6051(HTTPS)與 6052(透過 SSH 使用 Git)上接聽。新版本第一次啟動時,會把它們分別移到 9950、9951 與 9952,並以通知告知;您自己選擇的連接埠則維持不變。請變更指向舊連接埠的設定:書籤、指向 6050 的 Plesk Proxy,以及 ssh://git@<NAS>:6052/… 之類的 git 遠端(git remote set-url)。
移除、重新安裝與損壞的套件
套件被移除、重新安裝或損壞時,您的工作都會保留。您建立的一切都在資料目錄中:帳號與設定、Git 與 SVN 儲存庫、bucket、專案資料夾、HOME 資料夾、VS Code 的設定與擴充功能、App Builder 應用程式、環境、套件儲存庫以及備份。安裝資料夾(<磁碟區>/.qpkg/bucketvs)只有程式和一個指出資料目錄的檔案。
- 移除後再安裝。 移除套件會刪除安裝資料夾,但保留資料目錄以及指出它的檔案
/etc/config/bucketvs-data-root。下一次安裝會讀取該檔案,並在同一個資料目錄上啟動:相同的帳號與密碼、相同的專案與儲存庫,已登入的工作階段也包括在內。 - 在已安裝的套件上安裝。 相同或更新的版本只會取代程式檔案,不會動到資料目錄。
- 損壞的套件。 安裝資料夾損壞時(缺少程式、資料夾被手動刪除),請從 App Center 或以 手動安裝 重新安裝套件。安裝會以相同方式找到資料目錄。仍從已刪除檔案執行的 bvsd 會在啟動時被停止,並啟動已安裝的版本。
- 什麼會刪除資料。 只有刪除資料目錄資料夾本身。若要刻意從空白開始,請移除套件、刪除資料目錄資料夾,然後再安裝:第一次啟動會建立新的資料目錄(見資料目錄的初始位置)。
磁碟故障是另一回事:資料目錄位於 NAS 本身的磁碟上。請在另一台機器上保存備份(備份);每次備份都包含您的專案資料夾、HOME 資料夾、App Builder 的設定與套件儲存庫。
bvs 指令
bvs 是套件的命令列工具,位於 /usr/bin/bucketvs/bin。它在 bvsd 啟動的每個程序(包括 cron 工作)的 PATH 中。 套件執行期間,/usr/bin/bvs 會連結到它,因此在 NAS 的 SSH 工作階段中也能直接以名稱呼叫;停止套件會移除這個連結。
透過 CLI socket 與 bvsd 通訊的指令都需要 root,因為該 socket 僅限 root:user、jobs,以及 bvsd 執行時的 tc install、tc remove 與 env create、clone、export、delete。env shell、env run 與 qbuild 也需要 root:它們會啟動 bvs-chroot。以其他使用者執行時,需要 socket 的指令會以「bvsd's CLI socket … is open to root only: run bvs as root」停止。
bvs env list
bvs env create <name> --from <rootfs-id> [--package <name>]...
bvs env shell <name>
bvs env run <name> -- <command> [<arg>...]
bvs env clone <name> <new-name>
bvs env export <name>
bvs env delete <name>
bvs tc list
bvs tc install <id>
bvs tc remove <id>
bvs use <id>
bvs jobs
bvs user list
bvs user password <name>
bvs user totp-reset <name>
bvs guide [--path] [en|pl|de|fr|it|nl|sv|ja|zh-TW]
bvs qbuild [--env <name>] [<qbuild argument>...]
bvs kernel profile [--json]
bvs kernel sources
bvs kernel prepare [--source <id>] [--env <name>] [--option NAME=VALUE]... [--full]
bvs kernel make [--project <folder> | --dir <tree directory>] [--build-only] [<target>...]
bvs kernel check <file.ko | module>
bvs kernel load <module>
bvs kernel unload <module>
- bvsd 執行時,安裝與環境工作會透過其 CLI socket 交給 bvsd,因此面板也會顯示它們,而
bvs會追蹤到它們結束。沒有 bvsd 時,它們在bvs程序本身中執行;在指令前加上--local可刻意這樣做。 bvs jobs與user指令需要 bvsd。bvs guide在終端機中以套件的less開啟本指南,其他情況或加上--path時則印出其檔案路徑。未指定語言時,會依LC_ALL、LC_MESSAGES與LANG中第一個有設定的值決定:de_DE.UTF-8開啟德文指南,zh_TW與zh_HK開啟繁體中文指南,指南未提供的語言(C、zh_CN)則開啟英文指南。
檔案與資料夾
| 路徑 | 內容 |
|---|---|
/usr/bin/bucketvs | 套件的程式(指向其安裝資料夾的連結) |
/usr/bin/bucketvs/etc/data-root | 資料目錄的路徑 |
/usr/bin/bucketvs/var/run/bvsd.sock | 面板的 API socket(供 nginx 使用) |
/usr/bin/bucketvs/var/run/bvsd-cli.sock | bvs 指令的 socket,僅限 root |
<資料目錄>/etc/ | 設定、帳號、工作階段、權杖、憑證、產生的 nginx.conf(密鑰為模式 600) |
<資料目錄>/log/ | 記錄 |
<資料目錄>/tmp/ | 每個程序的暫存檔案 |
<資料目錄>/home/<使用者>/ | 每個帳號的家目錄 |
<資料目錄>/jobs/ | 操作、cron 工作及其執行,含記錄 |
<資料目錄>/toolchains/ | 下載快取、已安裝的工具鏈與執行環境、匯出檔 |
<資料目錄>/envs/ | 環境 |
<資料目錄>/projects/ | 工作區,在環境中以 /projects 出現 |
<資料目錄>/trash/ | 已刪除的項目,保留 7 天 |
各模組會加入自己的資料夾;其章節會說明位置。