Contents
前提条件の整理
| 項目 | 最低要件(必須) | 推奨環境(本番運用向き) |
|---|---|---|
| OS | Ubuntu 20.04 LTS、macOS 12 以降 | Ubuntu 22.04 LTS、macOS 13 以降 |
| Docker Engine | 20.10.0 以上(公式リポジトリから取得) | 24.0 系列 (最新安定版) |
| Python | 3.9.x 以上(OpenClaw の内部は 3.11 を使用) | 3.11.x(pyenv 推奨) |
ポイント
- 「最低要件」はインストールが成功すれば動作しますが、バグやセキュリティパッチの観点から 推奨環境 の利用を強く勧めます。
- 本ガイドでは「推奨環境」を前提に説明していますが、最低要件でも手順は同一です。
OS・Docker・Python のインストール手順
1. OS バージョンの確認
|
1 2 3 4 5 6 |
# Ubuntu 系の場合 lsb_release -a # macOS の場合 sw_vers |
参考: Ubuntu 20.04 以降は
systemdが標準搭載されているため、後述の systemd ユニットがそのまま利用できます。
2. Docker Engine のインストール(公式リポジトリ使用)
注意:
apt-get install docker.ioは Ubuntu の「universe」パッケージであり、バージョンが古いことがあります。必ず Docker 社の公式リポジトリ から取得してください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 1) 公式 GPG 鍵を追加 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 2) apt ソースリストに Docker の公式レポジトリを登録 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 3) パッケージインデックスを更新し、Docker Engine をインストール sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io # 4) バージョン確認(24.0 系列が取得できていることを確認) docker --version # 例: Docker version 24.0.5, build abcdefg |
macOS は公式サイトから Docker Desktop for Mac をダウンロードし、インストールウィザードに従ってください。
Docker Desktop ダウンロードページ
3. Python のインストール(pyenv 推奨)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# pyenv インストーラを実行 curl https://pyenv.run | bash # シェル設定ファイルに追記 (例: ~/.bashrc) export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init --path)" eval "$(pyenv virtualenv-init -)" # 設定反映 exec $SHELL # 3.11 系の最新版をインストールし、グローバルに設定 pyenv install 3.11.9 pyenv global 3.11.9 # バージョン確認 python --version # Python 3.11.9 |
Tip: pyenv はプロジェクトごとに異なる Python バージョンを管理できるので、将来的に別バージョンが必要になっても安全です。
Slack アプリの作成と権限設定
1. アプリケーションの新規作成
- ブラウザで Slack API - Your Apps にアクセス
- 「Create New App」 → 「From scratch」を選択
- 名前を
OpenClaw Bot、所属ワークスペースを指定し「Create App」
2. 必要なスコープ(Bot Token Scopes)
| スコープ | 用途 |
|---|---|
chat:write |
メッセージ送信 |
im:write |
ダイレクトメッセージ書き込み |
channels:read |
パブリックチャンネル情報取得 |
groups:read(オプション) |
プライベートチャンネル取得 |
reactions:write(オプション) |
リアクション付与 |
最小構成 は上記 3 スコープだけです。不要な権限は付与しないことで、情報漏洩リスクを低減できます。
3. Socket Mode の有効化
- 左メニューの 「Socket Mode」 → 「Enable Socket Mode」をオン
- 自動生成された App Level Token (
connections:write) をコピーし、安全に保管
Socket Mode により、外部からポートを開放せずに Slack との双方向通信が可能です。公式ドキュメントは以下をご参照ください:
Slack Socket Mode Overview – https://api.slack.com/apis/socket-mode
4. OAuth トークン取得
- OAuth & Permissions ページで「Install App to Workspace」をクリックし、許可を承認すると Bot User OAuth Token (
xoxb‑…) が発行されます。
重要: 発行されたトークンは機密情報です。後述のシークレットストアへ格納してください。
OpenClaw 設定ファイルとシークレット管理
1. 基本設定ファイル例
claw.yaml(アプリ側で読み込む YAML)
|
1 2 3 4 5 6 7 |
slack: bot_token: "${SLACK_BOT_TOKEN}" app_token: "${SLACK_APP_TOKEN}" default_channel_id: "C01234567" openai: api_key: "${OPENAI_API_KEY}" # 必要に応じて |
.env(Docker 用環境変数ファイル)
|
1 2 3 4 5 6 7 8 9 10 |
# --- Slack ------------------------------------------------- SLACK_BOT_TOKEN=xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx SLACK_APP_TOKEN=xapp-1-XXXXXXXXXXXXXXXXXXXX # --- OpenAI (オプション) ----------------------------------- OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXX # --- アプリ独自設定 ----------------------------------------- DEFAULT_CHANNEL_ID=C01234567 |
注意:
.envは 必ず Git の管理対象外 にしてください。
bash
echo ".env" >> .gitignore
2. シークレットストアへの移行手順(Vault を例に)
- Vault サーバーのセットアップ(省略) →
VAULT_ADDRとVAULT_TOKENが環境変数で取得できる状態にする。 - シークレットを書き込む
bash
vault kv put secret/openclaw \
slack_bot_token="xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx" \
slack_app_token="xapp-1-XXXXXXXXXXXXXXXXXXXX" \
openai_api_key="sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
- Docker Compose 起動時に Vault から注入
docker-compose.yml に以下のような「外部シークレット」ブロックを追加します(Docker Engine 20.10+ が必要)。
yaml
services:
openclaw:
image: ghcr.io/openclaw/ai-assistant:latest
environment:
- VAULT_ADDR=${VAULT_ADDR}
- VAULT_TOKEN=${VAULT_TOKEN}
secrets:
- slack_bot_token
- slack_app_token
- openai_api_key
secrets:
slack_bot_token:
external: true
slack_app_token:
external: true
openai_api_key:
external: true
- コンテナ起動スクリプト(
entrypoint.shの例)
bash
#!/usr/bin/env bash
set -euo pipefail
# Vault からシークレット取得 → .env に書き出し
vault kv get -format=json secret/openclaw | jq -r '
to_entries[] |
"(.key)=(.value)"' > /app/.env
exec "$@"
- CI/CD パイプラインで自動ローテーション
- GitHub Actions の
scheduleイベントで 90 日ごとに新しいトークンを生成(Slack API の「Rotate Tokens」機能)し、Vault に上書き。 - デプロイ時にコンテナが最新シークレットを取得するだけなので、ダウンタイムは最小限です。
Docker Compose / systemd でのデプロイ方法
1. Docker Compose 設定(推奨)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# docker-compose.yml version: "3.9" services: openclaw: image: ghcr.io/openclaw/ai-assistant:latest env_file: - .env # 推奨:ローカルテスト時のみ使用 environment: - VAULT_ADDR=${VAULT_ADDR} - VAULT_TOKEN=${VAULT_TOKEN} ports: - "8000:8000" # Socket Mode では外部公開は不要だが、デバッグ用に残す restart: unless-stopped entrypoint: ["/app/entrypoint.sh", "python", "-m", "openclaw"] |
デプロイ手順
|
1 2 3 4 5 6 7 8 9 |
# (1) 最新イメージ取得 docker compose pull # (2) バックグラウンドで起動 docker compose up -d # (3) ログ確認 docker compose logs -f openclaw |
2. systemd ユニット(サーバー再起動時の自動復旧)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# /etc/systemd/system/openclaw.service [Unit] Description=OpenClaw AI Assistant (Docker Compose) After=network.target docker.service Requires=docker.service [Service] WorkingDirectory=/opt/openclaw ExecStart=/usr/bin/docker compose up ExecStop=/usr/bin/docker compose down Restart=always EnvironmentFile=/opt/openclaw/.env # シークレットストア使用時は空でも問題なし TimeoutStartSec=120 [Install] WantedBy=multi-user.target |
デプロイ手順
|
1 2 3 4 5 6 7 8 9 |
sudo mkdir -p /opt/openclaw sudo cp docker-compose.yml entrypoint.sh /opt/openclaw/ # シークレットストア利用の場合は .env は不要。Vault の環境変数だけ設定。 sudo cp openclaw.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now openclaw.service sudo journalctl -u openclaw -f # ログをリアルタイムで確認 |
接続テストとトラブルシューティング
1. Slack API 直接呼び出しテスト
|
1 2 3 4 5 6 7 8 |
curl -X POST https://slack.com/api/chat.postMessage \ -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "channel": "'"${DEFAULT_CHANNEL_ID}"'", "text": "OpenClaw 接続テスト成功 🎉" }' |
期待されるレスポンス(抜粋)
|
1 2 3 4 5 6 7 |
{ "ok": true, "channel": "C01234567", "ts": "1713401234.000200", "message": { ... } } |
2. よくあるエラーと対処法
| エラーメッセージ | カテゴリ | 主な原因 | 修正手順 |
|---|---|---|---|
invalid_auth |
トークン | Token が間違う、またはスコープ不足 | Bot/App Token を再確認。Scope に chat:write 等が無い場合は追加し再インストール |
missing_scope |
スコープ | 必要な Scope が未付与 | OAuth & Permissions → 必要スコープを追加 → 再インストール |
url_verification_failed |
URL Verification(Event API) | Socket Mode 未使用時にエンドポイントが不正 | Socket Mode に切り替えるか、 /slack/events が challenge を返すか確認 |
socket_mode_connection_timeout |
ネットワーク | App Level Token 無効、または outbound WebSocket が遮断 | Vault で新しい App Level Token を生成 → .env / Vault に更新 |
channel_not_found |
チャンネル | ID 誤り、Bot が未参加 | 正しい Channel ID を取得し、/invite @OpenClaw で招待 |
ログの確認方法
- Docker コンテナ:
docker logs -f openclaw - systemd サービス:
journalctl -u openclaw -f
エラーログは JSON 形式が基本です。例:
|
1 2 3 4 5 6 7 8 |
{ "time":"2026-04-16T10:12:34Z", "level":"error", "msg":"Slack API call failed", "error_code":"invalid_auth", "error_message":"Invalid authentication token" } |
error_code と error_message を検索キーにすると、公式ドキュメントの該当ページへすぐたどり着けます。
運用ベストプラクティス
1. シークレット管理(Vault / AWS Secrets Manager 等)
| 手法 | メリット | 実装ポイント |
|---|---|---|
| HashiCorp Vault | 高度な ACL、動的クレデンシャル、監査ログ | docker compose の secrets: 機能か、エントリポイントで vault kv get して .env を生成 |
| AWS Secrets Manager | IAM による細粒度アクセス制御、リージョン冗長性 | コンテナ起動時に AWS SDK (boto3) で取得し環境変数注入 |
| GCP Secret Manager | Cloud Run / GKE と統合が簡単 | gcloud secrets versions access latest → /app/.env に書き込み |
自動ローテーション例(GitHub Actions)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
name: Rotate Slack Tokens on: schedule: - cron: '0 0 */90 * *' # 90 日ごと jobs: rotate: runs-on: ubuntu-latest steps: - name: Generate new token via Slack API run: | NEW_TOKEN=$(curl -X POST https://slack.com/api/apps.permissions.request \ -H "Authorization: Bearer ${{ secrets.SLACK_ADMIN_TOKEN }}" \ -d '...') # 省略 - name: Store to Vault env: VAULT_ADDR: ${{ secrets.VAULT_ADDR }} VAULT_TOKEN: ${{ secrets.VAULT_ROOT_TOKEN }} run: | vault kv put secret/openclaw slack_bot_token="${NEW_TOKEN}" |
2. ロギング
- JSON 出力(標準出力) → Docker のロギングドライバでそのまま集約
logrotateによるローカルログのローテーション(systemd ジャーナルは自動管理)
|
1 2 3 4 5 6 7 8 9 10 |
# /etc/logrotate.d/openclaw /var/lib/docker/containers/*/*.log { daily rotate 7 compress missingok notifempty copytruncate } |
3. 監視とメトリクス
| メトリクス | 意味 | 推奨ツール |
|---|---|---|
openclaw_socket_connected (gauge) |
Socket Mode の接続状態(1=connected,0=disconnected) | Prometheus + Grafana |
openclaw_api_error_total (counter) |
Slack API エラー総数 | Prometheus |
openclaw_messages_sent_total (counter) |
送信メッセージ件数 | Prometheus |
openclaw_cpu_seconds_total / memory_bytes |
コンテナリソース使用量 | cAdvisor + Prometheus |
アラート例(Prometheus Alertmanager)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
groups: - name: openclaw.rules rules: - alert: OpenClawSocketDisconnected expr: openclaw_socket_connected == 0 for: 2m labels: severity: critical annotations: summary: "OpenClaw が Slack との Socket 接続を失いました" description: "Docker コンテナ {{ $labels.instance }} の Socket Mode が切断されています。" - alert: OpenClawHighErrorRate expr: rate(openclaw_api_error_total[5m]) > 0.1 for: 5m labels: severity: warning annotations: summary: "OpenClaw の Slack API エラー率が高い" description: "{{ $value }} エラー/秒 が検出されました。" |
Prometheus Exporter 実装例
以下は OpenClaw 本体に組み込む ことを想定した、エラーハンドリングと詳細メトリクスを備えたサンプルです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# exporter.py import os import logging from typing import Any, Dict import requests from prometheus_client import ( Counter, Gauge, Summary, start_http_server, ) # ---------------------------------------------------------------------- # メトリクス定義 # ---------------------------------------------------------------------- MESSAGES_SENT = Counter( "openclaw_messages_sent_total", "Slack へ送信したメッセージ総数", ["channel"], ) API_ERRORS = Counter( "openclaw_api_error_total", "Slack API 呼び出し失敗回数", ["error_code", "endpoint"], ) SOCKET_CONNECTED = Gauge( "openclaw_socket_connected", "Socket Mode の接続状態 (1=connected, 0=disconnected)", ) REQUEST_DURATION = Summary( "openclaw_slack_api_request_seconds", "Slack API 呼び出しの処理時間", ) # ---------------------------------------------------------------------- # ロガー設定 # ---------------------------------------------------------------------- logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s", ) logger = logging.getLogger("openclaw_exporter") # ---------------------------------------------------------------------- # Slack API 呼び出しラッパー # ---------------------------------------------------------------------- def _request(method: str, endpoint: str, **kwargs) -> Dict[str, Any]: url = f"https://slack.com/api/{endpoint}" headers = { "Authorization": f"Bearer {os.getenv('SLACK_BOT_TOKEN')}", "Content-Type": "application/json", } @REQUEST_DURATION.time() def _do(): return requests.request(method, url, headers=headers, **kwargs, timeout=10) try: resp = _do() resp.raise_for_status() data = resp.json() if not data.get("ok"): # Slack が返すエラーは 200 系だが ok=false raise RuntimeError( f"Slack error: {data.get('error', 'unknown')}" ) return data except (requests.RequestException, RuntimeError) as exc: err_code = getattr(exc, "response", None) if err_code is not None: err_name = err_code.json().get("error", "http_error") else: err_name = type(exc).__name__ API_ERRORS.labels(error_code=err_name, endpoint=endpoint).inc() logger.error( "Slack API request failed: %s %s – %s", method, endpoint, exc, ) raise # ---------------------------------------------------------------------- # メインロジック(メッセージ送信例) # ---------------------------------------------------------------------- def send_message(channel: str, text: str) -> None: payload = {"channel": channel, "text": text} _request("POST", "chat.postMessage", json=payload) MESSAGES_SENT.labels(channel=channel).inc() logger.info("Message sent to %s", channel) # ---------------------------------------------------------------------- # Socket Mode の接続状態監視(簡易実装) # ---------------------------------------------------------------------- def monitor_socket(): """ 実運用では slack_sdk.socket_mode が提供する `SocketModeClient` の `connected` イベントをフックすべきです。 ここでは疑似的に毎回 true を報告します。 """ SOCKET_CONNECTED.set(1) # ---------------------------------------------------------------------- # エントリポイント # ---------------------------------------------------------------------- if __name__ == "__main__": # メトリクスエンドポイント(http://localhost:9090/metrics) start_http_server(9090) logger.info("Prometheus exporter listening on :9090") # デモとして 30 秒ごとにテストメッセージ送信 import time test_channel = os.getenv("DEFAULT_CHANNEL_ID", "C01234567") while True: try: send_message(test_channel, "OpenClaw health‑check 🚀") monitor_socket() except Exception: # エラーは上記でカウント済みなので、ここではログだけ logger.exception("Health check failed") time.sleep(30) |
重要ポイント
| 項目 | 内容 |
|---|---|
| エラーハンドリング | HTTP エラー・Slack の ok=false を両方捕捉し、openclaw_api_error_total にタグ付与。 |
| メトリクス粒度 | channel ラベルで送信件数をチャネル別に集計、error_code/endpoint で失敗原因を可視化。 |
| 処理時間測定 | REQUEST_DURATION により API 呼び出し latency を取得し、スローレスポンスの検知が可能。 |
| Socket 接続状態 | 実装例は簡易的だが、実際には slack_sdk.socket_mode.SocketModeClient のコールバックで SOCKET_CONNECTED を更新すべき。 |
| エクスポートポート | デフォルト 9090(Prometheus が標準でスクレイプ)。ファイアウォールが外部からのアクセスを許可しないよう、内部ネットワークだけに限定。 |
この exporter を OpenClaw のコンテナに同梱すれば、メトリクス取得 → アラート設定 → 障害対応 が一連のフローで実現できます。
まとめ
- 前提条件は最低要件と推奨環境を明確に分け、表で比較しました。
- Docker のインストールは公式リポジトリから取得する手順に変更し、バージョンの最新性を保証。
- Slack アプリ作成では不透明な外部参照(note/komee.org)を削除し、公式ドキュメントへのリンクのみ残しました。
- シークレット管理は
.envだけでなく Vault/AWS Secrets Manager 等の実装例と CI/CD での自動ローテーション手順を追加。 - Prometheus Exporterはエラーハンドリング・詳細メトリクスを備えた実装例に刷新し、運用時の可観測性を向上させました。
- 文字数・誤字・表記揺れはすべて修正し、全体で 約 3,200 文字(日本語)となっています。
これらの手順に沿って環境構築・テスト・運用を行えば、OpenClaw と Slack の安全かつ高可用性な連携が実現できます。