Claude Codeで本番環境を運用する|自宅サーバーの6サイトを一元管理する仕組み

作成日:2026年10月2日 14:46読了時間:約 16 分
"サムネイル画像"

「Claude Code」に本番のサーバーを操作させると、コードの修正からログの調査までを任せられる一方で、コマンド 1 つでサイトが止まることもあります。

私は、このサイト(ryusei.io)を含む 6 つのサイトを、自宅のミニ PC 1 台で運用しています。コードの修正から記事の投入、サーバーの管理までを、すべて Claude Code で一元管理しています。本当は開発用の環境を別に用意したかったのですが、メモリやストレージの値上がりでマシンの価格が上がっていたため見送り、本番のサーバーの上で直接 Claude Code を使っています。予算に都合がつけば、開発用のマシンも導入するつもりです。ソースを書き換えるとそのまま本番のファイルが変わる構成なので、事故が起きるたびに、指示ファイルと確認の仕組みを足してきました。

この記事では、そうして足してきた仕組みの全体を説明します。

この記事でわかること 

  • 本番のサーバーで使う CLAUDE.md の分け方
  • 危ない操作の前に Claude Code に確認を取らせる方法
  • 無人で実行する Claude Code の権限の絞り方
  • セッションをまたいで知識を引き継ぐ方法
  • Claude Code に記事と画像を作らせる手順

Claude Code のインストールや CLAUDE.md の役割といった基本は知っている人を想定しています。自宅サーバーの構築と外部への公開は別の記事で説明しているので、この記事では扱いません。

本番のサーバーで Claude Code を使っている構成 

サイトはそれぞれ Docker コンテナで運用しています。閲覧者からの接続は、IPv4 の入口にしている VPS を経由して自宅のサーバーに届きます。

Claude Code での作業は、サーバーで「Remote Control」(claude rc)を常駐させておき、PC の「Claude Desktop」やスマートフォンの Claude アプリからセッションを開いて行っています。同じセッションを PC とスマートフォンのどちらからでも開いて、続きを操作できます。自分でコマンドを実行したいときや、ターミナルでの作業が必要なときだけ、SSH でサーバーに接続しています。

claude rc(Remote Control)とは

claude rc(claude remote-control)は、このマシンで動く Claude Code のセッションを、ブラウザーの claude.ai/code や Claude のアプリから操作できるようにするコマンドです。作業フォルダで実行すると待ち受けの状態になり、別の端末からセッションを開くと、このマシンの上でセッションが起動します。ファイルの読み書きやコマンドの実行はすべてこのマシンで行われ、ほかの端末では画面の表示と入力だけを行います。

このマシンの側から Anthropic のサーバーへ接続して指示が来るのを待ち、ほかの端末からの指示は、その接続を通って届きます。ほかの端末とこのマシンが直接つながることはなく、外へ向かう HTTPS の通信だけで動くので、ルーターでポートを開放する必要はありません。

利用するには、Pro・Max・Team・Enterprise のいずれかのプランのアカウントで Claude Code にログインしている必要があります(Team・Enterprise では、管理者が先に Remote Control を有効にする必要があります)。API キーを設定して Claude Code を使っている場合は利用できません。

既定の --spawn same-dir では、すべてのセッションが同じフォルダで動きます。複数のセッションで同じファイルを同時に編集しないよう注意が必要で、セッションごとに git の worktree を分けたいときは --spawn worktree を使います。SSH で接続して起動したプロセスは、接続を切ると終了してしまうので、私は tmux の中で起動して常駐させています。

PC やスマートフォンの Claude のアプリから Remote Control を経由して Claude Code を使い、作業フォルダをバインドマウントで Docker コンテナに反映している構成図

作業フォルダの構成 

Claude Code は、すべてのサイトのリポジトリをまとめた 1 つの作業フォルダで起動しています。作業フォルダ自体も git で管理し、サイトごとのリポジトリや nginx の設定のリポジトリを、サブモジュールとして入れています。フォルダ名を例示用の名前に置き換えると、次のような構成です。

