症狀:密鑰沒有寫進程式碼,卻在建構後的映像層、前端套件或建構紀錄裡留下了值。
最快解法:一般應用程式密鑰優先放在具備環境隔離、權限控制與審計入口的 OpenShip 密鑰功能;伺服器本身必須使用的基礎設施憑據才留在目標伺服器,敏感正式專案再加上外部 Secrets Vault。
這篇適合三類人:第一次把模型 API Key 部署到 OpenShip、需要避免提交到 Git 的個人開發者;管理預覽、測試與正式環境的小團隊;以及負責發布、輪換和故障恢復的技術主管。你真正要決定的不是「平台一定比較安全,還是伺服器一定比較安全」,而是哪一類密鑰由哪一個執行環境負責,以及出事後誰能撤銷、誰能恢復、誰留下操作證據。
先建立 OpenShip 密鑰管理的責任邊界
OpenShip 官方文件目前把部署流程分成專案初始化、部署與環境變數設定等步驟,首頁也描述了從連接程式碼庫、建構、傳送到目標環境和執行服務的流程。這些內容可以用來理解資料會經過哪些階段,但不能直接等同於「你的密鑰已經通過安全驗證」。雲端、自建伺服器與混合部署的功能入口,仍要以你正在使用的版本與部署形態實際測試為準。 (openship.io)
先把密鑰分成四類,決策會清楚很多:
| 密鑰類別 | 典型用途 | 優先儲存位置 | 判斷理由 |
|---|---|---|---|
| 應用程式密鑰 | 模型 API、郵件服務、第三方 API | OpenShip 的環境範圍密鑰 | 跟著專案與環境部署,較容易交接與輪換 |
| 基礎設施憑據 | SSH、主機備份、伺服器內部服務 | 目標伺服器的系統密鑰管理 | 只有伺服器或部署程序需要,不應暴露給應用程式 |
| 臨時令牌 | 短期建構、測試或一次性授權 | 外部 Secrets Vault 或短期注入 | 降低長期憑據留存,並可在工作完成後撤銷 |
| 高敏感正式憑據 | 正式資料庫管理權、根級雲端權限 | 外部 Secrets Vault,按需注入 | 要求更細的權限、審計與災難恢復責任 |
如果你把所有值都塞進伺服器 .env,看似集中,實際上可能讓 SSH 管理者、備份操作者、主機入侵者和應用程式執行帳號共享同一個信任邊界。反過來,若把所有基礎設施憑據都放入平台,又會讓應用程式部署權限與伺服器管理權混在一起。
第一步:先排除 Git、映像層與前端套件的洩露路徑
最常見的錯誤不是「平台把密鑰偷走」,而是開發者以為密鑰沒有寫進原始碼,就忽略了建構過程仍可能把它寫入映像檔或產物。
Docker 官方明確提醒,使用建構參數或環境變數傳入建構密鑰,可能使密鑰留在最終映像檔;需要建構時使用密鑰,應採用只在該建構指令期間掛載的方式。 (docs.docker.com)
你應該檢查以下位置,而不是只搜尋目前工作目錄:
- 程式碼庫目前檔案與歷史提交;
- Dockerfile、建構參數及映像層歷史;
- 建構輸出、測試錯誤、部署紀錄和除錯訊息;
- 前端公開環境變數及打包後的 JavaScript;
- 伺服器備份、壓縮檔、暫存目錄和交接文件。
程式碼庫的推送保護可以阻止部分硬編碼密鑰進入遠端儲存庫,但它不是撤銷機制,也不能清除已經出現在舊提交、映像層或建構紀錄中的值。發現正式密鑰曾經曝光時,先撤銷和重發,再處理歷史清理;不要只刪除目前檔案。 (docs.github.com)
提醒:「控制台看不到明文」只代表顯示介面沒有直接展示,不代表密鑰沒有被程式碼、建構工具、日誌、備份或客戶端套件讀取。驗收必須沿著實際資料流追蹤。
第二步:把預覽、測試與正式環境完全拆開
預覽環境最容易被低估。開發者為了讓新分支快速可用,常把正式模型帳戶、正式資料庫連線字串或正式回呼網址直接複製過去。結果是測試程式可能消耗正式額度、讀到真實客戶資料,甚至把測試輸出寫回正式系統。
平台環境變數與伺服器 .env 的差異,核心不在檔案格式,而在責任邊界:
| 比較項目 | OpenShip 環境範圍密鑰 | 伺服器 .env |
|---|---|---|
| 環境複製 | 可按專案或部署環境建立差異,仍須實測入口 | 通常靠檔案複製,容易把正式值帶到測試 |
| 變更責任 | 發布者、專案管理者或平台角色負責 | SSH 管理者、作業系統帳號和部署腳本負責 |
| 誤配置發現 | 可從部署紀錄、環境名稱和發佈流程追查 | 常要比對主機檔案、腳本和手工紀錄 |
| 應用程式可見範圍 | 理論上可按部署環境注入,須以目前版本測試 | 讀得到該檔案的程序可能取得全部值 |
| 適合內容 | 模型 API Key、第三方服務憑據 | 主機啟動、備份、SSH 或本機服務憑據 |
OpenShip 官方頁面提到環境變數、預覽部署以及團隊與審計相關能力,但不同雲端、自建和混合方案的功能範圍可能不同。你至少要在預覽與正式專案各放一組刻意不同的測試值,部署後從應用程式端確認實際讀到的環境,而不是只看設定頁是否顯示「已儲存」。 (openship.io)
實務上,預覽密鑰還應限制模型權限、資料庫資料集與消費額度。若預覽環境需要連正式服務,應使用唯讀、限資料範圍或代理層憑據,而不是直接重用正式應用程式密鑰。
第三步:用可回復流程處理模型 API Key 輪換
更換模型 API Key 是否需要重新部署,不能只靠平台介面猜測。很多應用程式在容器啟動時把環境變數讀入記憶體,因此平台設定雖已更新,正在執行的程序仍可能使用舊值;另一些程式則會在每次請求前讀取外部密鑰服務。
你可以把輪換分成三種流程:
- 直接覆蓋:把新值取代舊值,再重啟或重新部署。流程簡單,但舊值若已失效,應用程式可能立即中斷。
- 新舊並行:先建立新憑據,讓應用程式切換到新值,確認請求正常後再撤銷舊值。這是較適合正式服務的流程。
- 外部取用:應用程式啟動或請求時向 Secrets Vault 取得短期或最新憑據,平台只保留讀取所需的授權。這能減少人工複製,但會增加外部服務不可用時的恢復設計。
OWASP 建議密鑰管理要涵蓋建立、輪換、撤銷和過期,並優先採用自動化、最小權限與短期憑據;輪換不應只追求「設定頁成功儲存」,而要證明新密鑰已被使用、舊密鑰可撤銷,且失敗時能回到可用狀態。 (cheatsheetseries.owasp.org)
每次輪換至少驗證:
- 新請求能成功通過模型供應商驗證;
- 應用程式日誌沒有輸出完整密鑰;
- 舊密鑰撤銷後,測試請求確實失敗;
- 撤銷或新值無效時,服務有明確告警;
- 回退到上一個仍有效版本後,服務可以恢復。
第四步:按角色拆開查看、修改、部署與審計
團隊權限過寬時,平台再好的密鑰儲存也會變成集中洩露點。你要分清楚「可以部署」和「可以讀出密鑰」不是同一種權限;能觸發正式部署的人,不必然需要看到正式 API Key 的完整內容。
建議採用以下責任分工:
- 開發者:可使用本地或預覽環境,查看非敏感設定,不能讀取正式密鑰。
- 發布者:可執行正式部署、觸發輪換和回退,但不應擁有所有環境的讀取權。
- 管理者:負責成員、環境範圍、撤銷、恢復與審計匯出。
- 自動化帳號:只取得單一專案、單一環境和單一操作所需的權限。
OpenShip 官方定價與產品頁面列出角色、資源權限及審計日誌等能力,但這些是官方功能描述,不是 Macstripe 對目前每一種部署形態的安全驗證結論。你需要建立測試帳號,分別嘗試查看、修改、部署、撤銷和查詢紀錄,再把結果寫入團隊的發布文件。 (openship.io)
若你使用外部 Secrets Vault,審計也不能只記錄「某人登入了平台」。應至少能回答:誰在甚麼時間取得哪個環境的哪一類密鑰、是讀取還是修改、對應哪次部署,以及舊值何時撤銷。專業密鑰系統通常把請求與回應的審計紀錄分開處理,並要求審計設備本身保持可用;這正是你要檢查外部系統是否真正提供的能力。 (developer.hashicorp.com)
第五步:為伺服器故障設計可恢復的密鑰路徑
伺服器備份不等於密鑰備份。你可能成功還原了容器、資料庫和部署設定,卻因為正式密鑰只存在原主機的 .env 或某位離職成員的帳戶中,導致應用程式仍然無法啟動。
恢復流程要分成三層:
- 應用程式資料備份:資料庫、物件檔案、佇列和必要的設定檔。
- 平台配置備份:專案、環境名稱、部署目標、網域與非敏感設定。
- 密鑰恢復來源:OpenShip 的受控密鑰、伺服器系統密鑰或外部 Secrets Vault。
備份檔不應直接存放正式密鑰明文。若必須保存加密的恢復資料,應讓解密權限與日常部署權限分離,並明確指定災難發生時由誰重新授權。使用外部密鑰系統時,還要測試它本身故障、登入方式失效或管理者無法聯絡時,應用程式能否以受控的備援路徑恢復。
你可以在非正式環境先做一次完整演練:建立空白伺服器、還原應用程式資料、重新連接 OpenShip、取得對應環境密鑰、啟動服務,再用測試請求確認模型 API 和資料庫連線。這個流程比「備份檔案存在」更能證明恢復能力。
部署前用這份清單作最後判斷
- [ ] 正式 API Key 沒有出現在程式碼庫、歷史提交或範例設定檔。
- [ ] Dockerfile、建構參數、映像層與建構輸出沒有包含完整密鑰。
- [ ] 前端公開變數與客戶端套件只包含真正可公開的設定。
- [ ] 預覽、測試、正式環境使用不同的模型、資料庫與回呼憑據。
- [ ] 已在目前 OpenShip 版本中實測環境範圍,而不是只依賴官方宣傳文字。
- [ ] 你能分別測試查看、修改、部署、撤銷和審計權限。
- [ ] 更換密鑰後,已確認新請求使用新值。
- [ ] 舊密鑰可以撤銷,撤銷後的失敗會被監控系統發現。
- [ ] 回退流程不會把已撤銷的舊密鑰重新帶回正式環境。
- [ ] 伺服器重建後,團隊仍能在不保存明文備份的情況下恢復服務。
- [ ] 外部 Secrets Vault 的授權失效時,有明確的人工接管與恢復責任人。
如果最後只有前四項通過,你只是避免了最基本的誤提交;要把專案交給團隊長期維護,至少還要完成輪換、權限和恢復測試。關於部署文件、帳戶交接與遠端環境安排,你可以把測試結果整理後放入 Macstripe 幫助中心,讓下一位發布者不必靠口頭經驗重建流程。
平台、伺服器,還是分層方案:最後這樣選
| 你的部署條件 | 建議方案 | 不建議的做法 |
|---|---|---|
| 個人專案、只有應用程式 API Key | OpenShip 環境範圍密鑰 | 把 .env 提交到程式碼庫 |
| 小型團隊,已有預覽與正式環境 | 平台密鑰加環境隔離 | 所有人共用同一組正式憑據 |
| 自建伺服器,密鑰只供主機服務使用 | 伺服器系統管理搭配最小權限 | 讓每個應用程式都讀取整份 .env |
| 正式 AI SaaS、高敏感資料或多人發布 | OpenShip 加外部 Secrets Vault | 把根級憑據複製到平台和主機兩邊 |
| 需要短期建構或代理授權 | 臨時令牌、完成後撤銷 | 使用不過期的共享長期密鑰 |
對大多數 AI SaaS 和 Agent 後端,推薦的起點是「平台管理應用程式密鑰,伺服器管理基礎設施憑據」。當正式資料、團隊規模或權限風險上升,再把高敏感值移到外部 Secrets Vault,由部署程序按環境取得,而不是一開始就把所有事情塞進單一 .env。
如果你目前採用的方案是把所有值放在伺服器 .env,它的真實缺點通常是環境複製容易漂移、成員權限和檔案權限難以分開、輪換依賴人工 SSH,故障後也常找不到完整恢復責任人。對需要臨時算力、遠端建構或多人交接的團隊,租用 Macstripe 的遠端 Mac 建構環境會更容易把建構端、部署端和個人憑據分開;但若你是長期固定重負載,或必須直接接觸特定實體介面,自購 Mac 或保留現有伺服器仍可能更合適。你可先從 Macstripe 首頁了解遠端環境,再按上述清單驗證權限隔離與交付流程。