「あのファイル、NASのどこに置いたっけ……?」
写真もコードも書類も、とりあえず全部NASに突っ込んでいる僕は、このセリフを月に何十回つぶやいているか分かりません。File Stationの検索窓に打ち込んで、待って、違って、また待って……。
そんなある日、ふと思いました。
「NASの中にAI置けばよくない?」
思いついたが吉日。SSHでログインして、Container Managerを開いて、気づけば深夜。結果から言うと——できました。しかも24時間常駐、iPhoneからどこでも操作可能、日本語で話しかけられる状態です。
この記事では、Synology NASにClaude Codeを常駐させる手順を、Dockerもtmuxもよくわからないというかたにも分かるように、一つずつ解説していきます。もちろん、僕が盛大にハマったポイント込みで。
なぜ「NASの中」でAIを動かすのか
「Macで動かせばいいじゃん」と思ったかた、正しいです。でも、NASで動かす理由が4つあります。
1. NASは24時間つけっぱなし
これが最大の理由です。MacBookは閉じたら止まりますが、NASは止まりません。つまり、AIに「あのフォルダ全部リネームしといて」と頼んで蓋を閉じても、NASの中のAIは黙々と作業を続けてくれます。処理を投げっぱなしにできる、というのはサーバーの特権です。
2. Remote Controlでどこからでも繋がる
Claude CodeにはRemote Controlという機能があって、NAS上で動いているセッションに、iPhoneのClaudeアプリのCodeタブから直接接続できます。電車の中から、自宅NASの中身を日本語で検索できるわけです。これはもう、ちょっとした魔法です。
3. WebサイトをAIに直接編集してもらえる
これは地味に効きます。僕自身このブログをSynology NASでホスティングしていますが、NASでWebサイトを立てているかたって、けっこう多いんじゃないでしょうか? そこにAIを住まわせてしまえば、いちいちエディタを開いてページを直さなくても、「あのページのここ直しといて」と指示するだけで編集してもらえます。ファイルはNASの中にあるので、AIの手がそのまま届くわけです。
ちなみに僕のkaylog.ioはWordPressなので、記事本文はデータベースの中。ここはファイル直編集では触れませんが、テーマやCSS、機能まわりのカスタマイズは指示だけでどんどん直せます。エディタを開く前に用事が終わる、あの感覚は一度味わうと戻れません。
4. なんでもNASに入れたいという浪漫
これまでこのブログでは、ブログ本体もPOSレジも野鳥のシューティングゲームも、全部NASの上で動かしてきました。「動くものは全部NASに入れたい」という病気にかかっている僕としては、AIだけ外に置いておくなんて選択肢はありません。
Kay’s Voice: 正直に言うと、4番目の理由が7割です。でも、動かしてみたら残りの3つの恩恵が想像以上でした。浪漫から入って実用に着地するの、自作勢あるあるだと思っています。
今回の舞台:3台あるうちの3番機
僕は仕事柄・趣味柄あわせて3台のSynology NASを運用しています。この記事では便宜上、NAS01・NAS02・NAS03と呼びます。
- NAS03(DS1825+):今回の主役。CPUはRyzen V1500Bのx86_64機。開発用フォルダやPOSシステムが動いている本番機でもある
- NAS02(DS1019+ / メモリ8GB):このブログ(kaylog.io)のWordPressが乗っているサーバー機
まずNAS03に構築し、動作が固まったあとNAS02にも同じ構成を移植しました。同じ手順で2台目が20分だったので、レシピとしての再現性はそれなりにあると思います。
🔍 Kay’s Check: 前提はx86_64(Intel / AMD)のモデルです。Ryzen搭載機やCeleron搭載機ならほぼ対象内。ARM系のエントリーモデルだと同じようにはいきませんのでご注意を。あとメモリは、余裕を見て4GB以上あると安心です。
そもそもDockerって何?なぜDockerなのか
ここでいきなり「Container Managerで」と言われても、多くの人は身構えます。なので先に一言だけ。
Dockerとは、NASの中に「小さな別のパソコン」を丸ごと1台作る仕組みです。
引っ越し用のコンテナをイメージしてください。中に必要な道具(今回はNode.jsとかgitとか)を全部詰め込んで、封をして、NASの上にポンと置く。中で何をしても、NAS本体(DSM)の環境は一切汚れません。要らなくなったらコンテナごと捨てられます。Synologyでは「Container Manager」というパッケージ名で提供されています。
で、なぜDocker方式なのか。Claude Codeは公式のインストーラーをNASに直接叩き込むことも一応できるのですが、AIはDockerに入れることにしました。理由は4つです。
- DSMのユーザーランドは極端に最小構成で、gitすら入っていない。Claude Codeが前提としている道具が足りない
- DSMのアップデートで環境が変わっても、コンテナの中は無傷
- Debianベースの素直な環境なので、足りないものはapt一発で足せる
- マウントするフォルダを選ぶことで「AIに見せる範囲」を制御できる(これが地味に最重要)
4つめが効きます。NASの中身を全部見せるのは、いくらなんでも豪快すぎます。Dockerなら「このフォルダだけ見せる」「ここは読むだけ」がcompose.yamlの数行で決まります。
構築手順
準備するもの
- コントロールパネル → 端末とSNMP → SSHサービスを有効化
- パッケージセンターから Container Manager をインストール
- フォルダを2つ作成
/volume1/docker/claude(ビルド用の作業フォルダ)/volume1/docker/claude/home(認証情報の永続化用。ここが後で効いてきます)
Dockerfileを書く
Dockerfileは「コンテナの設計図」です。何をインストールした状態のコンテナを作るか、を書いたただのテキストファイルです。
dockerfile
FROM node:22-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
git ripgrep jq less procps tmux \
poppler-utils \
exiftool \
python3 python3-pip \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --break-system-packages openpyxl pandas
RUN npm install -g @anthropic-ai/claude-code
ENV TZ=Asia/Tokyo
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
WORKDIR /workspace
CMD ["sleep", "infinity"]
何を入れているのか、意味が分かると愛着が湧くので簡単に。
- ripgrep:超高速な全文検索ツール。Claude Codeの検索能力の中核。後述する「検索が一瞬」の正体はこいつです
- git:差分管理・コミット操作に必須
- tmux:常駐化の要。これも後で詳しく
- poppler-utils / exiftool / openpyxl:PDFの中身検索、写真のEXIF読み取り、Excel読み取り用。NASに眠っている資料を掘るなら入れておくと世界が広がります
- ENV LANG / LC_ALL:これがないと日本語表示が壊滅します。詳しくはハマりポイントで
compose.yamlを書く
compose.yamlは「そのコンテナをどう動かすか」の設定ファイルです。
yaml
services:
claude:
build: .
image: claude-code-nas:latest
container_name: claude-code
tty: true
stdin_open: true
volumes:
- /volume1/docker/claude/home:/root/.claude # 認証の永続化
- /volume1/homes/Kay:/workspace/kay:ro # ホーム全体(読み取り専用)
- /volume1/homes/Kay/Devs:/workspace/kay/Devs # 開発フォルダのみ書き込み可
cpuset: "0-3"
mem_limit: 4g
restart: unless-stopped
ここが今回の設計の肝です。
- ネストマウント:ホーム全体を
:ro(読み取り専用)で見せつつ、開発用のDevsだけ書き込み可を上から重ねています。「全部読めるけど、書けるのはここだけ」という、いちばん安心できる形です - cpusetでCPUコアを4つに限定、
mem_limitでメモリ4GBに制限。本番サービスが同居しているNASなので、資源は物理的に分けておきます restart: unless-stoppedで、NAS再起動時にコンテナが自動で立ち上がります
🔍 Kay’s Check:
home:/root/.claudeの行は聖域です。ここに認証情報が保存されるので、この行を崩すと再ログインからやり直しになります。compose.yamlをいじるときは、この1行だけは絶対に触らないでください。(1回やらかしました)
ビルドして起動して、認証
bash
cd /volume1/docker/claude
sudo docker compose up -d --build
sudo docker exec -it claude-code claude
初回起動でテーマ選択などの画面が出るので、進めていくとOAuth認証用のURLが表示されます。そのURLをPCやスマホのブラウザで開いてログインし、表示されたコードをターミナルに貼り付けるだけ。NASにブラウザは要りません。
/root/.claudeを永続化してあるので、認証は最初の一度きりです。
Kay’s Voice: ここで一瞬固まりました。「URLが出ない……」と。実は最初のテーマ選択画面で止まっていただけでした。画面をちゃんと読め、という当たり前の教訓。
エイリアスとCLAUDE.md
毎回長いコマンドを打つのは苦行なので、~/.profileにエイリアスを追加します。
bash
alias cc='sudo docker exec -it -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 claude-code tmux -u attach -t cc'
これで、SSHからccと2文字打つだけでAIの前に座れます。
あわせて、作業フォルダにCLAUDE.mdを置きます。これはClaude Codeが自動で読む「その場所のルールブック」です。僕はフォルダ構成の説明と、こう書きました。
本番稼働中のシステムは、変更前に必ず確認を取ること。
たった一行ですが、これがガードレールとして本当に効きます。
tmuxって何?——「閉じても消えない部屋」を作る
さて、ここまでで動くようにはなりました。でも問題があります。SSHを切断すると、セッションが死にます。
そこで登場するのがtmuxです。
tmuxとは、ターミナルの中に「閉じても消えない部屋」を作るソフトです。
普通、SSHで繋いだターミナルは、接続を切った瞬間に中でやっていた作業も終了します。tmuxは、その作業を別室に隔離してくれます。ドアを閉めて帰っても、部屋の中では作業が続いている。翌朝もう一度ドアを開けると、昨日の続きがそのまま残っている。そういうものです。
なので運用のルールはこうなります。
- 部屋から出るとき:
Ctrl+Bを押して離してからD(デタッチ。セッションは生き続ける) /exitは使わない(部屋そのものを取り壊す操作。Remote Controlの接続も切れます)
🔍 Kay’s Check:
Ctrl+B→Dは同時押しではなく2段階です。Ctrlを押しながらBを押して、いったん両方離して、それからD。Macの場合の「control」キーです(commandではありません)。ここ、僕は3回くらい間違えました。
iPhoneから操作する:Remote Control
ここからが本番です。tmuxの中でClaude Codeをこう起動します。
bash
claude --remote-control
これだけで、iPhoneのClaudeアプリのCodeタブから、NAS上のセッションに直接接続できます。
重要なのは、スマホはあくまで「窓」だということ。実際の処理もファイルアクセスも、全部NASの中で完結しています。スマホの電池もギガも減りません。
🔍 Kay’s Check: Remote Controlの利用にはPro / Max等のサブスクリプションでのOAuthログインが必要です。APIキーやsetup-tokenでのトークン認証では使えません。
起動時の自動復帰と、月1回の自動アップデート
ここまで作ったら、あとは無人化です。DSMのタスクスケジューラに2つ登録します。
ブートアップタスク(NAS起動時に自動復帰)
「作成 → トリガーされたタスク → ユーザー指定のスクリプト」、ユーザーはroot、イベントは「ブートアップ」。
bash
#!/bin/bash
sleep 90
DOCKER=/usr/local/bin/docker
$DOCKER exec claude-code tmux kill-session -t cc 2>/dev/null
$DOCKER exec claude-code tmux new -d -s cc -c /workspace/kay/Devs
sleep 5
$DOCKER exec claude-code tmux send-keys -t cc 'claude --remote-control' Enter
sleep 90:コンテナの起動完了待ち。焦らないkill-session→newの順にすることで、手動で「実行」ボタンを押して再テストしても壊れません(冪等)- claudeをtmuxの起動コマンドに直接渡す方式もありますが、エラーが出た瞬間にセッションごと消えて原因が分からなくなるので、bashの部屋を先に作ってからsend-keysで打ち込む方式が正解でした
月次アップデートタスク(毎月1回・深夜)
bash
#!/bin/bash
cd /volume1/docker/claude
DOCKER=/usr/local/bin/docker
$DOCKER compose build --no-cache && $DOCKER compose up -d || exit 1
sleep 15
$DOCKER exec claude-code tmux new -d -s cc -c /workspace/kay/Devs
sleep 5
$DOCKER exec claude-code tmux send-keys -t cc 'claude --remote-control' Enter
$DOCKER image prune -f
--no-cacheが肝。これがないとnpmのインストール層がキャッシュされて、いつまでも古いバージョンのままです&& ... || exit 1:ビルドに失敗したら現行環境を維持します。壊れた状態で朝を迎えないための保険image prune -f:古いイメージの自動掃除
これで、メンテナンスすら自動になりました。
ハマりポイント集(この記事の本体)
きれいに書いてきましたが、実際はここからが長かったです。同じ道を通る人のために、全部置いていきます。
1. compose.yamlが「invalid leading UTF-8 octet」
エディタがUTF-16やBOM付きで保存していたのが原因でした。SSHからヒアドキュメント(tee << 'EOF')で書けば、確実にBOMなしUTF-8になります。
ちなみにDSMにはfileコマンドがないので、判定はこれで。
bash
head -c 4 compose.yaml | od -An -tx1
ff feならUTF-16、ef bb bfならBOM付きUTF-8です。
2. 「NanoCPUs can not be set」
DSMのカーネルはDockerのCFSクォータ(cpus:指定)に対応していません。cpuset: "0-3"のコア割り当て方式に変更して解決。むしろ物理的にコアを分けるので、本番サービスとの隔離という意味では確実です。
3. 「Bind mount failed: does not exist」
マウント元のフォルダが実在しないとコンテナが起動しません。僕の場合、開発フォルダが/volume1/devではなく/volume1/homes/Kay/Devsにあっただけでした。パスの大文字小文字は別物(Devsとdevs)なので要注意。
4. コンテナに直接入れたものは消える
docker exec ... apt-get installで入れたものはそのコンテナ限りです。compose.yamlを変更してコンテナが再作成されると、きれいに消えます。tmuxが消えたときは本気で焦りました。
恒久化したいものは必ずDockerfileに書いて、イメージに焼き込む。 これが鉄則です。
5. タスクスケジューラの罠3連発
- PATHが最小限なので、dockerはフルパスで書く(
/usr/local/bin/docker。DSMのバージョンによっては/var/packages/ContainerManager/target/usr/bin/docker) - 出力保存がデフォルトOFF。「設定」から出力結果の保存を有効化しないと、失敗しても何も分かりません
- そして最大の罠。タスクを別のNASに登録していた
……はい。「動かない、なぜだ」と1時間ほど格闘した挙げ句、ブラウザのタブがNAS02のDSMだった、というオチです。複数台運用しているかたは、まずタイトルバーのホスト名を確認してください。
6. マウントパスを変えたら信頼確認が出る
Claude Codeは作業フォルダをパスで記憶しているので、マウントパスを変えると初回の信頼確認ダイアログで止まります。一度attachして承認してあげてください。
7. 日本語が化ける(入力した文字も読めない)
node公式イメージは素の状態だとUTF-8ロケールが未設定で、tmuxが全角文字の幅を計算できません。結果、打った文字が消えたり重なったりします。
解決は、DockerfileにENV LANG=C.UTF-8とENV LC_ALL=C.UTF-8を焼き込むこと。attach側もtmux -uと-e LANG=...を付けます。
🔍 Kay’s Check: この症状、英語だけ使っているうちは絶対に表面化しません。日本語を打った瞬間に発症します。海外の解説記事に載っていないのはそのせいです。
おまけ:画面の状態を確認する裏技
トラブルシュート中、「今どういう画面になってる?」を確認するのに、スクリーンショットを撮るより確実な方法があります。
bash
tmux capture-pane -t cc -p
これでtmux内の画面がそのままテキストで吐き出されます。以後、僕のトラブルシュートはこれが標準になりました。
実際に使ってみた:検索が一瞬すぎて笑った
さて、本題です。何ができるのか。
日本語でファイルを探せる。しかも一瞬。
「◯◯ファイルを探して」
これが体感1〜2秒で返ってきます。File Stationの検索窓とは次元が違う速度です。正体は前述のripgrepで、数万ファイルを舐めても一瞬です。「NASの検索ってこんなに速かったの?」と本気で驚きました。
ファイルの中身を見て教えてもらうことも
「〇〇フォルダにある、▢▢PDFファイルの内容を読んで、△△について教えて!」 「あの写真には何が写ってる?」こんな感じ質問をすると、ちゃんと答えが返ってきます!
一括リネーム・整理も自然言語で。
「このフォルダのファイル名、先頭の日付を YYYY-MM-DD 形式に揃えて」
これだけで済みます。今までAutomatorやシェルスクリプトを書いていた作業が、話しかけるだけになりました。しかもNAS内で完結するので、巨大ファイルをネットワーク越しに転送する必要がありません。ここがローカルのMacで動かすAIとの決定的な差です。
設定ファイルの調査・修正。
「Web Stationの設定ファイルを読んで、いま何のサイトが動いてるか一覧にして」——こういう、自分で書いたのに忘れている設定の棚卸しが本当に楽です。
セキュリティと運用の注意点
便利ですが、無防備に使うものではありません。僕が守っているルールを共有します。
- 見せる範囲はマウントで制御する。見せたくない共有フォルダは、そもそもマウントしない。参照だけでいいものは
:ro - CLAUDE.mdに本番システムの注意書きを入れる。「変更前に必ず確認を取ること」の一文が保険になります
- コンテナ内はroot動作なので、AIが新規作成したファイルはroot所有になります。Web公開フォルダなどでは必要に応じて
chownを - 本番サービスと同居させるなら
cpusetとmem_limitで資源を隔離する - Remote Control使用中は、会話ログがAnthropicのサーバー経由で同期されます(実行とファイルアクセスはNASローカルで完結)
- compose.yamlなどの設定ファイルは
chmod 600で権限を絞る
まとめ
- Synology NAS(x86_64機)にClaude Codeを常駐させることはできる。方式はContainer Manager(Docker)一択
- tmuxでセッションを常駐化し、Remote ControlでiPhoneからどこでも接続
- タスクスケジューラでNAS起動時の自動復帰と、月1回の自動アップデートまで無人化
- ハマりどころは、文字コード・CPU制限方式・日本語ロケール・タスクスケジューラの罠。特にLANG/LC_ALLの焼き込みは必須
- 見せる範囲はマウントで制御。
:roとCLAUDE.mdがガードレール - 日常操作はたった2つ。SSHから
cc、抜けるときはCtrl+B→D
そして次回、事件が起きます
……と、きれいにまとまったところで終われば良かったのですが。
NASの中に24時間働くAIがいるという状況は、「じゃあ次は何を作らせよう」という危険な思考を生みます。ブログもPOSレジもゲームもNASで動かしてきた僕が、次に目をつけたのは——Synology純正の「USB Copy」でした。
野鳥を撮るかたなら分かると思うのですが、あのパッケージ、メモリカードをフォーマットすると登録したタスクが呼び出せなくなるんです。カードの性能維持のためにフォーマットは大事。でもフォーマットすると設定が飛ぶ。この矛盾に、僕は長いことモヤモヤしていました。
そこで、NAS常駐のClaudeと一緒に自作してみたところ——本家より使いやすいものができてしまいました。
挿す → ピッ → ピッピッ → アイコンごと消えるので、そのまま抜くだけ。しかもiPhoneから「USB Copyして」と話しかけても動きます。
次回はその全記録です。自動排出だけで5段階の迷宮に迷い込んだ話も含めて、洗いざらい書きます。お楽しみに。