plaintext
workspace/                ← Claude Code を起動するフォルダ
├── CLAUDE.md             ← 全サイト共通の制約と構成
├── .claude/
│   ├── settings.json     ← このフォルダで起動したときの権限
│   └── rules/            ← 特定のファイルを開いたときだけ読む規約
├── docs/                 ← 変更履歴と未解決の課題
├── memory/               ← Claude Code のメモリ
├── site-blog/            ← サイトごとのリポジトリ
│   └── CLAUDE.md         ← そのサイトのコマンドと注意
├── site-tool/
│   └── CLAUDE.md
└── proxy/                ← nginx の設定

各サイトのソースは、サイトごとのフォルダをそれぞれの Docker コンテナにそのまま共有する形(バインドマウント)で配信しているので、Claude Code がファイルを 1 つ書き換えると、本番の Docker コンテナの中のファイルも同時に変わります。Next.js のサイトはビルドし直すまで表示は変わりませんが、ファイルの変更を監視して自動で再起動するプロセスは、保存した時点で再起動します。

動作の確認は Playwright で E2E まで行わせる 

サーバーには、ブラウザーをプログラムから操作するツール「Playwright」と、Chromium を入れてあります。Claude Code が修正したあとの動作の確認は、ページを開いて操作し、結果の表示を確かめる E2E の検証まで、このマシンの中で完結させています。記事に載せるスクリーンショットも、同じ仕組みで撮らせています。

検証のためのビルドは、配信中のビルド成果物を上書きしないよう、フォルダを /tmp に複製してから行わせています。画面を確かめるだけなら、本番とは別のポートで開発用のサーバーを起動して開かせることもあります。

自分のサイトを自動で開くときは、広告と計測を止めた状態で開かせています。検証で開いた分が、広告の表示回数やアクセス解析に数えられないようにするためです。

Claude Code に任せていること 

作業の種類ごとに、確認なしで任せるものと、実行する前に私の確認を取らせるものを分けています。

作業

確認なしで任せるもの

実行前に確認を取らせるもの

コードの修正

編集・型チェック・リント

本番のビルドと反映

記事

構成・下書き・図解の作成

下書きの内容・公開・有料の画像生成

調査

ログ・アクセス解析・DB の読み取り

—

動作の確認

Playwright での E2E の検証・スクリーンショットの撮影

広告を表示させた状態での検証

サーバーの管理

Docker コンテナとプロセスの状態の確認

本番に影響する操作(後述)

git

—

作業の区切りの commit と push

CLAUDE.md を 3 層に分け、書く内容を 4 種類に絞る 

本番で起きた事故を振り返ると、多くはコマンドそのものの誤りではなく、そのコマンドがこの環境で何を引き起こすかという情報が、Claude Code に渡っていなかったことが原因でした。たとえば、型チェックのコマンドを実行したら、「pnpm」が実行前の確認で依存パッケージのずれを検出し、本番の依存パッケージを入れ直し始めたことがあります。.env を直してビルドしただけでは、Docker コンテナの作成時に固定された古い環境変数のまま公開されたこともありました。こうした環境ごとの事情は、CLAUDE.md や規約のファイルに書いて渡すしかありません。

Claude Code は、ユーザー全体の ~/.claude/CLAUDE.md と、起動したフォルダの CLAUDE.md をセッションの最初に読み込み、サブフォルダの CLAUDE.md は、そのフォルダのファイルを開いたときに読み込みます。私はこれに合わせて、CLAUDE.md を 3 つの層に分けています。

層

置き場所

書いていること

ユーザー全体

~/.claude/CLAUDE.md

応答の言語、確認の取り方、作業の区切りで commit と push を確認すること

作業フォルダ

作業フォルダの直下

本番であることと確認が必要な操作、サーバー全体の構成、全サイトに共通する規約

サイトごと

各リポジトリの直下

そのサイトのコマンド、データと設定の正本の場所、そのサイトだけの注意

書く内容を 4 種類に絞る 

