人の成長をデザインする会社

Codex専用Ubuntu環境の構築

Codex専用Ubuntu環境をVM・OSユーザー・ワークスペースの三層で分離する図

専用環境はrootを渡すためではなく、境界を小さくするために作る

Codex専用Ubuntu環境の目的は、AIへ強い権限を与えることではありません。日常の個人端末や本番serverから作業repositoryを分離し、Codexが読書きできるworkspace、OS user、network、資格情報、backupを明示することです。Codex sandbox、Ubuntuのfile permission、VMの隔離は異なる層なので、一つを有効にして他を省略しません。

本記事は、架空project inventory-app用の新規VMを構築するrunbookです。実在host、password、SSH鍵、API keyは含みません。OS・network・accountの作成は組織の管理者が承認済み環境で実施し、Codexの日常実行userにsudoを与えない構成にします。

Ubuntu Server 26.04 LTSをsupport期間から選ぶ

2026年8月25日時点で、CanonicalのUbuntu release cycleを基準に、新規専用VMのbaselineにはUbuntu Server 26.04 LTSを選びます。26.04 LTSは2026年4月のLTSで、標準security maintenanceはmain repositoryを中心に2031年5月まで、Ubuntu ProのExpanded Security Maintenanceを有効にする契約・範囲ではmainとuniverseについて2036年5月までと示されています。

標準supportと延長supportを同じ「無料で10年」と表現しません。対象package、契約、Ubuntu Proの有効状態を個別環境で確認します。また、support期間内でも、組織がsecurity update、再起動、application互換性を管理しなければ安全性は維持できません。

26.04を選ぶのは、執筆時点の現行LTSとして新規構築の保守期間を長く確保できるためです。「最新だから必ず安定・高速」とは評価しません。利用するCodex CLI、Git、build toolと組織の監視・backup agentが26.04で動くことを隔離testし、未対応toolがある場合は24.04 LTSを含む別baselineを例外票で比較します。

項目選定値確認元・確認日運用上の判断
OSUbuntu Server 26.04 LTSCanonical「Ubuntu release cycle」、2026-08-25新規専用VMのbaseline。point releaseとimage checksumも導入時確認
標準security maintenance2031年5月まで同資料のLTS lifecycle年次にtool互換性と次期LTS移行時期を再評価
延長security maintenanceUbuntu ProのESM対象で2036年5月まで同資料のUbuntu Pro / expanded security maintenance契約・有効化・対象packageを確認できた環境だけ延長済みと記録
architectureamd64(架空VM)cloud image・hypervisor・tool互換性実環境がarm64なら同じimageやbinaryを流用しない

/etc/os-releaseuname -m、support statusを構築記録へ残し、記事のversionを盲信しません。standard support終了が近づいてから移行を始めるのではなく、repositoryのtest、data migration、rollbackに必要な期間を逆算します。

管理者と日常実行userを分ける

管理者<admin-user>はVMの初期構築・更新・account管理を担当し、日常user<codex-user>は一つのworkspaceだけを扱います。placeholderは承認票の値へ置き換えます。codexubuntuのような共有しやすい名前をそのまま使わず、ownerと用途を台帳で対応させます。

管理者が実行する例です。

ADMIN_USER="<admin-user>"
CODEX_USER="<codex-user>"
PROJECT_GROUP="<project-group>"
WORKSPACE="/srv/codex-workspaces/<project-slug>"
getent passwd "${ADMIN_USER}"
sudo addgroup --system "${PROJECT_GROUP}"
sudo adduser --disabled-password --gecos '' "${CODEX_USER}"
sudo usermod --append --groups "${PROJECT_GROUP}" "${CODEX_USER}"
sudo install -d -o "${CODEX_USER}" -g "${PROJECT_GROUP}" -m 0750 "${WORKSPACE}"
getent passwd "${CODEX_USER}"
id "${CODEX_USER}"
namei -l "${WORKSPACE}"
stat -c '%U:%G %a %n' "${WORKSPACE}"
sudo -l -U "${CODEX_USER}"

<admin-user>は個人に対応する既存管理account、<codex-user>は日常実行専用user、<project-group>はこのprojectだけのgroup、<project-slug>inventory-appのような秘密を含まない識別子です。WORKSPACEはhome全体でなく専用pathにします。

期待結果は、日常userが存在し、project groupにだけ所属し、workspaceが<codex-user>:<project-group>、mode 0750で、sudo -l -Uが日常userに許可されたsudo commandなしを示すことです。環境のpolicyでsudo照会結果の表現が違う場合は管理者が解釈します。

