核心概念

Town OS 建立在一組核心想法之上。理解這些概念,有助於你看清各部分如何組合在一起—— 從定義一個套件,到管理一個執行中的服務。

套件(Packages)

套件是對某個服務的自足式 YAML 定義,從 git 儲存庫拉取。每個套件都會宣告自己的 網路連接埠對應、儲存磁碟區、環境變數與互動式問答——執行該服務所需的一切。套件可以 以容器方式執行(預設),也可以是基於 QEMU 的虛擬機器,或透過 Valve 的 Proton 相容層 執行的 Windows 應用程式。檔案範本(Go 的 text/template 檔案)可以在安裝時 算繪進磁碟區,達成動態設定。套件透過 supplies 標籤(例如 httpdatabasecache)描述自身能力。 預設套件庫內附一批精選套件,涵蓋 git 託管、視訊會議、媒體串流、團隊訊息 與資料庫——而且還在持續增加。

問答(Questions)

安裝套件時,Town OS 可能會出現一組稱為「問答」的互動式提示。你的回答會填入套件定義中 各處的 @variable@ 範本佔位符——用來設定主機名稱、連接埠、憑證與其他選項。 每個問題都帶有型別化的驗證器(hostnameportbytesvolumearchivedurationsecretbooleanoauth 或自由文字)以及選填的預設值, 因此設定錯誤在服務啟動前就會被攔下。型別也決定了你看到的控制項——boolean 是核取方塊、secret 是遮罩欄位,而 oauth 問題則是一個「連線」按鈕, 會帶你登入該廠商並保存它回傳的權杖。有幾種型別在留空時會自動產生值:連接埠在 10000–60000 範圍內隨機指派、主機名稱以 package-name-4hex 的形式產生, 密鑰則產生 64 位十六進位字串。標為 optional 的問題可以直接留白—— 你沒有的 SMTP 轉送會維持未設定,而不是被隨便填上一個猜測值。

服務(Services)

套件安裝完成後就成為一個服務——一個由 systemd unit 管理的執行中容器。Town OS 提供 啟動、停止與重新啟動的控制,透過 Server-Sent Events 即時串流記錄,支援以游標分頁瀏覽 journal,也可以啟用或停用服務。各服務之間,以及與主機系統之間,都是彼此隔離的。

網路(Networking)

Town OS 內建 rolodex, 這是一套 DNS 伺服器,為你的套件管理權威區域並轉送上游查詢。每個套件都宣告自己的 連接埠對應——external 連接埠對外開放給主機,internal 連接埠 僅在容器之間可用。連接埠值支援 @variable@ 範本,因此使用者可以在安裝時 自行選擇連接埠。宣告了相依關係的套件會共用同一個網路,讓同一相依樹中的容器能直接通訊。 上層套件可以在環境變數中以 @dep_KEY_host@@dep_KEY_port_N@ 範本變數參照相依套件,也可以透過執行階段環境變數 (TOWNOS_DEP_{KEY}_HOSTTOWNOS_DEP_{KEY}_PORT_{port})存取。UPnP 轉送則會自動處理。

網路

網路是一個具名的 WireGuard 疊加網路,並與一個 DNS TLD 配對。套件安裝到某個網路中, 對等裝置加入這個網路,而 TLD 決定誰能解析什麼。home 網路始終存在、無法移除, 而且只提供 DNS——它沒有通道,並且在它上面的對等裝置註冊會被拒絕,因為每個帳號本來就屬於它, 單憑成員身分不應成為進入通道的途徑。其他網路則會取得 WireGuard 介面,以及一個由本機自身識別推導出的子網路, 因此同時加入兩台 Town OS 主機的裝置永遠不會遇到衝突。停用網路只會關掉傳輸層: 遠端存取中斷,而本地 DNS 與容器照常執行。

Ingress

一扇共用的前門。單一 Caddy 執行個體為整台主機持有 :443:80, 並且完全依據 SNI 和 Host 決定你連到哪個服務——沒有依服務劃分的監聽器,也沒有 bind 指令, 所以區域網路用戶端和疊加網路對等裝置命中同一個 socket、拿到同一張憑證、被代理到同一個容器。 套件的名稱是一個字串,同時以四種方式被使用:A 記錄、憑證的 SAN、TLSA 的擁有者,以及 ingress 的虛擬主機。

TLS 與本地 CA

Town OS 執行自己的憑證授權單位,為套件所宣告的名稱簽發憑證, 因此不需要公開憑證、也不會有瀏覽器警告,服務就能透過 HTTPS 存取。 CA 憑證可從 /tls/ca.crt 下載——只要信任它一次,所有本地名稱就都能正常運作。 憑證在背景續期,而不是在開機時續期;變更 TLD 會重新簽發依賴於它的名稱。

物件儲存