一時期、CLAUDE.md が全部で 2,090 行になっていました。作業が終わるたびに、経緯や実測値まで CLAUDE.md に書き足していたのが主な理由です。そこで、CLAUDE.md に書くものを次の 4 種類に限り、全ファイルを見直して 940 行まで減らしました。

  • 破ると事故になる制約と、何が起きるかの 1 行
  • データ・設定・生成物の正本の場所
  • 毎回使う手順とコマンド
  • 詳しいドキュメントへのポインタと、それをいつ読むか

経緯や実測値、試して駄目だった案は変更履歴のファイルに、まだ直していない問題は未解決の課題のファイルに書かせています。1 項目は 3 行以内とし、迷ったら「次のセッションでも毎回必要か」で分けることも、CLAUDE.md 自体に書いてあります。

特定のファイルを開いたときだけ読ませる規約 

nginx の設定の手順のように、特定のファイルを触るときにだけ必要な規約は、作業フォルダの .claude/rules/ に置いています。ファイルの先頭に paths を書くと、そのパターンに一致するファイルを開いたときだけ読み込まれます。

markdown
---
paths:
  - "proxy/conf.d/**"
  - "proxy/nginx.template.conf"
---

# nginx の設定を変える前に読むこと

- nginx.conf は生成物なので直接編集しない。テンプレートを直して生成し直す
- 設定の反映(reload)は、実行する前に確認を取る

規約が読み込まれたときに呼ばれるフック(InstructionsLoaded)で確かめると、規約が読み込まれるのは、Claude Code の「Read」ツールでファイルを開いたときだけで、Bash の cat で読んだときは読み込まれません。規約の本文に @ でほかのファイルを取り込むと、その部分はファイルを開く前のセッションの開始時に読み込まれるので、読み込みを遅らせたい内容は本文に直接書いています。

私は、毎回は必要ないものの、読み落とすと事故になる規約をここへ移しています。ただし、読み込まれるきっかけはファイルを開くことに限られるので、Docker コンテナの再起動のように、ファイルを開かずに行う操作の前の注意は、CLAUDE.md の本体に残しています。

危ない操作の前に Claude Code に確認を取らせる 

CLAUDE.md に書いた禁止事項は、必ず守られるわけではありません。そのため、確認が必要な操作を CLAUDE.md に書くだけでなく、確認の取り方を決め、その規約を hooks で毎回入れ直しています。

確認なしでは実行させない操作 

作業フォルダの CLAUDE.md の冒頭に、次の操作は実行前に必ず確認を取ることと書いています。

  • Docker コンテナの停止・作り直し・再起動
  • プロセスの再起動・停止・台数の変更
  • DB のマイグレーションの適用
  • ファイル・ボリューム・イメージの削除
  • nginx の設定の変更と反映、SSL 証明書の差し替え
  • 作業フォルダを書き換える git の操作(checkout・reset・pull・clean)

ログやプロセスの状態を見るような読み取りの操作は、確認不要と明記しています。私は確認を毎回求められると煩わしく感じるので、確認の対象は本番に影響する操作だけに絞っています。

推奨案を付けた選択肢で確認する 

確認の取り方は、ユーザー全体の CLAUDE.md で決めています。Claude Code には、選択肢を出して質問する機能(AskUserQuestion)があります。私は、先頭の選択肢を推奨案にして、各選択肢に判断材料を 1 行ずつ添えるよう指示しています。

選択肢の形なので、推奨案でよければ 1 回選ぶだけで答えられ、どれも違うときは「その他」に自由に書いて返せます。確認する場面は、commit と push、設計の方針のように後から覆しにくい判断、仕様の解釈が分かれるとき、ファイルの削除や本番への反映です。

commit と push の確認は作業の区切りで 1 回にまとめる 

以前は、フックで commit と push のたびに許可を求めさせていました。毎回聞かれるのが煩わしくなり、外しています。今は、commit と push を許可の確認なしで実行できる設定にしたうえで、作業が一区切りついたときに、commit と push をまとめて 1 回だけ確認させています。

