VPSでClaude Codeを24時間動かしている
僕はClaude Code(AnthropicのCLIツール)をVPS上で24時間稼働させている。
やっていることはこんな感じだ。
- 毎朝8時にAI/ECニュースを自動収集してDiscordに配信
- クライアントのKPIを自動モニタリング
- フリーコンサル案件のソーシングを自動実行
- Discord Botとして常駐し、スマホからの指示に即応答
非エンジニアの僕がこれを構築できたのは、Claude Code自体が開発を代行してくれるからだ。コードは1行も自分で書いていない。
ただ、「作れる」と「安定運用できる」は別の話だった。
障害は突然やってくる
3月27日の夕方、いつも通りDiscordからClaude Codeに話しかけた。
返事がこない。
VPSのプロバイダ(ConoHa)で障害が発生し、サーバーが強制再起動されていた。
サーバー自体は復旧していたが、Claude Codeの認証(OAuth)が切れていた。これは想定内だ。「再ログインすればいい」と思った。
ここからが地獄だった。
「再ログイン」ができない
Claude Codeのログインコマンド claude auth login を実行すると、URLが表示される。そのURLをブラウザで開いて認証し、コードをCLIに貼り付ける仕組みだ。
問題: VPSにはブラウザがない。
「ヘッドレス環境」と呼ばれる状態で、画面もマウスもない。サーバーはターミナル経由でしか操作できない。
Claude Codeにはヘッドレス環境向けのフローがあり、ブラウザの代わりにコードを手入力できるはずだった。しかし、入力しても「400 エラー」で弾かれる。
何度やっても同じ結果だった。
8種類の方法を試して全部失敗
ここから2時間半の試行錯誤が始まった。
- expectスクリプト — 自動入力ツールで代わりに入力。stdin(標準入力)を読み取らない
- screen stuff — ターミナルセッション経由で文字を送り込む。パイプが壊れる
- TIOCSTI(キーストローク注入) — Linuxカーネルの機能で直接キーボード入力を偽装。入力は成功するが400エラー
- curl callback — 認証サーバーに直接コードを送信。302 success(成功)を返すのにトークン交換が400
- SSHポートフォワーディング — Macのブラウザ → VPSへトンネル。同じく400
- Terminal.appから対話的に — Macのターミナルで直接SSH。コード入力成功、だが400
- BROWSER環境変数 — 「ブラウザがある」と偽装。URLのパラメータがハードコードで変化なし
- Claude Code再インストール — 完全に入れ直し。変化なし
すべて同じ「400 エラー」。
この時点で分かったこと: claude auth login のヘッドレスフローは、構造的にバグっている。 認証URLの redirect_uri と、トークン交換時の redirect_uri が一致しないのが原因だと推定した。
突破口:Macのキーチェーン
発想を変えた。
VPSでログインできないなら、既にログイン済みのMacから認証情報をコピーすればいい。
macOSにはキーチェーンという認証情報の金庫がある。Claude Codeもここにトークンを保存している。
security find-generic-password -s "Claude Code-credentials" -w
このコマンドで、Macに保存されているClaude Codeの認証情報(アクセストークン + リフレッシュトークン)がJSON形式で出力される。
これをVPSに転送すれば、ブラウザなしでログインが復活するはずだ。
最初の失敗:環境変数方式
最初に試したのは、トークンを環境変数として設定する方法だった。
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxx...
動いた。 一瞬。
数時間後、またDiscord Botが沈黙した。アクセストークンには有効期限があり、数時間で失効する。環境変数にはアクセストークンしか入れていないから、リフレッシュ(自動更新)ができない。
つまり環境変数方式では、数時間おきにMacから新しいトークンを取得してVPSに送り続ける必要がある。Mac常時起動が前提。現実的じゃない。
正解:.credentials.json
Claude Codeのソースコードを読んだ。認証情報の保存場所を探すためだ。
function L3() {
if (process.platform === "darwin") return bv4(Iv4, o01); // Mac → keychain
return o01; // Linux → ファイル
}
Mac ではキーチェーン、Linux ではファイルに保存する。ファイル名は .credentials.json。パスは ~/.claude/.credentials.json。
Macのキーチェーンから取得したJSONを、VPSのこのファイルに書き込んだ。
CREDS=$(security find-generic-password -s "Claude Code-credentials" -w)
ssh root@VPS "echo '$CREDS' > ~/.claude/.credentials.json && chmod 600 ~/.claude/.credentials.json"
認証テスト。
$ claude -p 'say hi'
Hi! How can I help you today?
通った。環境変数なしで。
そしてこのファイルにはリフレッシュトークンが含まれている。Claude Codeがアクセストークンの期限切れを検知したら、自動的にリフレッシュトークンで新しいアクセストークンを取得する。
Mac常時起動は不要。cron同期も不要。一度書き込めば、あとはClaude Codeが自己回復する。
教訓
1. 「正しい保存場所」を最初に調べるべきだった
2時間半の大半は、claude auth login を動かす試行錯誤に費やした。最初からClaude Codeのソースコードを読んで .credentials.json を見つけていれば、5分で終わっていた。
「正規のログイン方法」に固執しすぎた。動かないものを動かそうとするより、別の道を探すべきだった。
2. AI自動化の本番運用はインフラ障害との戦い
「Claude Codeで自動化できた!」は入口でしかない。本当に大変なのは、障害時の復旧、トークン管理、プロセス監視、ログ設計。
AIが書いたコードは動く。でも、動き続ける仕組みは人間が設計しないといけない。
3. 手順書は「未来の自分」への投資
今回の経験を復旧手順書にまとめた。次に同じことが起きたら3分で直せる。
2時間半の苦痛は、3分×∞回の時間節約に変わった。これは確実にリターンのある投資だ。
まとめ
| 項目 | 詳細 |
|---|---|
| 問題 | VPS障害後、Claude Codeの認証切れ。ヘッドレス環境で再ログイン不可 |
| 試した方法 | 8種類、全て失敗 |
| 解決方法 | Macのキーチェーンからクレデンシャルを .credentials.json に書き込み |
| 所要時間 | 初回: 2時間半 → 次回: 3分 |
| 根本原因 | claude auth login のヘッドレスフローのバグ(400エラー) |
Claude Codeは驚くほど優秀なツールだ。でも、本番運用で本当に必要なのは、AIの能力ではなく、壊れたときに直せる知識と手順書だと思う。