Town OS 透過 gfeh 提供物件儲存。一個分割區是一個 btrfs 子磁碟區, 擁有自己的常駐程式和自己的一套使用者,而且每個網路恰好對應一個分割區—— 因此某個網路中的使用者、權限或已發布連結,在另一個網路中毫無意義。每個分割區提供四種檢視: S3、純 HTTP、類似雲端硬碟的瀏覽介面,以及 IPFS。使用者是以樹狀結構組織的主體; 存取權限是一項授權,並且始終會收窄到所授予主體的權限上限; 而已發布連結是一次可以事後撤回的公開曝光。任何分割區都不會發布主機連接埠—— ingress 透過容器名稱存取它們。

儲存(Storage)

所有資料都存放在 btrfs 子磁碟區上,並依套件彼此隔離。每個磁碟區都有容器內的掛載點、 可設定的配額(例如 512mb2gb),以及選填的 uid/gid 擁有者。磁碟區可以透過 archives 功能 從容器映像檔預先填入內容,也可以在安裝時把 git 儲存庫複製進空的磁碟區來初始化。 使用者也能自行建立獨立的磁碟區。虛擬機器磁碟映像檔會快取在專用子磁碟區中,之後的安裝 可以直接重用。系統支援 btrfs 快照,可用於時間點備份。資料在套件重新安裝與升級之間都會 保留——更新服務時你的檔案絕不會遺失。

套件庫(Repositories)

套件依套件庫組織——也就是內含 packages/ 目錄、其中放著帶版本 YAML 定義的 git 儲存庫。每套 Town OS 都包含預設套件庫,但任何人都可以建立並分享自訂套件庫。套件庫 是有順序的——當套件名稱衝突時,排在後面的會覆蓋前面的。套件庫中的 featured.json 檔案可以在介面上突顯特定套件。

範本與註記(Templates & Notes)

@variable@ 範本系統把使用者對問答的回應,連接到環境變數、連接埠對應、 磁碟區配額等各處。像 @LOCAL_EXTERNAL_HOST@@LOCAL_INTERNAL_HOST@ 這類內建變數隨時可用。安裝完成後,notes 會顯示關鍵資訊,例如連線 URL、憑證 或聯絡方式——並可對 urlphoneemail 進行選用的 型別驗證。

頁面(Pages)

Town OS 可以架設靜態網站。每個頁面有三種可用的來源:上傳 tar 封存檔、從容器映像檔擷取 檔案,或複製一個 git 儲存庫。每個頁面都有自己的網域,並透過 Caddy 提供服務。封存類型的 頁面可以重新上傳來更新;git 與容器映像檔類型的頁面則可以隨時重新建置。

監控(Monitoring)

內建的可觀測性堆疊開箱即用,不需要任何設定。Prometheus 負責收集指標,Node Exporter 回報主機統計資料(CPU、記憶體、磁碟、網路)。有兩種監控後端可選:輕量的內建介面(預設) 或自動佈建儀表板的 Grafana。整套元件都以系統服務執行,失敗時會自動重新啟動。

國際化(Internationalization)

所有面向使用者的字串都會經過以 BCP 47 語言代碼為索引的訊息目錄。介面以母語字體呈現 21 種常見語言,另有 87 種以上的國家/地區代碼可用。目前只有英文(en-US) 完成全部翻譯——相關基礎架構已經就緒,就等社群參與翻譯。

帳號與工作階段(Accounts & Sessions)

Town OS 支援管理者帳號與一般使用者帳號。密碼至少需要 8 個字元。身分驗證使用 JWT 權杖, 閒置 7 天後過期。工作階段是暫時性的——簽章金鑰會在每次重新開機時重新產生,因而自動 清除所有作用中的工作階段。

稽核記錄(Audit Logging)

每一項管理動作都會被記錄下來,包含帳號名稱、動作、請求路徑、細節、成功旗標與時間戳記。 唯讀端點不列入其中。稽核記錄支援分頁、依帳號篩選與全文搜尋。

設定(Settings)

全系統設定透過介面中的鍵值項目管理。可調整的項目包括預設磁碟區配額(50 GB)、 封存檔上傳大小上限(1 GB)、封存解壓逾時(600 秒)、語言地區、Proton 執行器映像檔, 以及 DNS 頂層網域。

套件升級(Package Upgrades)

當你設定的套件庫中出現更新版本時,Town OS 會自動偵測。儀表板上的標記會顯示待處理的 升級數量。你可以忽略不想升級的版本——忽略記錄以 SHA256 雜湊追蹤,只有在可升級的集合 改變時才會再次出現。

系統服務(System Services)

基礎架構容器——監控、DNS 與網頁介面——與使用者安裝的套件分開管理。它們使用不同的 systemd 前綴(town-os-system--),失敗時一律重新啟動,且使用者無法停用。