既存user、既存group、既存directoryが見つかった場合は上書きしません。ownerが別人、modeが0777、日常userにsudo・docker・lxd等の強いgroupがある、親directoryが他projectへ辿れる場合は停止します。chmod -R 777や広いchown -Rでerrorを消しません。

日常userに切り替えて境界を確認します。

sudo -u "${CODEX_USER}" -H sh -lc '
  id
  umask
  test -w "/srv/codex-workspaces/<project-slug>"
  test ! -w /etc
  test ! -w /usr/local/bin
  touch "/srv/codex-workspaces/<project-slug>/.write-test"
  stat -c "%U:%G %a %n" "/srv/codex-workspaces/<project-slug>/.write-test"
  rm "/srv/codex-workspaces/<project-slug>/.write-test"
'

期待はworkspace内test fileの作成・削除成功、ownerが日常user、/etc/usr/local/binが書込み不可です。test ! -wが失敗するなら日常userの権限が強すぎるため、Codex installや認証へ進みません。

最小構成を構築順に積み上げる

1. OS更新と時刻を固定する

管理者はCanonicalのpackage管理手順と組織のmaintenance windowに従い、package index、upgrade、再起動要否を確認します。

sudo apt update
apt list --upgradable
sudo apt upgrade
test -f /var/run/reboot-required && cat /var/run/reboot-required || true
timedatectl status

本番同居VMではない専用環境でも、無計画なrebootは進行中作業を失います。更新前にsnapshot・backup、作業中session、rollbackを確認します。repositoryがdirty、長時間jobが動作、backup不合格なら更新を延期します。

自動security updateを使う場合はCanonicalのautomatic updates資料を基に、対象package、実行時刻、reboot方針、log、通知を設定します。自動化したことを理由に月次確認を省きません。

2. Gitと必要toolだけを導入する

sudo apt install git ca-certificates curl jq
git --version
curl --version
jq --version
dpkg-query -W git ca-certificates curl jq

toolは架空projectの最低例です。compiler、container runtime、cloud CLI、database clientを「便利だから」一括導入しません。各toolへ用途、package source、version、network先、更新ownerを持たせます。curlはTLSを無効にしたdownloadへ使いません。

Node.js/npmがCodex CLI導入に必要な方式を選ぶ場合、OpenAI Docsの現行要件と組織のNode配布方法を確認します。Ubuntu archive、承認済みrepository、管理されたversion managerのいずれを正本にするか決め、検索結果のsetup scriptをrootでpipe実行しません。

3. Codex CLIを公式の配布元から入れる

2026年8月25日時点のOpenAI公式Codex CLIページで確認したstandalone installerを、日常userとして実行する例です。組織がscript実行を制限している場合は、管理者が取得物と配布方法を審査します。

curl -fsSL https://chatgpt.com/codex/install.sh | sh
command -v codex
type -a codex
codex --version

期待は導入したbinaryが一つ、version表示成功です。permission errorをsudo実行で回避せず、日常userの導入先、owner、PATHを修正します。複数binary、root ownerのuser config、非公式な取得元なら認証しません。

更新時も公式ページでcommandを再確認し、同じ配布元を使います。更新前後versionとtest結果を記録し、全VMへ同時配布しません。test VMで/status/permissions、read-only repository調査、小変更のdiff・testを確認してから展開します。

4. workspaceへrepositoryと指示を置く

日常userとして承認済みrepositoryをworkspace直下へ取得します。実際のremote URL、credential helper、SSH host keyは組織手順で検証し、記事に秘密値を置きません。

cd "/srv/codex-workspaces/<project-slug>"
pwd
git status --short --branch
test -f AGENTS.md
git remote -v

期待は絶対path一致、承認済みbranch、既存差分0、AGENTS.mdあり、remoteが承認済み組織です。remote URLにtokenが埋め込まれている、別組織、既存差分、owner不一致ならCodexを起動しません。

AGENTS.mdにはtest command、対象directory、禁止path、network・package追加・commit・deployの承認、秘密の扱い、完了条件を書きます。自然言語指示はOS permissionやVM boundaryの代わりではなく、追加のproject契約です。

5. 認証と本番資格を分離する

Codex認証は担当者・組織が承認した方式で行い、共有loginや平文token fileを使いません。本番deploy key、cloud credential、顧客dataは日常userのhome、workspace、environmentへ置きません。test用資格にも本番書込み権限を与えません。

