<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Vps on Tarragon</title><link>https://tarrragon.github.io/blog/tags/vps/</link><description>Recent content in Vps on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 08 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/vps/index.xml" rel="self" type="application/rss+xml"/><item><title>遠端 agent 工作機選型：家用機還是 VPS</title><link>https://tarrragon.github.io/blog/linux/tools/remote/agent-workstation-home-vs-vps/</link><pubDate>Wed, 08 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/linux/tools/remote/agent-workstation-home-vs-vps/</guid><description>&lt;p>遠端 agent 工作機是一台常駐待命的機器：從任何裝置連入、把長任務（編譯、測試、Claude Code 這類 coding agent）丟給它、關掉連線走人、跑完收通知。要架這樣一台機器，第一個選型問題是機器擺在哪——家用機還是租 VPS。這個決策取決於三個維度：連線延遲、家用 IP 的穩定性、環境隔離。這篇逐項拆解這三個維度，結論是它們各自都有軟體層的標準解、跟機器擺在哪無關；把工作環境拆成連線、session、隔離三層獨立能力之後，家用機與 VPS 的差異只剩唯一一個變數——機器由誰保證活著。這篇是 &lt;a href="../remote-agent-paved-road/">把遠端 agent 工作機鋪成一條路&lt;/a> 的起點（形態選型）；整條從零到可用的順序總覽見那篇。&lt;/p>
&lt;p>工具本身的選型與配置這篇只給路由：連線工具的比較見 &lt;a href="../connection-and-sync-tools/">遠端連線與同步工具選型&lt;/a>、tailnet 網路層機制見 &lt;a href="../tailscale-tailnet-and-relay/">Tailscale tailnet 與中繼&lt;/a>、多工器見 &lt;a href="../../cli/tmux-persistence-and-basics/">tmux 基礎&lt;/a> 與 &lt;a href="../../cli/zellij-pane/">zellij 操作&lt;/a>、推播通知見 &lt;a href="../../../debug/ntfy-push-notification-service/">ntfy 推播服務&lt;/a>。這篇聚焦在這些工具之上的選型判斷。&lt;/p>
&lt;h2 id="使用形態先於機器選擇">使用形態先於機器選擇&lt;/h2>
&lt;p>選型的起點是使用形態：agent 工作機的典型循環是「連入 → 丟任務 → 斷線 → 收通知 → 回來看結果」，連線只在丟任務跟看結果的幾分鐘存在、任務在斷線期間持續執行。這個形態對機器提出四個成立條件，全部落在軟體層：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>成立條件&lt;/th>
 &lt;th>承擔的問題&lt;/th>
 &lt;th>對應工具與路由&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>session 獨立於連線存活&lt;/td>
 &lt;td>手機切網路、app 進背景、斷線後任務照跑&lt;/td>
 &lt;td>多工器，見 &lt;a href="../../cli/tmux-persistence-and-basics/">tmux 基礎&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>結果主動推出來&lt;/td>
 &lt;td>跑完主動通知到手機、人可以離開&lt;/td>
 &lt;td>agent hook 接 &lt;a href="../../../debug/ntfy-push-notification-service/">ntfy 推播&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>行動端輸入可用&lt;/td>
 &lt;td>終端 UI 依賴 Esc / Ctrl / 方向鍵、手機鍵盤缺這些&lt;/td>
 &lt;td>SSH client 的擴充鍵列（Termius、Blink Shell 這類）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>工作負載與機器本體隔離&lt;/td>
 &lt;td>環境可重現、agent 權限有邊界、爆掉不拖垮機器&lt;/td>
 &lt;td>container，見下方隔離段&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>行動端輸入是四個條件裡最容易被漏掉的一個：手機的軟體鍵盤預設沒有 Esc、Ctrl、方向鍵，而 coding agent 的終端介面重度依賴這些按鍵做中斷與模式切換。SSH client 有沒有提供擴充鍵列，決定手機端是「可操作」還是「只能看」——這個條件跟機器擺在哪完全無關，卻常是整套手機工作流用不下去的真正原因。&lt;/p>