確認を取らずに応答を終えようとしたときは、Stop フック(Claude Code が応答を終える直前に呼ばれるフック)が、未コミットや未 push の変更が残っていないかを調べて止めます。同じ状態で 2 回は止めないので、私が「コミットしない」と答えた変更で何度も止まることはありません。

このフックが実行する git status は、git のインデックスを書き換えます。そのため、ファイルの変更を監視して自動で再起動するプロセスが、フックが動くたびに再起動していました。今は、フックの git に GIT_OPTIONAL_LOCKS=0 を付けてインデックスを書き換えないようにし、監視の対象からも .git を外しています。

hooks と権限の設定 

確認の取り方のように常に守らせたい規約は 1 つのファイルにまとめ、UserPromptSubmit フック(私がメッセージを送るたびに呼ばれるフック)で、毎回のメッセージに添えています。規約のファイルを直すと、次のメッセージから反映されます。ユーザー全体の設定(~/.claude/settings.json)のうち、確認に関わる部分は次のとおりです。

json
{
  "permissions": {
    "allow": ["Bash(git add:*)", "Bash(git commit:*)", "Bash(git push:*)"]
  },
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "$HOME/.claude/hooks/inject-rules.sh", "timeout": 10 }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "$HOME/.claude/hooks/check-git.sh", "timeout": 15 }] }
    ]
  }
}

確認なしで通す操作は、ユーザー全体の設定と、作業フォルダの設定(.claude/settings.json)に分けています。外部のサーバーへの接続のように影響の大きいものは、作業フォルダで起動したセッションでだけ確認なしで通るようにしました。

ここまでの仕組みは、Claude Code に確認を求めさせるためのもので、危ない操作そのものを設定で止めてはいません。確実に止めたい場合は、permissions の ask や deny に対象のコマンドを書くか、コマンドの実行前に呼ばれる PreToolUse フックで止める方法があります。私の環境では、まだ入れていません。

無人で実行する Claude Code の権限を絞る 

以前、毎朝 cron で Claude Code を無人で実行し(claude -p)、記事の題材を調べて、執筆の材料をフォルダに置かせていました。提案される題材がいまひとつだったので、今は止めています。題材は自分で用意しています。

作るときに分かったのは、無人の実行でも、対話で使っているユーザー設定とプロジェクト設定をそのまま読み込むことでした。そのため、commit や push などを確認なしで通す許可と Stop フックが、無人の実行にもそのまま引き継がれていました。無人の Claude Code は外部の Web ページを読むので、ページに書かれた指示を実行した場合(プロンプトインジェクション)に、それらの許可を使える状態になっていました。

そこで、無人で実行するときは、対話用とは別の狭い設定を渡しています。

  • --restricted で、ユーザー設定とプロジェクト設定を読み込まず、コマンドを実行するツールを外す(--tools で名前を挙げたツールだけは使える)
  • 専用の設定ファイル(--settings)で、書き込める場所を作業用のフォルダ 1 か所に、実行できるコマンドを自作のスクリプトだけに限る
  • --permission-mode dontAsk で、確認が必要になる操作は、許可の一覧に無ければすべて拒否する(読み取りは通るので、秘密の情報を含むファイルは deny で読めないようにする)
  • 自動メモリ(判明したことを Claude Code がファイルに書き残し、次のセッションで読み込む機能)を無効にする。保存先は git のリポジトリごとに決まるので、有効のままだと対話用のメモリに書き込めてしまう
  • DB や git は前処理のスクリプトで扱い、Claude Code には結果のファイルだけを読ませる
bash
claude -p --restricted \
  --tools Read Glob Grep Write Edit WebFetch WebSearch Bash \
  --settings ./config/headless-settings.json \
  --permission-mode dontAsk \
  --output-format json < prompt.md

設定を決めたあと、ダミーのファイルを使って、作業用のフォルダの外への書き込み、秘密の情報を含むファイルの読み取り、git の実行がすべて拒否されることを確かめました。

セッションをまたいで知識を引き継ぐ 

新しく始めたセッションには、前のセッションの会話の内容は入っていません。次のセッションでも必要な情報は、作業を終える前にファイルへ書かせています。書く場所は、内容によって 4 つに分けています。