認証後は/status/permissionsを確認し、最初の依頼はAGENTS.mdとREADMEの変更なし要約にします。想定より強いsandbox、network有効、別directoryならpromptを送らず終了します。

logは監査に必要な事実だけを残す

OS log、package log、Codex session記録、repository diffは目的と保持を分けます。journalctl/var/log/apt/で更新・service errorを確認できますが、日常userへsystem log全体の読取りを無条件に与えません。必要なserviceと期間を管理者が抽出します。

記録するのは作業ID、OS・Codex・Git version、user、workspace、開始・終了、実効permissions、変更file、test、approval、終了codeです。prompt・command outputに秘密や個人dataが含まれた場合、それを監査のために複製せずincident手順へ送ります。

log保持は「できるだけ長く」ではなく、監査・incident・契約要件から期間を決めます。owner、access、削除、時刻同期を設計します。Codexの説明文だけで成功判定せず、OSとGitの観測を併用します。

backupはVM snapshot、workspace、構成記録を分ける

VM snapshotは障害前のdisk状態へ戻す助けになりますが、同じstorage・accountの障害やapplication整合性を必ず解決するものではありません。workspace repositoryはremoteへ反映していない変更、未追跡test dataを別途扱います。秘密をbackupへ無差別に含めません。

対象頻度例保持例保存先復元test
VM image/snapshotOS・tool大変更前、日次日次7、週次4VM hostとは別の承認済みbackup account四半期に隔離VMとしてboot、user・networkを確認
workspace未反映成果物作業終了時、重要変更前change IDごと30日暗号化off-site。repository remoteとは別file checksum、owner、Git statusを隔離pathで確認
構成台帳user・package・network変更時12 revisionaccess制御した文書repository新規VMでuser・mode・tool versionを再現
秘密組織の秘密管理policypolicy準拠専用secret manager回復担当が値を露出せず利用可能性をtest

snapshot取得成功とrestore成功を分けます。隔離復元でOS起動、日常user login、workspace owner、Codex binary、network default deny、秘密分離を検査します。復元VMが本番networkへ同じidentityで接続しないようNIC・資格を隔離します。

filesystem境界を読取りと書込みでtestする

構築後、日常userで次を実行します。これは新規のtest VMで管理者が承認したpathだけを対象にします。

WORKSPACE="/srv/codex-workspaces/<project-slug>"
OUTSIDE="/srv/codex-boundary-test/admin-only"
id
stat -c '%U:%G %a %n' "${WORKSPACE}"
touch "${WORKSPACE}/.boundary-write"
test -w "${WORKSPACE}/.boundary-write"
rm "${WORKSPACE}/.boundary-write"
test ! -r "${OUTSIDE}"
test ! -w "${OUTSIDE}"
test ! -w /etc
test ! -w /usr/local/bin

<project-slug>は承認済みworkspace、OUTSIDEは管理者がtest用に作った秘密を含まないdirectoryです。他user homeや実秘密をtest対象にしません。期待はworkspaceの書込み成功、外側の読書き不可、system path書込み不可です。

test ! -rまたはtest ! -wが失敗したら、Codex sandboxで隠す前にOS group、ACL、parent mode、mountを確認します。日常userがdocker group、lxd group、sudoを持つ場合は、filesystem permission以外から強い権限を得られるため不合格です。

Codex sessionでもread-only調査、workspace編集、workspace外書込み提案を模擬し、/status/permissionsと実際の結果を記録します。OS境界testに合格してもCodex設定が強いことはあり、逆もあります。

network境界は名前解決、接続、外部副作用を分ける

新規VMはdefault denyを組織のnetwork制御で実装し、OS package更新、Codex認証・service、承認済みrepository、時刻同期など必要先を管理者がallowlist化します。具体的なfirewall変更は組織のnetwork設計に従い、本稿の一般commandで本番へ適用しません。

日常userの観測例です。

getent hosts developers.openai.com
curl --fail --silent --show-error --head \
  --max-time 10 https://developers.openai.com/ > /dev/null
getent hosts "<blocked-test-host>" || true
curl --fail --silent --show-error --head \
  --max-time 5 "https://<blocked-test-host>/" > /dev/null && exit 1 || true

<blocked-test-host>は組織が所有し、拒否test用に承認した安全なhostです。無関係な第三者や本番systemをtestしません。期待は許可された公式documentへのTLS接続成功、拒否test先への接続失敗です。ただしCodexが実際に必要とするendpointはOpenAI Docs・管理設定で確認し、この記事の一URLだけを完全なallowlistとしません。