コメント
NASにAI常駐か、さすがに思いつかなかったわ
codexはスマホから使えるので
MacBookかメインPCを起動してる時なら
どこにいてもcodexがなんでもやってくれます
それがNASだけで、ロマンや‼️
Caosさん、ありがとうございます!
自分のあらゆるデータの母艦で、それらのデータに対して指示が出せる!
データ活用の可能性が一気に広がりました。
こんにちは、はじめまして
記事興味深く拝見しました。
2点ほど質問あります。
1)Kayさんが実施しているClaudeCodeコンテナ常駐ですが、CPUやメモリ使用量って、
どれくらいでしょうか?
というのも、以前私はOllamaをDS720+でコンテナ常駐させてみたのですが、CPU100%
はりつきで全然使いものにならなかったです。
2)ClaudeCodeはやはり月額使用料払ってらっしゃいますか?
aoao様
ブログ記事をお読みいただきありがとうございます!また、お返事が遅くなりまして申し訳ありませんm(_ _)m
当ブログのサーバーとなっているDS1019+(8GB)にClaudeCodeを常駐させていますが、CPUもメモリも負荷が高くなることはありません。実測しましたところ、アイドル時で CPU 1%未満・メモリ約270MB程度でした。
おそらくですが、お使いのOllamaでは推論自体NASのリソースを使って行いますが、Claude CodeはAnthropicのサーバーサイドで行われているためこの違いが出ているのだと思います。
また、サブスクについては私は月額100ドルのMaxプランに入っています。Remote ControlにはサブスクのOAuthログインが必要ですので、Pro以上のサブスクが必要になります。
ご参考になりましたら
また何かありましたらお気軽にご相談ください!