書く場所

書くもの

例

CLAUDE.md

毎回必要な制約・正本の場所・手順

本番のビルド成果物を削除しない

変更履歴

経緯・実測値・試して駄目だった案

ある設定にした理由と、そのときの測定値

未解決の課題

まだ直していない問題と、確認する予定

対策の効果を確かめる日

メモリ

私の好み・進行中の案件

文章は比喩を使わずに書く

メモリには自動メモリの機能を使い、保存先を設定(autoMemoryDirectory)で作業フォルダの中に移して、git で管理しています。

作業が終わったら、判明したことをこの分類で書かせ、完了の報告で更新したファイルを挙げさせています。セッションを開始したときには、SessionStart フックで、バックアップの失敗や、確認を待っている件を表示させています。

記事の執筆と画像の作成をスキルにまとめる 

このサイトの最近の記事は、執筆の手順をスキル(作業の手順と参照資料をまとめておき、必要なときに Claude Code が読み込むファイル)にまとめて、Claude Code に書かせています。スキルには、題材の決め方から、文体の規則、記事の構成、画像の作り方、CMS への投入までの手順が入っています。なかでも次の 3 つは、記事の内容と見た目に直接関わるので、手順の中で必ず行わせています。

書く前に体験を聞き取る 

スキルには、構成を決めたあと、本文を書く前に私へ次の 6 つを質問する手順があります。

  • 最初に失敗したところ
  • 途中で捨てた選択肢と、その理由
  • 手元の実測値(所要時間・料金・スペック・バージョン)
  • 公式ドキュメントに書かれていないのに詰まった点
  • 今も使っているか、別のものへ乗り換えたか
  • 読者が誤解していそうなこと

私が体験していないことは書かせないので、この回答が無いと、誰が書いても同じ一般論の記事になります。聞き取りの前には、コードや CLAUDE.md、変更履歴から分かることを Claude Code 自身に確かめさせ、推測を書いたうえで確認だけを求めさせています。

文体を私の記事と数字で比べる 

文体の規則は、私が書いた記事 14 本を集計した値で決めています。たとえば私の 1 文は平均 52 字ですが、スキルを作った当初に Claude Code が書いた記事は平均 31.7 字で、同じくらいの長さの短い文が並んでいました。

下書きは、付属のチェッカーで文の長さのばらつきや「」と「私」の頻度を私の記事と比べ、使わない語が無いかも調べさせ、すべての項目が基準に入ってから私が読みます。私が読んで「自分ならこう書かない」と感じた箇所は、「× こう書いた / ○ こう書く」の表に追記させています。

それでも、Claude Code が書いた記事 12 本を照合し直したところ、事実の誤りと、ツールの変更で古くなった記述が 18 件見つかりました。古くなった記述は、記事を書いたあとにツールの仕様を変えたのに、記事を直していなかったものです。今は、ツールの画面や上限を変えるファイルを開くと、その仕様を書いた記事も直すよう求める規約が読み込まれるようにしています。

画像は SVG で描かせて、縮小して確かめる 

サムネイルと図解は、Claude Code に SVG で描かせ、自作の小さなツールで PNG や WebP に変換しています。このサーバーには日本語のフォントが入っておらず、そのまま変換すると日本語の文字がすべて「□」になるので、ツールに「Noto Sans JP」を同梱し、変換するときだけ読み込ませています。

Claude Code は変換した画像を読み込んで内容を確認できるので、サムネイルは記事の一覧に表示される大きさまで縮小した画像も見させ、文字が読めるかを確認させています。

写真のような絵が必要なときだけ、Google の画像生成モデル「Nano Banana Pro」の API を呼び出す別のツールを使います。こちらは 1 枚ごとに料金がかかるので、実行前に見積もりを出させ、私が確認してから生成させています。

サブエージェントで調査とレビューを分ける 

調査やレビューは、サブエージェント(別のコンテキストで動く Claude Code)に分けて、並行して進めさせています。

サブエージェントのモデルを使い分ける 