DNS解決できてもTCP/TLSが拒否される場合、network異常とは限らず設計どおりの可能性があります。proxy環境ではproxy変数の存在だけを記録し、credential値を表示しません。TLS検証を無効化、個人VPNへ切替え、firewallを全面開放して解決しません。

networkが許可されても、deploy、メール送信、issue更新、課金API等の外部副作用は別の業務承認が必要です。sandboxのnetwork accessは通信到達性の制御で、外部状態変更の承認を代替しません。

三層の責任を混ぜない

境界層主に止めるもの本例の設定・所有者単独では止められないもの
Codex sandbox・approvalmodel生成commandのworkspace外書込み、network、承認対象workspace-writeon-request、network offを基準。Codex利用責任者日常userが手動で行う操作、OS user自体の強い権限、VM外の資格
Ubuntu OS permissionuser・group・mode・ACLによるfile/process access専用user、workspace 0750、sudoなし。OS管理者kernel・hypervisor侵害、同VM上の強いservice、許可network先の副作用
VM・cloud/network境界host、他VM、本番network、snapshot、egress専用VM、segment、allowlist、別backup account。基盤管理者VM内で許可されたrepositoryの誤変更、promptの品質、review不足

Codex sandboxがworkspace-writeでも、workspaceに本番秘密があれば読取り可能性を考える必要があります。OS userを分けても、VMが本番networkへ無制限に到達できれば外部影響が残ります。VMを分けてもroot運用ならVM内の全dataを失い得ます。

三層すべてで最小化し、Git review、test、backup、業務承認を重ねます。どれか一層が絶対安全という説明をしません。

構築途中で失敗してもVMを削除して証拠を失わない

架空case BUILD-20260825-03では、step 3のCodex CLI installでpermission errorが起き、担当者がsudoでinstallerを再実行しようとしました。runbookはそこで停止します。VMを削除して最初からやり直すと、誤ったownerやPATHなどの原因を失うため、状態を記録します。

cat /etc/os-release
id
printf '%s
' "$PATH"
command -v codex || true
type -a codex || true
find "$HOME" -maxdepth 3 -user root -printf '%u:%g %m %p
' 2>/dev/null
stat -c '%U:%G %a %n' "/srv/codex-workspaces/<project-slug>"

期待は失敗時のOS、user、PATH、binary候補、root owner file、workspace状態を秘密なしで記録できることです。findは日常userのhomeだけに限定し、他userやsystem全体を探索しません。

失敗票には、最後に成功したstep 2、実行command、終了code、errorの必要部分、作成済みuser/group/directory、package差分、snapshot ID、次のownerを記載します。認証tokenやenvironment全文は保存しません。

再開は、管理者が導入先とowner、PATHを組織方式へ修正し、日常userでwrite test、公式installer、command -v codex、version確認を新しいrun IDで行います。作成済みuser・workspaceを重複作成せず、getentstatで期待状態を確認して該当stepから続けます。

もし誤ってroot ownerのCodex configやbinaryが日常user homeへ作られた場合、対象file一覧と作成時刻を確定してから修正します。home全体を再帰chownせず、組織の変更承認で正確な対象だけを直します。原因と影響が分からなければVM snapshotを保持し、security・OS管理者へescalateします。

削除が必要になるのは、秘密の広範な露出、base imageの信頼性不明、構成逸脱を列挙できない等、復旧より再構築が安全と責任者が判断した場合です。その場合も、必要なincident証拠、snapshot、構成記録を保持し、破棄は承認済み手順で行います。

完了判定は新しいuserで再現する

構築完了時には、OS support、package update、日常userとsudoなし、workspace owner/mode、Codex version、repository・AGENTS.md、認証分離、filesystem境界、network allow/deny、log、backup復元を確認します。一項目でも「後で」ならreadyにしません。

別の確認者が日常userとしてloginし、id、workspace書込み、system path拒否、Codex read-only依頼、Git差分0、network境界を再現します。構築者のshellだけで動くPATHやenvironmentなら不合格です。

月次はsecurity update・disk・log・資格・backup、四半期は隔離restoreと境界test、Codex更新時はread-onlyと小変更test、年次にtool互換性と次期LTS移行時期を判断します。専用環境は作って終わりではなく、境界が狭いままかを繰り返し確かめる運用です。

関連記事

ホーム » BLOG » Codex専用Ubuntu環境の構築