&lt;p>四個條件都跟機器位置無關，這是後面所有判斷的基礎：家用機跟 VPS 要跑的軟體層是同一套，選型比較的只剩機器層本身。&lt;/p>
&lt;h2 id="延遲拆成生成延遲與按鍵回顯兩層">延遲：拆成生成延遲與按鍵回顯兩層&lt;/h2>
&lt;p>遠端跑 agent 的延遲由兩個獨立來源組成，影響方式完全不同，混在一起看會高估遠端的代價：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>延遲層&lt;/th>
 &lt;th>決定因素&lt;/th>
 &lt;th>對體感的影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>生成延遲&lt;/td>
 &lt;td>agent 後端的模型推論速度&lt;/td>
 &lt;td>秒級、本機跑也一樣要等，跟機器擺在哪無關&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>按鍵回顯延遲&lt;/td>
 &lt;td>使用者到機器的網路 RTT&lt;/td>
 &lt;td>每個按鍵都要走一趟 RTT 才顯示，打字時直接有感&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>agent 的使用形態稀釋了 RTT 的影響：多數時間在等模型輸出，真正暴露在 RTT 下的只有打 prompt 的那幾秒。所以延遲問題的判讀是「按鍵回顯能不能接受」，而按鍵回顯由兩件事決定：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>機房地理位置&lt;/strong>。RTT 由物理距離主導：台灣連東亞機房約幾十毫秒、體感接近本機；連歐美機房動輒兩三百毫秒、每個按鍵都慢半拍。租 VPS 時機房位置的優先序高於所有工具層優化——選錯地理位置、後面的工具都在補救。家用機在這一層佔優：機器通常就在同一個城市、RTT 貼近本機。&lt;/li>
