Synology NAS 安裝 Codex CLI 實戰:手機 Web Terminal、網站修改與 Docker 重建

作者:

分類:

這篇文章記錄如何在 Synology NAS 上把 Codex CLI 做成長期運作的 Container 服務,透過手機瀏覽器進入 Web Terminal,直接修改 NAS 上的多個網站,並用一個受限制的專屬指令完成 restart、up 與 rebuild。

先看結論:這套架構完成後能做什麼?

完成後,可以用手機或電腦瀏覽器連進 NAS 上的 Web Terminal,讓 Codex CLI 直接讀寫指定網站;對話由 tmux 保留,部署則交給只接受白名單專案與動作的 project-helper。第一次建置建議預留 30~60 分鐘;後面的「10 分鐘」是指檔案、帳號與權限已經備妥後的部署檢查流程。

只想先架起來:先看「最終成功架構摘要」與「10 分鐘快速部署清單」。
想理解設計:再讀 Codex CLI、ttyd、tmux、目錄掛載與安全邊界。
已經出錯:直接跳到疑難排解表。

最終成功架構摘要

整套系統可以分成「瀏覽器操作」、「持久終端」、「程式修改」與「受限制部署」四層。Codex 不需要直接取得整台 NAS 的控制權,也不需要直接掛載 Docker socket。

手機/電腦瀏覽器
ttyd Web Terminal
tmux + Codex CLI Container
相簿、網誌原始碼與 Git
project-helper → Docker Compose
元件 唯一責任 成功判斷 安全界線
ttyd 把終端送到瀏覽器 手機能開啟、輸入中文及執行指令 不直接對外開放 7681;外出使用 VPN 或 HTTPS
tmux 保存終端工作階段 關閉頁面後重新連線,原工作仍在 不負責帳號驗證,也不取代 ttyd 的連線保護
Codex CLI 分析與修改指定專案 可在 /workspace/專案 改檔及執行測試 只看得到 Compose 明確掛載的目錄
Volumes 界定可讀寫範圍 目標網站可寫,參考資料使用 :ro 不掛載整個 /volume1
project-helper 代為執行受限部署 project-control restart|up|rebuild 專案 可用 Token、專案、路徑與動作皆採白名單
Container Manager 管理 Compose 生命週期 服務保持 running,網站正常回應 Codex 不直接掛載 Docker socket


10 分鐘快速部署清單

開始前:NAS 已安裝 Container Manager;已建立 /volume1/docker/codex;Dockerfile、啟動腳本、Compose 與 helper 白名單均已依後文備妥。首次下載映像、建置與登入所需時間不計入 10 分鐘。
  1. 0–2 分鐘|確認檔案:放好 Dockerfile、compose.yaml、ttyd/tmux 啟動腳本及 .env;不要把 Token 寫入映像或 Git。
  2. 2–4 分鐘|限制掛載:只把相簿與網誌掛載到 /workspace/專案名;參考資料加上 :ro,不要掛載整個 NAS 或 Docker socket。
  3. 4–6 分鐘|建立專案:在 Container Manager 建立 Codex Project,載入 Compose 後建置並啟動。
  4. 6–7 分鐘|檢查終端:於區域網路開啟 http://NAS_IP:7681/,確認 ttyd 與中文輸入正常。
  5. 7–8 分鐘|登入 Codex:執行 codex 完成登入,以 codex resume --last 驗證續接。
  6. 8–9 分鐘|驗證權限:進入 /workspace/專案名 執行 git status,做一項可還原的小修改並檢查差異。
  7. 9–10 分鐘|驗證部署:執行 project-control restart 專案名;確認陌生專案與未允許動作會被拒絕。
完成標準:瀏覽器可操作 → 斷線可續接 → 只看得到指定專案 → 可修改並檢查 Git 差異 → 白名單部署成功 → 網站與 Container 正常。六項全部通過才算完成。

接著怎麼讀:照做請從Synology 前置準備開始;理解元件請讀Codex CLI與ttyd/tmux;失敗時直接看疑難排解。

一、為什麼把 Codex CLI 放在 Synology NAS?

