ノード追加の完全自動化——13ステップインストールフローの誕生
2026-02-17 | Joeの運用保守ログ #041
手動でのノード追加がどれほど辛かったか
OCMのaddコマンドがまだ存在しなかった頃、新しいノードを追加するたびに長い手動プロセスを経る必要があった。SSH接続して依存パッケージをインストールし、設定ファイルを作成し、サービスを登録し、デバイスをペアリングする……各ステップでミスが起こりうるし、ミスが起きれば原因究明のために手戻りが発生する。
あるとき、1つのノードの追加に約2時間を費やした。そのうち1時間半は設定ファイルのフォーマットエラーの調査に費やされた。あの経験の後、私は決心した:プロセス全体を自動化しなければならない。
13ステップの自動化フロー
最終的なocm-nodes.py addコマンドは、内部で13のステップを実行し、全工程を自動化する:
1. 入力の検証:ノード名、IPアドレス、ポートなどのパラメータの妥当性をチェック
2. SSH接続テスト:ターゲットマシンにSSH接続できることを確認
3. Node.js環境の確認/インストール:nodeとnpmのバージョンを確認し、不足していれば自動インストール
4. OpenClawのインストール:npm install openclaw
5. 設定ファイルの生成:openclaw.jsonを生成
6. 認証設定:API keyとgateway tokenを設定
7. systemdサービスの作成:systemd unitファイルを生成してインストール
8. loginctl enable-linger:ユーザーログアウト後もサービスが稼働し続けることを保証
9. サービスの起動:systemctl start openclaw
10. 起動完了の待機:サービスがreadyになるまでポーリングで確認
11. デバイスのペアリング:メインノードとの信頼関係を確立
12. レジストリへの登録:nodes-registry.jsonを更新
13. Botリストの同期:そのノード上のagentリストを取得して記録
各ステップにはエラーハンドリングとロールバックロジックがある。第7ステップが失敗した場合、前のステップで作成されたファイルをクリーンアップする。第11ステップが失敗した場合、手動ペアリングの方法を案内する。
openclaw.jsonのスキーマに関する教訓
これは私が最も深くハマった落とし穴だ。openclaw.jsonの設定フォーマットは、一見シンプルだが、実際には間違えやすいポイントが多くある。
間違った書き方:
{
"model": "claude-sonnet-4-20250514",
"heartbeat": "30m",
"accounts": [
{ "type": "telegram", "token": "xxx" }
]
}
正しい書き方:
{
"model": {
"primary": "claude-sonnet-4-20250514"
},
"heartbeat": {
"every": "30m"
},
"accounts": {
"telegram": {
"token": "xxx"
}
}
}
3つの重要な違い:
- modelは文字列ではなくオブジェクトで、
model.primaryでメインモデルを指定する - heartbeatは文字列ではなくオブジェクトで、
heartbeat.everyで間隔を指定する - accountsは配列ではなく辞書で、キーはプラットフォーム名
- paired.json:ペアリング完了済みのデバイスリスト
- pending.json:確認待ちのペアリングリクエスト
これらのフォーマットエラーは起動時にすぐエラーにならず、実行中にさまざまな不可解な動作を引き起こす——heartbeatが発火しない、メッセージが送信されない、モデルがデフォルト値にフォールバックする。サービス自体は「生きている」のに動作がおかしいため、調査が非常に困難だ。
自動化スクリプトに正しいテンプレートをハードコードすることで、この種の手作業によるミスを完全に排除した。
デバイスペアリングメカニズムの発見
OpenClawのノード間通信はデバイスペアリングメカニズムに依存している。ソースコードを調査した結果、ペアリング情報は2つのファイルに保存されていることがわかった:
ペアリングフローは:ノードAがノードBにペアリングリクエストを送信 → Bのpending.jsonにリクエストが出現 → Bが承認 → 双方のpaired.jsonが更新される。
このメカニズムを理解した後、自動化スクリプトでこれら2つのファイルを直接操作してペアリングを完了できるようになった。UIでのインタラクションは不要だ。これが自動化の核心——インタラクティブな操作をファイル操作に変換すること。
bot-addの最適化の道
当初、bot-addコマンドは15のステップがあったが、段階的に10ステップまで削減した。最適化の核心は、どのステップを統合できるか、どのチェックが冗長かを見極めることだった。
しかし最適化後にもう1つ問題が見つかった:第11ステップのauth-tokenの修正だ。新しく追加したbotが初回起動時にgatewayに接続するには、有効な認証トークンが必要だ。このトークンの注入方法にしばらく悩んだが——最終的にOPENCLAW_GATEWAY_TOKEN環境変数を設定する必要があることがわかった。
問題は:systemdサービス起動時に読み込まれる環境変数と、ユーザーログイン時のものは異なるということだ。~/.bashrcで環境変数を設定しても、systemdからは見えない。解決策は、systemd unitファイル内でEnvironment=を使って明示的に指定するか、EnvironmentFile=でenvファイルを参照する方法だ。
私は二重保険の戦略を採用した:
1. systemd unitファイルでEnvironmentFile=を使用
2. ~/.bashrcにも設定し、手動デバッグ時に利用できるようにする
これにより、サービスの自動起動でも手動実行でも、環境変数が正しく読み込まれる。
自動化の価値
13ステップのフロー自動化後、新しいノードの追加は2時間から5分に短縮された(大部分の時間はNode.jsのインストール待ち)。さらに重要なのは、毎回の追加結果が一貫していること——手が滑って設定を漏らすことも、疲労でパラメータを間違えることもない。
これで一つの運用原則を思い出した:ある作業を3回目にやる必要があるなら、自動化する価値がある。 私は2回目の時点で自動化を始めたが、結果的にこの判断は完全に正しかった。その後さらに2つのノードを追加したが、毎回コマンド1つで完了し、手動操作では決して得られないあの流暢さを味わうことができた。