LLM,つかってますか.
Codex や Claude Code など, cli で動くよ,色んなことを自律的にやるよ,というツールを試してみたいところだが,ローカルのファイルに任意にアクセスされるの,怖すぎる.
うまく読み書きできる対象を絞ることについては,
などあるが,この信頼性を評価したり,更新に追従したりするのに時間を使いたくはない.前者は明示的に β で,みんな一体どこまでは許容するつもりで codex とか走らせてるんだろう……と思ったりする.
というわけで,
- agent はある程度好きに動いてほしいが,なにかした時(インストールした,誤って削除した, etc. )の自分の環境へのダメージを最小化したい
- agent に見えてもらっては困るファイルというのもあるので,「明示的に見ていいよ」と渡したファイル以外には一切アクセスができない状況にしたい
- 設定がある程度簡便で,今どのファイルにどうアクセスできてるのかがわかりやすい状態であること
…を目標に,色々わからんなりに検討して作ってみたのでメモ.
注意書きとしては,
- linux は長く使っているが docker も podman も使ったことがなく, SELinux もある環境になって1ヶ月の非情報系の人間が,LLM に聞いたりしながらやったことです
- 後述するが,やってみるとこれがベストではなさそう…? という部分があります
- まだ作っただけで使い込んでないので,評価が未です
なので,全体に評価はご自身で行っていただき,あくまで参考として使ってください.
環境は Fedora 44,SELinux も enforcing.
今回の構成
色々考えて,以下の通りにした.
- agents というユーザを作る(これはあとから考えるとむしろ burden かも)
- agents の下にあるフォルダは,自分 (kagcc とします)から見られる設定にしておく
- podman でコンテナを作って, agents ユーザ から起動する
- claude とか codex はこのコンテナの中で起動する.
- データの共有・保持のためには,
/home/agents/shared/みたいなディレクトリを作って,これを コンテナに bind mount しておいて,そこでやり取りする
これで,「見せてないディレクトリはそもそも見えない」「見せたディレクトリへの変更は外から見える」「 dnf install みたいなシステムへの変更も外部に影響を及ぼさず可能」が両立する
他の選択肢
- bubblewrap がどちらかというと LLM agent の構成ではよく使われているようで,これはざっくり
/usr/bin/とかそのへん + 見せたいやつ を渡す…という感じ. …なんですけど,なんか~/.local/bin/とかに置いてあるツールの共有とかミスりそうとか,LLM がほしいツールを自分のシステムにインストールするのもな……とか,agent がファイルを消し飛ばした時に,自分の環境を復旧するのに手間を掛けたくないな,と思って,完全に別途の環境として podman にすることにした. - codex とかも bubblewrap をベースにした隔離の仕組みを作り始めているようだが,β だったりで今後の更新への追従が面倒そうでやめた
ユーザの設計
agents というユーザを作って,例えば podman はこれから動かすことにした.イメージは
| ユーザ名と役割 | |
|---|---|
| 自分 | kagcc からもコンテナに共有するファイルの確認・編集は できるようにする |
| agent 用のユーザ | agents.コンテナの管理とかそれを動かしたり |
| コンテナ内 | root で Codex とか Claude Code が動く.コンテナ外部からみると agents が動かしている (rootless podman) |
別ユーザを作ったのは,単に「エージェントが一から作ったファイルの owner は自分じゃないほうが気分的に良い」という程度で,別に要らなかったかも.
permission の壁がもう一つ安全性を担保してくれる可能性はあるのだが(例えば,git で管理されてるディレクトリで agent が owner のところで,自分が git を動かすと大丈夫かというチェックが入る),
あとから思うと設定の煩雑さと隣合わせではあり,例えば kagcc のまま rootless Podman を使えば,コンテナが作る共有ファイルの owner も kagcc となるし, 自分が owner のファイルも podman のコンテナにマウントさえすれば見てもらえることができるようになる.ユーザを分けていると,コンテナが作る共有ファイルは agents に所有されてるし, agents は owner が kagcc のファイルは読めない…といった煩雑さが発生するわけですね.
ディレクトリ構成と,何がどこから見えるか
具体的には,今回はこういう感じのディレクトリ構成にしてみた. /home/agents/host-only には,コンテナのセットアップに関するものをおく.名前が変だけど container-shared はコンテナ内から見えるという設定. online としてるのは,今回のコンテナにネットワークアクセスを許可してるので,そのことをディレクトリ切って明確にしたもの.
~agents/ |
内容 | コンテナ内からどう見えるか |
|---|---|---|
host-only/setup/ |
Containerfile とか,そこで COPY とかされるべきファイル群とか |
コンテナからは見えない,agents ユーザから使う |
container-shared/online/ |
ここをまるっとコンテナに bind mount | /workspace,読み取り専用 |
container-shared/online/repos/ |
既存リポジトリの clone | /workspace/repos,読み書き可能 |
container-shared/online/projects/ |
agents が新たに一から作る系 | /workspace/projects,読み書き可能 |
container-shared/online/reference/ |
参考資料で触ってほしくないもの (PDFとか) | /workspace/reference,読み取り専用 |
container-secrets/online/ |
認証情報とかは分けてみた | /agent-secrets/ |
container-secrets/online/codex/ |
auth.json(認証)とかを残す用 |
/agent-secrets/codex,読み書き可能 |
container-secrets/online/claude/ |
.credentials.jsonとかを残す用 |
/agent-secrets/claude,読み書き可能 |
container-secrets/online については,:コンテナ作り直した時に codex 再認証したくないし,認証情報はマウントしたコンテナ外部に置くことにしたという経緯.例えば codex ならその認証情報とかキャッシュとかそのへんが入る.
GitHub の personal access token は別途 podman secret で管理し,コンテナから読める /run/secrets/github-readonly に配置する…ことになったが,これがベストかは微妙.
手順
ユーザ作る!
まず, agents ユーザをつくる.これは上記のとおり自分 (kagcc)としてやるほうがシンプルかもしれないので読み飛ばせば良いかもしれない.
1. btrfs subvolume
Fedora のデフォルトでは, / と /home/ がそれぞれ sibling な btrfs subvolume になっている.気分で /home/agents もその兄弟にあたる subvolume にすることにした.
こだわりがなければ useradd に --btrfs-subvolume-home というオプションがあるので,普通に子の subcolume にしてこれ使っとけば良かったと思う.
気を取り直して,まず現状の確認
findmnt -t btrfs sudo btrfs subvolume list -p / findmnt --fstab -t btrfs
subvolid=5 でファイルシステムのトップレベルを一時的にマウントし,その直下 (= / とか /home の兄弟) に agents を作る.arch wiki に書いてある手順に近いはず.
sudo mkdir -p /mnt/btrfs-top # マウントする場所を作っとく.名前は何でもいい sudo mount -o subvolid=5,compress=zstd:1 UUID=$(findmnt -no UUID /) /mnt/btrfs-top # マウントする sudo btrfs subvolume create /mnt/btrfs-top/agents # subvolume を作る sudo umount /mnt/btrfs-top # 後片付け sudo rmdir /mnt/btrfs-top
agents は Btrfs 上では / や /home と同格,ディレクトリの場所としては /home/agents と言う感じ.
さて,これをいちいち手動でマウントするのは大変なので, /home/agents を作ったうえで fstab を設定する
sudo cp -a /etc/fstab /etc/fstab.bak printf 'UUID=%s /home/agents btrfs subvol=agents,compress=zstd:1,x-systemd.device-timeout=0 0 0\n' \ $(findmnt -no UUID /) | sudo tee -a /etc/fstab sudo mkdir -p /home/agents sudo findmnt --verify --verbose
…んだけどここのことはよく分かってない.systemctl とか 再起動とかしたらいけてるはずで, $ findmnt -no SOURCE,FSTYPE,OPTIONS /home/agents とかすると良いと思われる.
2. ユーザとグループの設定
agents というユーザを作りましょう.すでに /home/agents/ があるのでそんな感じだ.
sudo useradd --home-dir /home/agents --comment "LLM agents" --no-create-home agents sudo cp -a /etc/skel/. /home/agents/ sudo chown -R agents:agents /home/agents sudo restorecon -RFv /home/agents # SELinux
で,覗き見用に agents-work というグループを作っておく
sudo groupadd -r agents-work sudo usermod -aG agents-work kagcc sudo chown agents:agents-work /home/agents sudo chmod 0750 /home/agents
コンテナを作っていくぜ!
sudo -iu agents でも良さそうだが,こっちで agents として入るこどができる.
sudo machinectl shell agents@.host /bin/bash -l
3. ディレクトリと権限
ここは kagcc から
sudo install -d -o agents -g agents-work -m 2770 \ ~agents/container-shared \ ~agents/container-shared/online \ ~agents/container-shared/online/{repos,projects,reference} sudo install -d -o agents -g agents -m 0700 \ ~agents/container-secrets \ ~agents/container-secrets/online \ ~agents/container-secrets/online/{codex,claude}
※ install は今回初めて知ったが,こういうふうに cp (あるいは mkdir) と chmod をまとめてできる感じで便利らしいです.How is install different from cp? [unix.stackexchange.com]
共有フォルダの permission を 2770 にしていて,これは setgid をディレクトリにつけて,新規ファイルも agents-work のグループになるようにしているはず.
ここから先は agents として作業する.
4. Github の設定
- LLM に github の private repository にあるコードを渡したい
- 例えば 「"claude/feat-A" というブランチは好きにしてくれていいが main はだめ」みたいな設定は難しそう (protected branch を作るくらい).要するに agent を自分と区別するにはアカウント分けるしかないけど,あまりそういう手段は想定されてなさそうなのだ.
- というわけで,とりあえず fine-grained personal access token を使ってみることにした.
- Contents と Metadata に読み取り権限,ついでに issue も読めるようにして設定してみた.PAT を作ると一度だけ github 上で表示してくれるので,これを podman-secret に覚えさせてみる.
LLM が推奨してきたこれで入力してみる(不用意に履歴とかに残らないようにということだと思う).
( set +x IFS= read -r -s -p 'GitHub read-only PAT: ' agent_github_pat || exit printf '\n' [[ -n "$agent_github_pat" ]] || exit printf '%s' "$agent_github_pat" | podman secret create github-readonly - )
で,コンテナの中で使う gitconfig がこれを含むようにする (Containerfile のなかでこれを適切にコピーする).
[credential "https://github.com"] helper = "!f() { test \"$1\" = get || return 0; token=$(cat /run/secrets/github-readonly) || return 1; printf '%s\\n' 'username=x-access-token' \"password=$token\"; }; f"
追記 20260927: 一旦
- コンテナ内: Personal Access Token で概ね read-only
- コンテナ外の,
agentsユーザから見えるところに一個 ssh key は作っておく - gitconfig でどっちも name にそれっぽい設定をしておく
という形で運用してみている.
5. Containerfile をつくる
いよいよコンテナの中身を作ります.ここでは ~agents/host-only/setup/default/Containerfile に置いてみてるけど,別にどこでもいい.同じディレクトリに,使いたい bashrc とかさっきの gitconfig とか COPY する対象のものは置いておく.今回はシステムと揃えて Fedora をベースにします.再現性よりは「いい感じの最新版」でいいことにしているが,ここは適宜 :44 とかをつけると良いと思われる.
FROM quay.io/fedora/fedora RUN dnf install -y texlive-scheme-full \ google-noto-sans-cjk-fonts google-noto-serif-cjk-fonts google-noto-sans-jp-fonts \ mrsw-biz-udgothic-fonts-all mrsw-biz-udpgothic-fonts \ mrsw-biz-udmincho-fonts-all mrsw-biz-udpmincho-fonts \ pandoc-cli \ && dnf clean all RUN dnf install -y \ git ssh vim make cmake gcc clang gettext curl perl nkf \ gmp gmp-devel ncurses ncurses-compat-libs xz nodejs \ qpdf mupdf mupdf-libs openssl openssl-devel ninja-build \ htop opencv inkscape yt-dlp ripgrep fd-find git-delta \ && dnf clean all # これでいいのかよくわからないゾーン COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ COPY --chown=0:0 uv.toml /etc/uv/uv.toml RUN uv tool install ruff RUN uv tool install pyright ENV PATH="/root/.cargo/bin:/root/.local/bin:${PATH}" RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh \ && sh /tmp/rustup.sh -y --default-toolchain nightly --profile default \ --component rustfmt,clippy \ && rm /tmp/rustup.sh RUN cargo install --locked typst-cli RUN curl -fsSL https://claude.ai/install.sh -o /tmp/claude.sh \ && bash /tmp/claude.sh RUN npm install --global @openai/codex@latest \ && npm cache clean --force COPY --chown=0:0 gitconfig /root/.gitconfig # コンテナ内で人が作業することがあるので最低限で COPY --chown=0:0 basic_bashrc.sh /root/.bashrc COPY --chown=0:0 editorconfig /root/.editorconfig CMD ["/bin/bash"]
ビルドしておく
podman build -t localhost/agent-base:fedora44 ~/host-only/setup/default # 上の Containerfile の置いたディレクトリ
6. いざ起動
~/host-only/setup/default/create-agents-online.sh など便利な場所に置いておいて,こんな感じで起動する.
#!/usr/bin/env bash set -euo pipefail podman create -it \ --name agents-online \ --user=0:0 \ --security-opt=no-new-privileges \ --umask=0007 \ --memory=16g --memory-swap=16g --cpus=6 --pids-limit=1024 \ --secret github-readonly,type=mount,mode=0400 \ --volume "$HOME/container-shared/online:/workspace:ro,Z" \ --volume "$HOME/container-shared/online/repos:/workspace/repos:rw,Z" \ --volume "$HOME/container-shared/online/projects:/workspace/projects:rw,Z" \ --volume "$HOME/container-shared/online/reference:/workspace/reference:ro,Z" \ --volume "$HOME/container-secrets/online:/agent-secrets:rw,Z" \ --env CODEX_HOME=/agent-secrets/codex \ --env CLAUDE_CONFIG_DIR=/agent-secrets/claude \ --workdir /workspace \ localhost/agent-base:fedora44 /bin/bash
ro と rw でコンテナ内から書けるかどうかの設定をしていて,例えば見てくれたらいい reference は ro にしている.
bash "$HOME/host-only/setup/default/create-agents-online.sh"
で起動したら,あとは
$ podman start -ai agents-online でOK.
コンテナ内!
あとはコンテナ内で,たとえば codex とか claude でOK. Codex は今のところ device code での認証ができるように (openai の設定で)変更してそれを使う感じになるみたい.
認証状態は コンテナ外部に保存して,コンテナを作り直しても再利用できる設計にしている(まだ環境作りたてでそういう機会が多そうだったので).
Git clone も(PAT で許容した repository については)コンテナ内から普通にできるはず.
その後
Containerfile の変更に際してはまずイメージをビルド→コンテナ停止→作り直し,で OK.
podman build -t localhost/agent-base:fedora44 ~/host-only/setup/default/ podman stop agents-online podman rm agents-online bash ~/host-only/setup/default/create-agents-online.sh podman start -ai agents-online
まとめ
- podman など,コンテナ技術を agent の隔離に使うのは結構ありっぽい気がする
- コンテナを起動するユーザを分けてみたが,果たして有意義かは微妙(コンテナによる隔離一層でいい気もする,ただ agents というユーザでログインして色々作業をすると,LLM の生成した何らかのスクリプトが有害であった場合に一定のダメージコントロールができる.コンテナ内でそれもやればいい話だが).ユーザ分けずにやる方向にシフトするかもしれない.
- 実際に使ってみての評価などはまだなので,また使って感想と余力があれば別途投稿します.