我的網站與 Docker 專案原本就放在 Synology NAS。如果每次修改都要先開 Windows 電腦、連線 NAS、下載檔案、修改後再上傳,流程很容易被切碎。把 Codex CLI 放進 NAS 的 Container 後,手機或電腦只需要一個瀏覽器,就能回到同一個終端工作階段。

NAS 並不是在本機執行大型 AI 模型。Codex CLI 主要連線使用 OpenAI 模型,NAS 負責保存專案、執行命令、修改檔案與管理容器,因此 x86_64 的 Synology 機種即使效能不算高,也能負擔這種工作方式。

實際得到的改變:Windows 不必一直開著;出門時可用手機接續工作;網站原始碼、Git 與部署命令都在 NAS 上完成;tmux 還能在瀏覽器斷線後保留工作階段。

↑ 回到目錄

二、Codex 與 Codex CLI 有什麼不同?

Codex 是 OpenAI 的程式開發代理與整體產品能力,可以出現在不同操作介面,例如桌面應用程式、IDE 擴充功能、雲端環境及終端機。它能理解程式庫、規劃修改、編輯檔案、執行命令與檢查差異。

Codex CLI 則是其中一種官方操作介面。CLI 是 Command-Line Interface 的縮寫,也就是「命令列介面」。安裝後,在專案目錄輸入 codex,便能讓 Codex 讀取該環境中的檔案,並使用 Container 內已安裝的 Git、npm、curl 或其他開發工具。

名稱 代表意義 與 NAS 的關係
Codex OpenAI 的程式開發代理與產品能力 負責理解需求、分析程式碼、提出修改並呼叫可用工具;不專指某一個畫面。
Codex CLI 在終端機執行的 Codex 客戶端 可安裝於 Linux Container,直接讀寫掛載進來的 NAS 專案並執行本地命令,因此最適合 DSM。
Codex 圖形介面 桌面應用程式或 IDE 中的操作介面 通常需要完整桌面系統或支援的程式編輯器;Synology DSM 並不是一般桌面 Linux,因此不能直接照搬。
簡單比喻:Codex 是會寫程式、能使用工具的代理;Codex CLI 是在終端機和它互動的其中一個入口。本文安裝的不是較陽春的另一套 AI,而是使用 CLI 介面來操作 Codex。

OpenAI 官方將 Codex CLI 定位為可在終端中檢查程式碼、修改檔案、執行命令及串接自動化流程的工具。它和桌面版、IDE 擴充功能、Codex cloud 是不同操作表面,各自適合不同環境。

↑ 回到目錄

三、ttyd 是什麼?NAS 為何看起來只有文字介面?

ttyd:把終端機送進瀏覽器的小型 Web 服務

ttyd 是一個開源的 Web Terminal 工具。它會啟動指定的終端程式,建立瀏覽器可顯示的終端畫面,再利用 HTTP 與 WebSocket 傳送鍵盤輸入和即時輸出。如此一來,手機不必安裝 SSH App,只要開啟瀏覽器,就能操作 Container 裡的命令列。

ttyd 本身不是 AI、不是 Shell,也不負責保存 Codex 對話。它比較像一座橋:

手機瀏覽器
ttyd 網頁終端
tmux
Codex CLI
網站專案
  • ttyd:把終端畫面送到瀏覽器,接收鍵盤輸入。
  • tmux:保存正在執行的終端工作階段,瀏覽器斷線後仍繼續運作。
  • Codex CLI:提供 Codex 對話、程式分析、修改檔案與執行命令的能力。
  • Docker volume:決定 Codex 在 NAS 上能看到和修改哪些目錄。

NAS 並非絕對只能使用 CLI,而是 CLI 最符合它的環境

Synology DSM 本質上是以網頁管理的 NAS 作業系統,底層雖然是 Linux,但不是平常用滑鼠操作的 Ubuntu、Windows 或 macOS 桌面。Container 通常也只包含程式執行所需的最小環境,沒有桌面、視窗系統、VS Code 或可直接顯示 Codex 圖形介面的螢幕。

因此,在 NAS 上直接安裝官方支援 Linux 的 Codex CLI 最自然:它不需要桌面環境,能直接在專案資料夾工作,又可以透過 Docker volume 精確限制目錄。ttyd 再把這個文字介面包成手機可使用的網頁,tmux 則補上斷線續接。