&lt;li>&lt;strong>連線工具的回顯策略&lt;/strong>。mosh 用本地回顯預測把按鍵立即顯示、不等 RTT，行動網路下再疊上 UDP 漫遊；工具比較與代價見 &lt;a href="../connection-and-sync-tools/">遠端連線與同步工具選型&lt;/a>的連線層段。&lt;/li>
&lt;/ol>
&lt;p>判讀訊號：如果工作流已經是「丟任務、關連線、收通知」的形態（上一段的四條件成立），延遲的權重會再降一級——掛在終端上盯著跑的時間本來就少。反過來說，若使用形態是長時間逐鍵互動（遠端 vim 改程式碼），RTT 的體感成本就高，機房地理與 mosh 都省不掉。&lt;/p>
&lt;h2 id="浮動-ip可達性由網路層承擔">浮動 IP：可達性由網路層承擔&lt;/h2>
&lt;p>「家用 IP 會變、所以連不到」把兩個不同層的問題混在一起了。可達性（找得到機器、連得進去）是網路層的責任，mesh VPN（Tailscale 這類、或自建 WireGuard）給每台裝置一個私網內固定的位址與主機名，跟機器當下的公網 IP 解耦：機器的實際網路位置變了，由它自己向協調伺服器回報、連線自動重建。家用 IP 重撥、手機在 Wi-Fi 與行動網路間切換、甚至機器在電信業者級 NAT（CGNAT，多戶共用一個公網 IP、對外開 port 這條路直接消失）後面，可達性都成立。工具的取捨與配置見 &lt;a href="../connection-and-sync-tools/">遠端連線與同步工具選型&lt;/a>的網路層段。&lt;/p>
&lt;p>這個設計同時把「定位」跟「授權」合併成同一層：連得到私網位址，代表裝置已通過 tailnet 認證。SSH / ttyd 這類服務可以只綁私網介面、公網防火牆全關，對外攻擊面收攏到零個開放 port——比開公網 port 再堆疊 fail2ban 這類防護的維護成本低得多。&lt;/p>
&lt;p>IP 相關真正需要 VPS 的情境只剩一種：&lt;strong>出口 IP 要固定&lt;/strong>——例如某個外部服務要求固定來源 IP 才能加白名單。這是「從機器連出去」的需求，跟「連得進機器」是兩回事；沒有這個需求，浮動 IP 就已經被網路層完整處理掉了。&lt;/p>
&lt;p>判讀訊號：IP 變動的瞬間（PPPoE 重撥、光貓重啟）已建立的連線會斷幾秒到幾十秒。session 獨立於連線存活的設計（使用形態段的第一個條件）讓這個空窗無感——任務照跑、重連接回。兩個設計互相搭配、單獨看都會高估斷線的代價。&lt;/p>
&lt;h2 id="隔離容器把環境跟機器解耦">隔離：容器把環境跟機器解耦&lt;/h2>
&lt;p>環境隔離發生在 container 層、跟機器擺在哪無關：同一個 Docker image 在家用 VM 跟 VPS 上是同一個環境。這帶來一個比隔離本身更重要的性質——&lt;strong>選型決策變成可逆的&lt;/strong>。在家用機上把 image 跑通，之後要搬 VPS 是 &lt;code>docker pull&lt;/code> 加 bootstrap 的事（環境還原的方法論見 &lt;a href="../../../dotfile/08-sync-bootstrap/bootstrap-script-packages/">bootstrap 腳本與套件清單&lt;/a>）；在家用機上投入的所有配置工夫，同時就是 VPS 的遷移準備、沒有沉沒成本。&lt;/p>
&lt;p>container 隔離有三個要先劃清的邊界：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>信任邊界等於 mount 清單&lt;/strong>。container 隔離的意義是 agent 只碰得到掛進去的檔案與目錄，所以掛載清單就是授權清單：專案目錄是工作對象、要掛；版本控制的推送憑證是高權限物、掛完整 SSH key 等於打穿邊界，可以改用範圍受限的 deploy key、或把推送動作留在 host 側（完整金鑰 vs deploy key 的信任邊界見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys&lt;/a>）。第三條路是完全不把 SSH 私鑰放進 container——用 fine-grained PAT 當 &lt;code>GH_TOKEN&lt;/code> 走環境變數注入、git 用 &lt;code>gh&lt;/code> 的 credential helper 現讀，跟 Claude Code token 同一套注入機制、爆炸半徑更小，見 &lt;a href="../claude-code-container-and-hooks/">在 container 裡跑 Claude Code&lt;/a> 的 GitHub 認證段。要讓 agent 更自主地跑的話，Claude Code 官方文件有 devcontainer 參考配置、含網路出口 allowlist，團隊環境的 devcontainer 定位見 &lt;a href="../../../dotfile/09-team-environment/devcontainer-nix/">devcontainer 與 Nix&lt;/a>。&lt;/li>
&lt;li>&lt;strong>狀態要顯式持久化，且認證與設定走不同路&lt;/strong>。container 內要活過重建的狀態分兩類、持久化方式不同。&lt;strong>設定&lt;/strong>（Claude Code 的 &lt;code>settings.json&lt;/code>、hooks）掛成 volume 就跨重建持久化。&lt;strong>認證&lt;/strong>則不走 volume——實測 Claude Code 的 &lt;code>setup-token&lt;/code> 給的是長效 token 的環境變數注入模型（token 是機密、存在 host 側、&lt;code>docker run&lt;/code> 時注入），而不是「持久化登入態到 &lt;code>~/.claude&lt;/code>」。兩者分離反而更乾淨：憑證輪替只換注入的機密檔、不碰 volume，rebuild image 也不影響認證。機制與踩過的坑見 &lt;a href="../claude-code-container-and-hooks/">在 container 裡跑 Claude Code&lt;/a>、機密為何 runtime 注入見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/runtime-secret-injection/" data-link-title="Runtime Secret Injection（機密注入）" data-link-desc="要決定 token / 金鑰放哪、能不能烤進 image 或提交進（即使私有的）repo 時回來讀">機密 runtime 注入&lt;/a>。&lt;/li>
&lt;li>&lt;strong>資源上限把連線基礎設施跟工作負載分開&lt;/strong>。給 container 設 memory / CPU 上限，編譯爆記憶體時死的是 container 內的編譯程序，host 上的 VPN daemon 與多工器不受波及——斷線存活的設計要成立，前提是連線基礎設施活得比工作負載久。&lt;/li>
&lt;/ul>
&lt;h2 id="三層拆完選型只剩機器由誰養">三層拆完、選型只剩機器由誰養&lt;/h2>
&lt;p>把前三段收攏：遠端工作環境由三層獨立能力組成，每層各自可替換、且在家用機與 VPS 上是同一套：&lt;/p></description><content:encoded><![CDATA[<p>遠端 agent 工作機是一台常駐待命的機器：從任何裝置連入、把長任務（編譯、測試、Claude Code 這類 coding agent）丟給它、關掉連線走人、跑完收通知。要架這樣一台機器，第一個選型問題是機器擺在哪——家用機還是租 VPS。這個決策取決於三個維度：連線延遲、家用 IP 的穩定性、環境隔離。這篇逐項拆解這三個維度，結論是它們各自都有軟體層的標準解、跟機器擺在哪無關；把工作環境拆成連線、session、隔離三層獨立能力之後，家用機與 VPS 的差異只剩唯一一個變數——機器由誰保證活著。這篇是 <a href="../remote-agent-paved-road/">把遠端 agent 工作機鋪成一條路</a> 的起點（形態選型）；整條從零到可用的順序總覽見那篇。</p>
<p>工具本身的選型與配置這篇只給路由：連線工具的比較見 <a href="../connection-and-sync-tools/">遠端連線與同步工具選型</a>、tailnet 網路層機制見 <a href="../tailscale-tailnet-and-relay/">Tailscale tailnet 與中繼</a>、多工器見 <a href="../../cli/tmux-persistence-and-basics/">tmux 基礎</a> 與 <a href="../../cli/zellij-pane/">zellij 操作</a>、推播通知見 <a href="../../../debug/ntfy-push-notification-service/">ntfy 推播服務</a>。這篇聚焦在這些工具之上的選型判斷。</p>
<h2 id="使用形態先於機器選擇">使用形態先於機器選擇</h2>
<p>選型的起點是使用形態：agent 工作機的典型循環是「連入 → 丟任務 → 斷線 → 收通知 → 回來看結果」，連線只在丟任務跟看結果的幾分鐘存在、任務在斷線期間持續執行。這個形態對機器提出四個成立條件，全部落在軟體層：</p>
<table>
  <thead>
      <tr>
          <th>成立條件</th>
          <th>承擔的問題</th>
          <th>對應工具與路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>session 獨立於連線存活</td>
          <td>手機切網路、app 進背景、斷線後任務照跑</td>
          <td>多工器，見 <a href="../../cli/tmux-persistence-and-basics/">tmux 基礎</a></td>
      </tr>
      <tr>
          <td>結果主動推出來</td>
          <td>跑完主動通知到手機、人可以離開</td>
          <td>agent hook 接 <a href="../../../debug/ntfy-push-notification-service/">ntfy 推播</a></td>
      </tr>
      <tr>
          <td>行動端輸入可用</td>
          <td>終端 UI 依賴 Esc / Ctrl / 方向鍵、手機鍵盤缺這些</td>
          <td>SSH client 的擴充鍵列（Termius、Blink Shell 這類）</td>
      </tr>
      <tr>
          <td>工作負載與機器本體隔離</td>
          <td>環境可重現、agent 權限有邊界、爆掉不拖垮機器</td>
          <td>container，見下方隔離段</td>
      </tr>
  </tbody>
</table>
<p>行動端輸入是四個條件裡最容易被漏掉的一個：手機的軟體鍵盤預設沒有 Esc、Ctrl、方向鍵，而 coding agent 的終端介面重度依賴這些按鍵做中斷與模式切換。SSH client 有沒有提供擴充鍵列，決定手機端是「可操作」還是「只能看」——這個條件跟機器擺在哪完全無關，卻常是整套手機工作流用不下去的真正原因。</p>
<p>四個條件都跟機器位置無關，這是後面所有判斷的基礎：家用機跟 VPS 要跑的軟體層是同一套，選型比較的只剩機器層本身。</p>
<h2 id="延遲拆成生成延遲與按鍵回顯兩層">延遲：拆成生成延遲與按鍵回顯兩層</h2>
<p>遠端跑 agent 的延遲由兩個獨立來源組成，影響方式完全不同，混在一起看會高估遠端的代價：</p>
<table>
  <thead>
      <tr>
          <th>延遲層</th>
          <th>決定因素</th>
          <th>對體感的影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>生成延遲</td>
          <td>agent 後端的模型推論速度</td>
          <td>秒級、本機跑也一樣要等，跟機器擺在哪無關</td>
      </tr>
      <tr>
          <td>按鍵回顯延遲</td>
          <td>使用者到機器的網路 RTT</td>
          <td>每個按鍵都要走一趟 RTT 才顯示，打字時直接有感</td>
      </tr>
  </tbody>
</table>
<p>agent 的使用形態稀釋了 RTT 的影響：多數時間在等模型輸出，真正暴露在 RTT 下的只有打 prompt 的那幾秒。所以延遲問題的判讀是「按鍵回顯能不能接受」，而按鍵回顯由兩件事決定：</p>
<ol>
<li><strong>機房地理位置</strong>。RTT 由物理距離主導：台灣連東亞機房約幾十毫秒、體感接近本機；連歐美機房動輒兩三百毫秒、每個按鍵都慢半拍。租 VPS 時機房位置的優先序高於所有工具層優化——選錯地理位置、後面的工具都在補救。家用機在這一層佔優：機器通常就在同一個城市、RTT 貼近本機。</li>
<li><strong>連線工具的回顯策略</strong>。mosh 用本地回顯預測把按鍵立即顯示、不等 RTT，行動網路下再疊上 UDP 漫遊；工具比較與代價見 <a href="../connection-and-sync-tools/">遠端連線與同步工具選型</a>的連線層段。</li>
</ol>
<p>判讀訊號：如果工作流已經是「丟任務、關連線、收通知」的形態（上一段的四條件成立），延遲的權重會再降一級——掛在終端上盯著跑的時間本來就少。反過來說，若使用形態是長時間逐鍵互動（遠端 vim 改程式碼），RTT 的體感成本就高，機房地理與 mosh 都省不掉。</p>
<h2 id="浮動-ip可達性由網路層承擔">浮動 IP：可達性由網路層承擔</h2>
<p>「家用 IP 會變、所以連不到」把兩個不同層的問題混在一起了。可達性（找得到機器、連得進去）是網路層的責任，mesh VPN（Tailscale 這類、或自建 WireGuard）給每台裝置一個私網內固定的位址與主機名，跟機器當下的公網 IP 解耦：機器的實際網路位置變了，由它自己向協調伺服器回報、連線自動重建。家用 IP 重撥、手機在 Wi-Fi 與行動網路間切換、甚至機器在電信業者級 NAT（CGNAT，多戶共用一個公網 IP、對外開 port 這條路直接消失）後面，可達性都成立。工具的取捨與配置見 <a href="../connection-and-sync-tools/">遠端連線與同步工具選型</a>的網路層段。</p>
<p>這個設計同時把「定位」跟「授權」合併成同一層：連得到私網位址，代表裝置已通過 tailnet 認證。SSH / ttyd 這類服務可以只綁私網介面、公網防火牆全關，對外攻擊面收攏到零個開放 port——比開公網 port 再堆疊 fail2ban 這類防護的維護成本低得多。</p>
<p>IP 相關真正需要 VPS 的情境只剩一種：<strong>出口 IP 要固定</strong>——例如某個外部服務要求固定來源 IP 才能加白名單。這是「從機器連出去」的需求，跟「連得進機器」是兩回事；沒有這個需求，浮動 IP 就已經被網路層完整處理掉了。</p>
<p>判讀訊號：IP 變動的瞬間（PPPoE 重撥、光貓重啟）已建立的連線會斷幾秒到幾十秒。session 獨立於連線存活的設計（使用形態段的第一個條件）讓這個空窗無感——任務照跑、重連接回。兩個設計互相搭配、單獨看都會高估斷線的代價。</p>
<h2 id="隔離容器把環境跟機器解耦">隔離：容器把環境跟機器解耦</h2>
<p>環境隔離發生在 container 層、跟機器擺在哪無關：同一個 Docker image 在家用 VM 跟 VPS 上是同一個環境。這帶來一個比隔離本身更重要的性質——<strong>選型決策變成可逆的</strong>。在家用機上把 image 跑通，之後要搬 VPS 是 <code>docker pull</code> 加 bootstrap 的事（環境還原的方法論見 <a href="../../../dotfile/08-sync-bootstrap/bootstrap-script-packages/">bootstrap 腳本與套件清單</a>）；在家用機上投入的所有配置工夫，同時就是 VPS 的遷移準備、沒有沉沒成本。</p>
<p>container 隔離有三個要先劃清的邊界：</p>
<ul>
<li><strong>信任邊界等於 mount 清單</strong>。container 隔離的意義是 agent 只碰得到掛進去的檔案與目錄，所以掛載清單就是授權清單：專案目錄是工作對象、要掛；版本控制的推送憑證是高權限物、掛完整 SSH key 等於打穿邊界，可以改用範圍受限的 deploy key、或把推送動作留在 host 側（完整金鑰 vs deploy key 的信任邊界見 <a href="/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys</a>）。第三條路是完全不把 SSH 私鑰放進 container——用 fine-grained PAT 當 <code>GH_TOKEN</code> 走環境變數注入、git 用 <code>gh</code> 的 credential helper 現讀，跟 Claude Code token 同一套注入機制、爆炸半徑更小，見 <a href="../claude-code-container-and-hooks/">在 container 裡跑 Claude Code</a> 的 GitHub 認證段。要讓 agent 更自主地跑的話，Claude Code 官方文件有 devcontainer 參考配置、含網路出口 allowlist，團隊環境的 devcontainer 定位見 <a href="../../../dotfile/09-team-environment/devcontainer-nix/">devcontainer 與 Nix</a>。</li>
<li><strong>狀態要顯式持久化，且認證與設定走不同路</strong>。container 內要活過重建的狀態分兩類、持久化方式不同。<strong>設定</strong>（Claude Code 的 <code>settings.json</code>、hooks）掛成 volume 就跨重建持久化。<strong>認證</strong>則不走 volume——實測 Claude Code 的 <code>setup-token</code> 給的是長效 token 的環境變數注入模型（token 是機密、存在 host 側、<code>docker run</code> 時注入），而不是「持久化登入態到 <code>~/.claude</code>」。兩者分離反而更乾淨：憑證輪替只換注入的機密檔、不碰 volume，rebuild image 也不影響認證。機制與踩過的坑見 <a href="../claude-code-container-and-hooks/">在 container 裡跑 Claude Code</a>、機密為何 runtime 注入見 <a href="/blog/linux/dotfile/knowledge-cards/runtime-secret-injection/" data-link-title="Runtime Secret Injection（機密注入）" data-link-desc="要決定 token / 金鑰放哪、能不能烤進 image 或提交進（即使私有的）repo 時回來讀">機密 runtime 注入</a>。</li>
<li><strong>資源上限把連線基礎設施跟工作負載分開</strong>。給 container 設 memory / CPU 上限，編譯爆記憶體時死的是 container 內的編譯程序，host 上的 VPN daemon 與多工器不受波及——斷線存活的設計要成立，前提是連線基礎設施活得比工作負載久。</li>
</ul>
<h2 id="三層拆完選型只剩機器由誰養">三層拆完、選型只剩機器由誰養</h2>
<p>把前三段收攏：遠端工作環境由三層獨立能力組成，每層各自可替換、且在家用機與 VPS 上是同一套：</p>
<table>
  <thead>
      <tr>
          <th>層</th>
          <th>承擔的問題</th>
          <th>工具</th>
          <th>家用機 vs VPS</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>連線層</td>
          <td>找到機器、斷了接得回</td>
          <td>Tailscale + mosh</td>
          <td>同一套、無差異</td>
      </tr>
      <tr>
          <td>session 層</td>
          <td>工作獨立於連線存活</td>
          <td>zellij / tmux</td>
          <td>同一套、無差異</td>
      </tr>
      <tr>
          <td>隔離層</td>
          <td>環境可重現、可搬遷</td>
          <td>container image</td>
          <td>同一套、無差異</td>
      </tr>
      <tr>
          <td>機器層</td>
          <td>硬體活著、供電、對外網路</td>
          <td>——</td>
          <td>唯一差異：誰來保證</td>
      </tr>
  </tbody>
</table>
<p>VPS 買到的價值在這個框架下看得很清楚：排除掉延遲（機房地理反而是家用機佔優）、IP（網路層已解）、隔離（container 已解）之後，月費換到的是<strong>託管的存活保證</strong>——停電、硬體故障、機器重啟有人兜底。對應地，家用機路線的成立前提是：宿主機常開、可接受偶發的停電與當機、有人（自己）在機器掛掉時處理。</p>
<p>由此得出的決策路徑：</p>
<ul>
<li><strong>家用機起手</strong>：宿主機本來就常開的話，先在家用 VM 把三層架構跑通。這條路同時回答兩個問題——工作流成不成立（四個成立條件的實測）、以及到底需不需要一台雲端機器。隔離層的可逆性讓這個起手沒有機會成本：所有投入都能原封搬走。</li>
<li><strong>直接租 VPS 合理的情境</strong>：家裡機器沒有常開的條件（筆電為主、電費 / 噪音考量）、需要固定出口 IP、或需要比家用頻寬更好的對外網路。這時下一段的規格判讀框架接手。</li>
<li><strong>兩邊並存</strong>：家用機當日常主力、VPS 短租應付出遠門或高負載時段——隔離層可逆性讓切換成本趨近於零，這個混合形態才因此可行。</li>
</ul>
<h2 id="vps-租用評估的判讀框架">VPS 租用評估的判讀框架</h2>
<p>規格與計費的具體數字隨市場變動，這段只給不會過期的判讀維度；每個維度標出判讀訊號與常見的認知偏差。</p>
<p><strong>CPU 與 RAM：瓶頸在工作負載、不在 agent 本體。</strong> agent 程序本身輕量（常駐程序加網路請求），吃資源的是它觸發的編譯與測試。抓規格拿實際峰值當基準：在現有機器上跑一次典型的編譯、用 <code>htop</code> 記下 RAM 峰值，以此估算。RAM 的風險形態比 CPU 尖銳——CPU 到頂是變慢、RAM 到頂是 OOM killer 直接砍掉 build（退出碼 137，見 <a href="/blog/linux/dotfile/knowledge-cards/oom-exit-code-137/" data-link-title="OOM Killer and Exit Code 137（OOM killer 與退出碼 137）" data-link-desc="程序或 container 被無預警砍掉、退出碼是 137、或編譯 / 測試在記憶體吃緊時突然死掉、要判斷是不是記憶體不足時回來讀">OOM killer 與退出碼 137</a>），所以 RAM 要留餘裕、再配 swap 當安全網。CPU 有 burstable（基準額度 + 短時衝高、持續滿載會被限速）與 dedicated（隨時滿載）兩種計費形態：編譯是短時吃滿的型態、burstable 通常划算；長時間持續重負載才需要 dedicated。</p>
<p><strong>磁碟：低估的大戶是套件快取跟 container layer。</strong> 語言套件快取（node_modules、cargo registry 這類）與 container image layer 的膨脹速度遠超直覺，用 container 的配置對磁碟需求要抓寬——省下的是日後反覆清 image 的維護工。</p>
<p><strong>流量：「只有 SSH 流量」是常見的低估。</strong> 套件安裝、container image 拉取、git 操作、agent 對後端 API 的持續請求都是對外流量；SSH 本身反而微不足道。多數 VPS 方案的流量額度對單人開發機綽綽有餘，這個維度要調整的是認知、規格照常抓即可。</p>
<p><strong>計費模式：停機是否計費要在租用前查。</strong> 「用完關機省錢」這個直覺在多數按小時計費的 VPS 上落空：實例存在就佔著 CPU、RAM、磁碟與 IP，關機狀態照常計費、停止計費要刪除實例。單人可預測負載（自己按下去才會忙）選固定月費最單純；動態擴縮機制服務的是無法預測的線上流量、對這個情境是多付的複雜度。</p>
<p><strong>機房地理：延遲段的結論在這裡落地。</strong> 按鍵回顯的 RTT 由機房到使用者的物理距離主導，地理位置的優先序高於規格——同規格下選近的機房，體感差距比多一顆 vCPU 大得多。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>把這篇的三層架構在 VM 上實際架起來（十步驟 + 三情境、每步含實測除錯判讀）：<a href="../agent-workstation-vm-handson/">遠端 agent 工作機實作記錄</a></li>
<li>連線與同步工具的具體比較（ssh / mosh / autossh、Tailscale / WireGuard、rsync / mutagen）：<a href="../connection-and-sync-tools/">遠端連線與同步工具選型</a></li>
<li>多工器讓 session 獨立於連線：<a href="../../cli/tmux-persistence-and-basics/">tmux 基礎</a>、<a href="../../cli/zellij-pane/">zellij 操作</a></li>
<li>跑完主動推播：<a href="../../../debug/ntfy-push-notification-service/">ntfy 推播通知服務</a></li>
<li>讓機器無人值守跑完長任務（互動提示、斷線即死、結果推送三個障礙）：<a href="../../../install/unattended-remote-work/">讓機器跑無人值守的長任務</a></li>
<li>環境一鍵還原的方法論：<a href="../../../dotfile/08-sync-bootstrap/bootstrap-script-packages/">bootstrap 腳本與套件清單</a></li>
</ul>
]]></content:encoded></item></channel></rss>