私は Claude の「Max 20x」プランを契約しています。このサーバーの運用とほかのプロジェクトの開発の両方で、朝から晩まで同じアカウントの Claude Code を使っています。最近は、大きなコードベースで複数のサブエージェントを決まった手順で動かすワークフロー機能を使うことが増え、Max 20x でも利用枠が足りなくなってきました。予算に余裕があれば、2 つ目のアカウントも契約したいと考えています。

以前、モデルを指定せずに 6 本のサブエージェントを同時に起動したところ、親のセッションと同じ「Fable」で動き、利用枠を大きく消費したことがあります。Fable は、1 トークンあたりの料金が最も高いモデルです。それ以降、モデルは Claude Code に選ばせ、Fable だけは使う前に私の承認を取らせています。

モデルの別名(sonnet など)が指すモデルは、Claude Code のバージョンで決まります。私の環境では Claude Code の自動更新を止めていたため、新しい Sonnet が出たあとも、sonnet を指定したサブエージェントが 1 つ前の Sonnet で動いていました。Remote Control の常駐プロセスも起動したときのバージョンで動き続けるので、Claude Code を更新したら、常駐プロセスも起動し直す必要があります。今は、新しいバージョンが出ていないかを、cron のスクリプトで週に 1 回確かめています。

自分の差分を別のサブエージェントにレビューさせる 

不具合をまとめて直したあとは、その修正の差分を、別のサブエージェントにもう一度レビューさせています。私が運用しているツールのサイトで、レビューで見つかった 59 件の不具合をまとめて直したときは、この差分のレビューで、修正が新しく持ち込んだ不具合が 6 件見つかりました。どれも型チェックとリントは通っていました。うち 2 件は、直そうとした問題を、別の形で作り直していたものです。

差分のレビューは修正をコミットする前に行い、修正前のファイルを git show HEAD:<パス> で取り出させて、その差分が本当に持ち込んだ問題かを比べさせています。

まとめ 

本番のサーバーで起きた事故の多くは、その環境に固有の事情が Claude Code に渡っていなかったことが原因でした。私は事故のたびにルールを足し、CLAUDE.md に書くだけでなく、確認の取り方を決めて、その規約を hooks で毎回入れ直しています。

  • CLAUDE.md はユーザー全体・作業フォルダ・サイトごとの 3 層に分け、書く内容を制約・正本・手順・ポインタの 4 種類に絞る
  • 本番に影響する操作だけを確認の対象にし、推奨案を付けた選択肢で確認させる
  • 無人で実行するときは、対話用の設定を読み込ませず、専用の狭い設定を渡す
  • 経緯は変更履歴に、好みと進行中の案件はメモリに書かせ、次のセッションへ引き継ぐ
  • 記事はスキルの手順で書かせ、執筆の前に体験を聞き取り、文体は私の記事の実測値と比べる

関連記事 

自宅サーバー用ミニPCのおすすめと選び方|6サイトを1台で運用する構成とメモリの目安 | Ryusei.IO

自宅サーバーに使うミニPCの選び方とおすすめ4機種を、6つのWebサービスを1台のミニPCで運用している実例から紹介します。CPUとメモリの目安、24時間稼働させたときの電気代、停電や故障への備えまで解説します。

faviconryusei.io
自宅サーバーを外部公開する方法とセキュリティ対策|v6プラスでもVPS経由で公開できる | Ryusei.IO

v6プラスやDS-LiteなどのIPoE回線でポート開放できなくても、VPSを入口にしてIPv6で自宅へ転送すれば公開できます。実際に運用している構成と設定、Cloudflare Tunnelとの比較、SSHでの外部接続、公開前のセキュリティ対策を解説します。

faviconryusei.io
複数のNext.js製アプリをポート番号を分けて同じサーバーで運用する方法の解説 | Ryusei.IO

Next.js製のWebアプリをセルフホストする場合に、同じサーバー内でリバースプロキシを使って複数のアプリを運用する方法を解説していきます。リバースプロキシにはOpen Lite Speedを使用します。

faviconryusei.io

Latest Tips