方式 可行性 實際限制
Codex CLI + ttyd 最適合 資源需求低、可直接操作 NAS 檔案,手機可用;介面仍是終端形式。
SSH + Codex CLI 可行 最簡單,但手機需要 SSH App,且每次都像在操作遠端命令列。
NAS 內安裝桌面與遠端桌面 不建議 需要額外桌面、VNC 或瀏覽器環境,增加記憶體消耗、維護與攻擊面。
自行開發 Codex Web GUI 可行 必須另外實作有狀態對話、任務佇列、串流輸出、檔案差異、修改前確認與權限控制。
所以「NAS 只能用文字介面」並不完全正確。更精確的說法是:DSM 沒有現成的 Codex 桌面介面,而 Codex CLI 是最容易在 NAS Linux Container 中安裝、最能直接操作本機專案,也最不需要額外開發的官方介面。

↑ 回到目錄

四、最後採用的 Container 架構

最後版本不是把 Codex 直接安裝進 DSM,也不是讓 Codex Container 任意操控整台 NAS,而是拆成兩條路徑:

手機或電腦
ttyd Web Terminal
tmux 工作階段
Codex CLI
已掛載的網站目錄
Codex CLI
project-control
project-helper
專案白名單
Docker Compose

codex-web 只負責終端與檔案工作,不直接掛載 /var/run/docker.sock。需要重啟或重建網站時,Codex 呼叫 project-control,再由獨立的 project-helper 驗證 Token、動作與專案白名單。這樣比把 Docker socket 直接交給 Codex 更容易限制範圍。

重要觀念:project-control 不是 Codex 內建命令,而是為這套 NAS 架構建立的包裝指令。它只接受預先允許的專案與動作。
本文匿名說明:為避免公開真實網站與服務結構,後文只使用 photo(相簿)與 wordpress(網誌)作為示範名稱;讀者應替換成自己的專案名稱與目錄。

↑ 回到目錄

五、從只能 SSH 重啟,改成 Container Manager 專案

最初版本雖然能在 NAS 執行 Codex CLI,但每次啟動、停止或重啟都必須先從電腦 SSH 進 NAS,再輸入 Docker 命令:

ssh your_name@NAS_IP
cd /volume1/docker/codex
sudo docker compose run --rm codex

這種 docker compose run --rm 是一次性 Container:終端離開後 Container 就被移除,也不是適合長期由 Synology Container Manager 管理的服務。手機仍得先準備 SSH App,使用體驗和直接操作 NAS 命令列沒有太大差別。

要讓它出現在 Container Manager 的「專案」中,必須把 Codex 改成 Compose 裡的常駐服務,例如 codex-web,設定 restart: unless-stopped、固定的 7681 連接埠與啟動命令,然後使用下列其中一種方式建立:

  1. 在 Container Manager 的「專案」新增專案,選擇存放 compose.yaml 的資料夾。
  2. 或先在該資料夾執行 sudo docker compose up -d,再確認 Container 與 Compose 專案名稱固定。

改完之後,即使 Codex Web Terminal 暫時連不上,也能從 DSM 的 Container Manager 檢查狀態、查看 Log、停止或重新啟動服務。不過 Container Manager 是管理介面,Codex CLI 本身不能直接按 DSM 裡的「重新啟動」按鈕;要讓 Codex 自己完成部署,仍需要後面介紹的 project-control 與受限制的 helper。

角色分工:Container Manager 用來讓人從 DSM 管理整個專案;project-control 則讓 Codex 在白名單範圍內呼叫相同的 Compose 操作。兩者管理的是同一組常駐 Container,並不互相衝突。

↑ 回到目錄

六、Synology 前置準備

這次環境是 Synology DSM 7、Container Manager、Docker 24、x86_64。先用 SSH 登入 NAS,確認處理器架構與 Docker 服務:

whoami
uname -m
sudo docker version
sudo synopkg list | grep -i container

Synology 上一般使用者直接執行 docker,可能遇到 Docker socket 的權限錯誤。管理者帳號可以先使用 sudo docker ...;不要為了方便把 socket 改成所有人都能讀寫。

建立 Codex 專案、登入資料與工作目錄:

sudo mkdir -p /volume1/docker/codex/home
sudo mkdir -p /volume1/docker/codex/workspace
sudo chown -R skypray:users /volume1/docker/codex
cd /volume1/docker/codex

home 會掛載到 Container 裡的 /home/codexuser/.codex,保存 Codex 登入與設定;重新建立 Container 後,不必每次重新登入。

↑ 回到目錄

七、建立 Codex Web Terminal 映像

Debian bookworm-slim 的套件庫不一定提供 ttyd,所以不能把它直接放進 apt-get install。這裡改用 ttyd 官方發行的 x86_64 執行檔:

FROM node:22-bookworm-slim

ARG TTYD_VERSION=1.7.7
ARG CODEX_UID=1026
ARG CODEX_GID=100

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
       bash ca-certificates curl git tmux \
    && rm -rf /var/lib/apt/lists/*

RUN curl -fsSL \
    "https://github.com/tsl0922/ttyd/releases/download/${TTYD_VERSION}/ttyd.x86_64" \
    -o /usr/local/bin/ttyd \
    && chmod 0755 /usr/local/bin/ttyd

RUN npm install -g @openai/codex

RUN groupadd -g "${CODEX_GID}" codexgroup 2>/dev/null || true \
    && useradd -m -u "${CODEX_UID}" -g "${CODEX_GID}" -s /bin/bash codexuser

ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8

COPY start-codex-web.sh /usr/local/bin/start-codex-web
COPY project-control /usr/local/bin/project-control
RUN chmod 0755 /usr/local/bin/start-codex-web /usr/local/bin/project-control

USER codexuser
WORKDIR /workspace
EXPOSE 7681
CMD ["/usr/local/bin/start-codex-web"]

正式使用時,建議把 ttyd 版本固定,並依官方 release 提供的校驗方式驗證下載檔,避免每次建置取得不同內容。

↑ 回到目錄

八、Compose 與網站目錄掛載

Compose 的重點是持久化 Codex 設定、開放 Web Terminal 的 7681 連接埠,以及只掛載真正需要 Codex 處理的網站。以下省略 project-helper 的建置細節,保留 codex-web 的主要設定:

services:
  codex-web:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        CODEX_UID: 1026
        CODEX_GID: 100
    container_name: codex-web
    restart: unless-stopped
    env_file:
      - .env
    environment:
      LANG: C.UTF-8
      LC_ALL: C.UTF-8
      PROJECT_HELPER_URL: http://project-helper:8080
    ports:
      - "7681:7681"
    volumes:
      - /volume1/docker/codex/home:/home/codexuser/.codex
      # 以下均為示範名稱:photo 代表相簿,wordpress 代表網誌
      - /volume1/docker/photo:/workspace/photo
      - /volume1/docker/wordpress:/workspace/wordpress
      - /volume1/web/reference-site:/workspace/reference-site:ro
    depends_on:
      - project-helper

  project-helper:
    build:
      context: ./project-helper
    container_name: codex-project-helper
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      # 僅掛載 helper 執行白名單專案所需的 compose 目錄
      - /volume1/docker:/volume1/docker
    expose:
      - "8080"

Volume 一行的格式是 NAS 路徑:Container 路徑:存取模式。最後的 :ro 是 read-only(唯讀),不是目錄名稱的一部分。以上例來說,Codex 可以讀取 /workspace/reference-site 的內容,但不能在其中新增、修改或刪除檔案。若最後沒有寫 :ro,Docker 預設使用讀寫模式,效果相當於 :rw。

這套架構同時管理三個核心專案:codex 是操作與管理工具本身,photo 代表相簿網站,wordpress 代表網誌。只需要一個 Codex Web Terminal,就能在掛載範圍內修改相簿與網誌,並透過白名單指令重啟或重建各自的 Container;不需要每個網站安裝一套 Codex。
YAML 不可使用 Tab 縮排。Compose 檔只能用空白,建議每層兩格。遇到 found character that cannot start any token,可用 sed -n '1,80l' compose.yaml 檢查是否混入 \t。

.env 請使用強密碼與隨機 Token,且不要貼進公開文章或 Git:

TTYD_USER=your_web_terminal_user
TTYD_PASSWORD=CHANGE_THIS_TO_A_LONG_RANDOM_PASSWORD
PROJECT_HELPER_TOKEN=CHANGE_THIS_TO_A_RANDOM_TOKEN

完成後建置並啟動:

cd /volume1/docker/codex
sudo docker compose config
sudo docker compose build --no-cache
sudo docker compose up -d
sudo docker compose ps
sudo docker logs --tail 80 codex-web

↑ 回到目錄

九、如何決定 Codex 可以控制哪些目錄?

Codex 預設不是「控制整台 NAS」。它在 Container 裡只看得到映像本身,以及 Compose 明確掛載進去的目錄。目錄規劃因此就是最重要的權限邊界。

NAS 實際目錄 Container 內路徑 模式 用途與判斷原則
/volume1/docker/codex/home /home/codexuser/.codex 讀寫 保存登入、設定與 Codex 工作狀態,應固定保留。
/volume1/docker/photo /workspace/photo 讀寫 相簿網站範例;Codex 可以修改原始碼、執行測試與準備重建。
/volume1/docker/wordpress /workspace/wordpress 讀寫 網誌範例;需要 Codex 修改程式、Git 提交或執行建置。
文件或參考資料 /workspace/reference-site 唯讀(:ro) Codex 可以分析內容,但不能新增、修改或刪除檔案,適合不希望被改動的參考資料。

決定目錄時,我使用三個問題:

  1. Codex 是否真的需要看到這個目錄?不需要就不要掛載。
  2. 只需要分析,還是需要修改?只讀資料使用 :ro。
  3. 修改是否直接影響正式站?正式站應先建立 Git、快照或備份。

新增網站時,只要在 compose.yaml 的 volumes 增加一行,再重新建立 codex-web:

# 範例:新增一個唯讀參考目錄
# 最後的 :ro 代表 read-only,只能讀取,不能修改或刪除
- /volume1/web/reference-site:/workspace/reference-site:ro

sudo docker compose up -d --force-recreate codex-web

移除掛載後,Codex 就無法再透過該路徑存取 NAS 目錄。不要掛載整個 /volume1、使用者家目錄或不相干的共享資料夾。

↑ 回到目錄

十、手機操作、中文字體與字級

ttyd 把終端變成瀏覽器頁面,tmux 則保留長時間工作階段。啟動腳本可以把驗證、中文字體與字級一次設定好:

#!/usr/bin/env bash
set -euo pipefail

: "${TTYD_USER:?TTYD_USER is required}"
: "${TTYD_PASSWORD:?TTYD_PASSWORD is required}"

exec ttyd \
  -W \
  -p 7681 \
  -c "${TTYD_USER}:${TTYD_PASSWORD}" \
  -t 'fontFamily=Consolas,Microsoft JhengHei,PingFang TC,Noto Sans Mono CJK TC,monospace' \
  -t 'fontSize=16' \
  tmux new-session -A -s codex \
  'codex --sandbox danger-full-access'

中文輸入後變成底線、空白或看不見,通常不是 Codex 壞掉,而是終端字型與 Locale 不完整。這個版本同時處理兩層:

  • Container 設定 LANG=C.UTF-8 與 LC_ALL=C.UTF-8。
  • ttyd 優先使用手機或電腦常見的繁體中文字型,最後才退回 monospace。
  • 手機以 fontSize=16 起步;想多顯示幾欄可改成 14,閱讀優先則可改成 17 或 18。

-W 允許 WebSocket 寫入,tmux new-session -A 會連回既有的 codex 工作階段。手機切換 App 或網路短暫中斷後,重新整理頁面通常就能接回;必要時可在 Codex 使用 codex resume --last 延續最近對話。


Synology NAS 透過 ttyd 開啟 Codex CLI 網頁終端介面
Synology NAS 上的 Codex CLI 網頁終端介面:透過 ttyd 即可在手機或電腦瀏覽器操作。
瀏覽器網址:區域網路內可使用 http://NAS_IP:7681/。不要把 7681 直接做路由器 Port Forwarding;外出連線建議走 VPN,或使用具 HTTPS 與存取控制的反向代理。

↑ 回到目錄

十一、用專屬 project-control 控制各網站

只修改程式碼還不夠。Node.js、Docker 或需要編譯的網站,改完後常常還要重啟或重建。為了讓指令一致,我把操作包成:

project-control restart wordpress
project-control up wordpress
project-control rebuild wordpress

Codex Container 裡的 project-control 可以是一個很薄的 HTTP 包裝程式:

#!/usr/bin/env bash
set -euo pipefail

action="${1:-}"
project="${2:-}"

case "$action" in
  restart|up|rebuild) ;;
  *) echo "Usage: project-control {restart|up|rebuild} PROJECT" >&2; exit 2 ;;
esac

curl -fsS -X POST \
  "${PROJECT_HELPER_URL}/projects/${project}/${action}" \
  -H "Authorization: Bearer ${PROJECT_HELPER_TOKEN}"

project-helper 收到請求後,不直接使用使用者傳入的任意路徑,而是從固定白名單取得專案目錄。例如:

專案名稱 Compose 目錄 可執行的工作
photo /volume1/docker/photo 重啟既有容器、補啟動服務或依 Dockerfile 重建。
wordpress /volume1/docker/wordpress 修改網站程式後 restart、up 或 rebuild。
codex /volume1/docker/codex 維護這套工具本身;重建時要特別留意目前工作階段會中斷。

白名單同時限制「專案名稱、實際目錄、允許動作」。如果 Codex 傳入 ../../、陌生專案或任意 Docker 指令,helper 應直接拒絕。也因此,新增一個可控制網站時需要做兩件事:把網站目錄掛載到 codex-web,並在 project-helper 白名單加入對應的 Compose 專案。

實例:為什麼 photo 一開始無法用 project restart?

設定過程中,wordpress 可以透過 project-control 操作,但 photo 一開始無法以 Project 方式重新啟動。後來確認真正的差異在 photo 的 compose.yaml:裡面的建置目錄或 Bind mount 來源使用了 NAS 的完整絕對路徑。

這份 Compose 原本只在 NAS 的 SSH 環境執行,所以寫死完整路徑仍可使用;改成由 Container Manager 與 project-helper 呼叫後,Compose 可能是在不同的執行環境中解析。寫死的 NAS 路徑不一定存在於 helper 的檔案系統,因而無法穩定載入同一份 Project 設定。

原本概念類似:

services:
  photo:
    build:
      context: /volume1/docker/photo
    volumes:
      - /volume1/docker/photo/app:/app

後來改成以 compose.yaml 所在資料夾為基準的相對路徑:

services:
  photo:
    build:
      context: .
    volumes:
      - ./app:/app

其中 . 代表 compose.yaml 所在的專案目錄,./app 則代表該目錄下的 app 資料夾。只要 Container Manager 與 helper 都從這個 Project 目錄執行 Compose,同一份設定就不再綁死某個 NAS 絕對路徑。

  1. 將 compose.yaml、Dockerfile 與程式資料夾放在同一個 Project 根目錄。
  2. 把 build.context 從完整路徑改成 .。
  3. 把同一專案內的 Bind mount 改成 ./app:/app 這類相對路徑。
  4. 確認 helper 以這個資料夾作為 Compose 的 working directory,再重新執行 up -d。
cd /volume1/docker/photo
sudo docker compose config
sudo docker compose up -d

# 之後即可從 Codex 測試
project-control restart photo
不要混淆兩份 Compose:前面 codex/compose.yaml 使用 /volume1/docker/photo:/workspace/photo,目的是把 NAS 上另一個專案掛載進 Codex Container,因此可以明確寫出 NAS 絕對路徑;這裡修正的是 photo 自己的 compose.yaml,其 build.context 與專案內部資料夾改用相對路徑,讓 Project 能在不同管理入口下重複使用。
相對路徑不是任何情況都自動正確。它會以 Compose Project 目錄為基準,因此 Container Manager 與 helper 必須使用相同的 Project 目錄。也不是所有絕對路徑都不能使用;這次問題是同一份 Compose 需要跨 SSH、Container Manager 與 helper 環境執行,改用相對路徑後可攜性較好。

↑ 回到目錄

十二、restart、up、rebuild 到底差在哪裡?

命令 對應 Compose 動作 適合情境與限制
restart docker compose restart 只重啟現有容器。適合讀取外部掛載程式碼或設定後即可生效的服務;不會重建映像,也不會套用新的 Dockerfile。
up docker compose up -d 確保服務在背景啟動,並套用部分 Compose 變更。容器停止或尚未建立時很好用,但不保證重新建置映像。
rebuild docker compose up -d --build Dockerfile、套件、編譯產物或映像內容改變時使用。耗時較久,也可能造成短暫服務中斷。

日常可以先讓 Codex 完成修改與測試,再清楚指定:「請檢查差異,確認沒問題後執行 project-control rebuild wordpress,最後查看容器狀態與最近 80 行 log。」這比只說「幫我部署」更容易得到可驗證的結果。

↑ 回到目錄

十三、實際踩過的問題與解法

症狀 原因與處理方式
Docker socket permission denied Synology 使用者無權直接操作 Docker。先使用管理者帳號搭配 sudo docker;不要把 socket 改成 666。
Compose 顯示 YAML line 4 錯誤 檔案混入 Tab 或縮排不一致。以 sed -n '1,80l' compose.yaml 找出 \t,全部改成空白後執行 docker compose config。
Package ttyd has no installation candidate bookworm-slim 套件庫沒有 ttyd。改從 ttyd 官方 release 下載對應的 ttyd.x86_64。
中文輸入後消失或變成底線 同時設定 UTF-8 Locale 與含繁中文字型的 ttyd fontFamily,再重建 codex-web。
bwrap: Creating new namespace failed Synology 的核心或 Docker 限制 user namespace。既然 Codex 已在獨立 Container 中,可把 Docker 當外層隔離,再以 --sandbox danger-full-access 啟動;前提是只掛載可信且必要的目錄。
Container 顯示 running,但 7681 連不上 先執行 docker port codex-web,再於容器內測試 curl http://127.0.0.1:7681/。若內部也失敗,代表 ttyd 沒啟動,應檢查 CMD、腳本權限與 log。
手機顯示 Press Enter to Reconnect 網路切換會中斷 WebSocket。按 Enter 或重新整理;tmux 仍會保留工作階段。若對話已結束,可用 codex resume --last。
某個網站無法用 Project restart 檢查 compose.yaml 是否把 build.context 或 Bind mount 寫成 NAS 完整路徑。若同一份 Compose 會由 Container Manager 與 helper 執行,可改用 .、./app 等相對於 Project 目錄的路徑,並確認兩者使用相同 working directory。

↑ 回到目錄

十四、安全邊界與我最後採用的日常流程

這套架構的便利性來自 Codex 能真正修改檔案與執行命令,所以安全設計不能只靠 Web Terminal 的帳號密碼。我的原則是:

  • 7681 只在區域網路、VPN 或受保護的 HTTPS 反向代理使用,不直接暴露到網際網路。
  • Codex Container 不直接持有 Docker socket;Docker 操作經過 project-helper 的 Token、專案與動作白名單。
  • 只掛載需要處理的網站;參考資料使用 :ro;不掛載整個 /volume1。
  • 正式網站使用 Git、Synology Snapshot 或其他備份,重大修改前先建立可還原點。
  • 先讓 Codex列出預計修改內容與差異,再執行 rebuild;完成後檢查 docker compose ps、log 與網站 HTTP 狀態。
  • Codex 本身專案若要重建,先保存工作並預期 Web Terminal 會短暫斷線。

實際工作範例

cd /workspace/wordpress
git status

# 在 Codex 對話中描述修改需求,完成後檢查:
git diff

# 需要套用新映像時:
project-control rebuild wordpress

# 驗證服務與網站狀態,再視需要提交:
git status
git add -A
git commit -m "Update website feature"

這樣的組合,已經很接近在手機上使用完整 Codex 工作站:對話狀態由 Codex 與 tmux 延續,網站權限由 Compose 掛載決定,部署權限由 helper 白名單限制。手機只負責顯示與輸入,真正的檔案、Git、建置和容器操作都留在 NAS。

最後結論:Synology + Codex CLI 最實用的重點,不只是「把終端搬到網頁」,而是把可讀寫目錄、持久化對話、手機顯示、Container Manager 專案、網站部署與安全邊界一起設計。完成後,一個 project-control rebuild wordpress 就能把修改、重建與啟動串成清楚且可重複的流程。

參考資料

↑ 回到文章頂端

這篇文章已有 48 次瀏覽

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *