Fly.io デプロイ

目標:Fly.io マシン上で永続ストレージ、自動 HTTPS、Discord/チャンネルアクセスを備えた OpenClaw Gateway を実行すること。

必要なもの

  • flyctl CLI のインストール
  • Fly.io アカウント(Free Tier で対応可能)
  • モデル認証:選択したモデルプロバイダーの API キー
  • チャンネル認証情報:Discord ボットトークン、Telegram トークンなど

初心者向けクイックパス

  1. リポジトリをクローン → fly.toml をカスタマイズ
  2. アプリ + ボリュームを作成 → シークレットを設定
  3. fly deploy でデプロイ
  4. SSH で接続して設定を作成、またはコントロール UI を使用

1) Fly アプリの作成

# リポジトリのクローン
git clone https://github.com/openclaw/openclaw.git
cd openclaw

# 新しい Fly アプリの作成(任意の名前を指定)
fly apps create my-openclaw

# 永続ボリュームの作成(1GB で通常は十分)
fly volumes create openclaw_data --size 1 --region iad

**ヒント:**近くのリージョンを選択してください。主な選択肢:lhr(ロンドン)、iad(バージニア)、sjc(サンノゼ)。

2) fly.toml の設定

アプリ名と要件に合わせて fly.toml を編集します。

**セキュリティに関する注意:**デフォルトの設定ではパブリック URL が公開されます。パブリック IP なしのハードニングデプロイについては、プライベートデプロイまたは fly.private.toml を参照してください。

app = "my-openclaw"  # アプリ名
primary_region = "iad"

[build]
  dockerfile = "Dockerfile"

[env]
  NODE_ENV = "production"
  OPENCLAW_PREFER_PNPM = "1"
  OPENCLAW_STATE_DIR = "/data"
  NODE_OPTIONS = "--max-old-space-size=1536"

[processes]
  app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]

[[vm]]
  size = "shared-cpu-2x"
  memory = "2048mb"

[mounts]
  source = "openclaw_data"
  destination = "/data"

主要設定:

設定理由
--bind lan0.0.0.0 にバインドし、Fly のプロキシが Gateway に到達可能にする
--allow-unconfigured設定ファイルなしで起動(後で作成)
internal_port = 3000Fly のヘルスチェックのため --port 3000(または OPENCLAW_GATEWAY_PORT)と一致させる
memory = "2048mb"512MB では不足。2GB を推奨
OPENCLAW_STATE_DIR = "/data"ボリュームに状態を永続化

3) シークレットの設定

# 必須:Gateway トークン(非ループバックバインディング用)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)

# モデルプロバイダーの API キー
fly secrets set ANTHROPIC_API_KEY=sk-ant-...

# 任意:その他のプロバイダー
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...

# チャンネルトークン
fly secrets set DISCORD_BOT_TOKEN=MTQ...

注意事項:

  • 非ループバックバインド(--bind lan)にはセキュリティのため OPENCLAW_GATEWAY_TOKEN が必要です。
  • これらのトークンはパスワードと同様に扱ってください。
  • **API キーやトークンはすべて環境変数で管理することを推奨します。**これにより、openclaw.json にシークレットが含まれて意図せず公開やログに記録されるリスクを避けられます。

4) デプロイ

fly deploy

初回デプロイでは Docker イメージのビルドに約 2〜3 分かかります。以降のデプロイはより高速です。

デプロイ後の確認:

fly status
fly logs

以下のように表示されるはずです:

[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx

5) 設定ファイルの作成

SSH でマシンに接続して適切な設定を作成します:

fly ssh console

設定ディレクトリとファイルを作成:

mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-opus-4-6",
        "fallbacks": ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
      },
      "maxConcurrent": 4
    },
    "list": [
      {
        "id": "main",
        "default": true
      }
    ]
  },
  "auth": {
    "profiles": {
      "anthropic:default": { "mode": "token", "provider": "anthropic" },
      "openai:default": { "mode": "token", "provider": "openai" }
    }
  },
  "bindings": [
    {
      "agentId": "main",
      "match": { "channel": "discord" }
    }
  ],
  "channels": {
    "discord": {
      "enabled": true,
      "groupPolicy": "allowlist",
      "guilds": {
        "YOUR_GUILD_ID": {
          "channels": { "general": { "allow": true } },
          "requireMention": false
        }
      }
    }
  },
  "gateway": {
    "mode": "local",
    "bind": "auto"
  },
  "meta": {
    "lastTouchedVersion": "2026.1.29"
  }
}
EOF

注意:OPENCLAW_STATE_DIR=/data を設定した場合、設定ファイルのパスは /data/openclaw.json になります。

**注意:**Discord トークンは以下のどちらからでも取得できます:

  • 環境変数:DISCORD_BOT_TOKEN(シークレット管理に推奨)
  • 設定ファイル:channels.discord.token

環境変数を使用する場合、設定ファイルにトークンを追加する必要はありません。Gateway は DISCORD_BOT_TOKEN を自動的に読み取ります。

再起動して適用:

exit
fly machine restart <machine-id>

6) Gateway へのアクセス

コントロール UI

ブラウザで開く:

fly open

または https://my-openclaw.fly.dev/ にアクセスしてください。

Gateway トークン(OPENCLAW_GATEWAY_TOKEN で設定したもの)を貼り付けて認証します。

ログ

fly logs              # ライブログ
fly logs --no-tail    # 最近のログ

SSH コンソール

fly ssh console

トラブルシューティング

「App is not listening on expected address」

Gateway が 0.0.0.0 ではなく 127.0.0.1 にバインドされています。

修正:fly.toml のプロセスコマンドに --bind lan を追加してください。

ヘルスチェック失敗 / 接続拒否

Fly が設定されたポートで Gateway に到達できません。

修正:internal_port が Gateway のポートと一致しているか確認してください(--port 3000 または OPENCLAW_GATEWAY_PORT=3000 を設定)。

OOM / メモリの問題

コンテナが再起動を繰り返す、または強制終了される場合。兆候:SIGABRTv8::internal::Runtime_AllocateInYoungGeneration、またはサイレントな再起動。

修正:fly.toml でメモリを増やしてください:

[[vm]]
  memory = "2048mb"

既存のマシンを更新する場合:

fly machine update <machine-id> --vm-memory 2048 -y

**注意:**512MB では不足です。1GB では負荷時や冗長ログ出力時に OOM になる可能性があります。2GB を推奨します。

Gateway ロックの問題

Gateway が「already running」エラーで起動を拒否する場合。

コンテナが再起動しても PID ロックファイルがボリューム上に残っていることが原因です。

**修正:**ロックファイルを削除してください:

fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>

ロックファイルは /data/gateway.*.lock にあります(サブディレクトリ内ではありません)。

設定が読み込まれない

--allow-unconfigured を使用している場合、Gateway は最小限の設定を作成します。/data/openclaw.json のカスタム設定は再起動時に読み込まれるはずです。

設定の存在を確認:

fly ssh console --command "cat /data/openclaw.json"

SSH 経由での設定ファイル書き込み

fly ssh console -C コマンドはシェルリダイレクションをサポートしていません。設定ファイルを書き込むには:

# echo + tee を使用(ローカルからリモートへパイプ)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"

# または sftp を使用
fly sftp shell
> put /local/path/config.json /data/openclaw.json

**注意:**ファイルが既に存在する場合、fly sftp が失敗することがあります。まず削除してください:

fly ssh console --command "rm /data/openclaw.json"

状態が永続化されない

再起動後に認証情報やセッションが失われる場合、状態ディレクトリがコンテナファイルシステムに書き込まれています。

修正:fly.tomlOPENCLAW_STATE_DIR=/data が設定されていることを確認して再デプロイしてください。

アップデート

# 最新の変更を取得
git pull

# 再デプロイ
fly deploy

# ヘルスチェック
fly status
fly logs

マシンコマンドの更新

フルの再デプロイなしで起動コマンドを変更する必要がある場合:

# マシン ID の取得
fly machines list

# コマンドの更新
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y

# メモリ増加と組み合わせる場合
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y

注意:fly deploy 後、マシンコマンドが fly.toml の内容にリセットされることがあります。手動で変更した場合は、デプロイ後に再度適用してください。

プライベートデプロイ(ハードニング)

デフォルトでは Fly がパブリック IP を割り当てるため、Gateway は https://your-app.fly.dev でアクセス可能になります。便利ですが、インターネットスキャナー(Shodan、Censys など)からデプロイが発見可能であることを意味します。

パブリック公開なしのハードニングデプロイには、プライベートテンプレートを使用してください。

プライベートデプロイを使用すべき場面

  • アウトバウンドの通話/メッセージのみ行う場合(インバウンド Webhook なし)
  • Webhook コールバックに ngrok や Tailscale トンネルを使用する場合
  • SSH、プロキシ、または WireGuard 経由で Gateway にアクセスする場合
  • デプロイをインターネットスキャナーから隠したい場合

セットアップ

標準の設定の代わりに fly.private.toml を使用:

# プライベート設定でデプロイ
fly deploy -c fly.private.toml

既存のデプロイを変換する場合:

# 現在の IP を一覧表示
fly ips list -a my-openclaw

# パブリック IP を解放
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw

# プライベート設定に切り替え(以降のデプロイでパブリック IP が再割り当てされない)
# ([http_service] を削除するか、プライベートテンプレートでデプロイ)
fly deploy -c fly.private.toml

# プライベート専用 IPv6 を割り当て
fly ips allocate-v6 --private -a my-openclaw

この後、fly ips list には private タイプの IP のみ表示されるはずです:

VERSION  IP                   TYPE             REGION
v6       fdaa:x:x:x:x::x      private          global

プライベートデプロイへのアクセス

パブリック URL がないため、以下のいずれかの方法を使用します:

方法 1:ローカルプロキシ(最もシンプル)

# ローカルポート 3000 をアプリに転送
fly proxy 3000:3000 -a my-openclaw

# ブラウザで http://localhost:3000 を開く

方法 2:WireGuard VPN

# WireGuard 設定を作成(初回のみ)
fly wireguard create

# WireGuard クライアントにインポートし、内部 IPv6 でアクセス
# 例:http://[fdaa:x:x:x:x::x]:3000

方法 3:SSH のみ

fly ssh console -a my-openclaw

プライベートデプロイでの Webhook

パブリック公開なしで Webhook コールバック(Twilio、Telnyx など)が必要な場合:

  1. ngrok トンネル - コンテナ内またはサイドカーとして ngrok を実行
  2. Tailscale Funnel - Tailscale で特定のパスを公開
  3. アウトバウンド専用 - 一部のプロバイダー(Twilio)はアウトバウンド通話で Webhook なしでも動作

ngrok を使った音声通話設定の例:

{
  "plugins": {
    "entries": {
      "voice-call": {
        "enabled": true,
        "config": {
          "provider": "twilio",
          "tunnel": { "provider": "ngrok" },
          "webhookSecurity": {
            "allowedHosts": ["example.ngrok.app"]
          }
        }
      }
    }
  }
}

ngrok トンネルはコンテナ内で実行され、Fly アプリ自体を公開せずにパブリックな Webhook URL を提供します。転送されたホストヘッダーが受け入れられるように、webhookSecurity.allowedHosts にパブリックトンネルのホスト名を設定してください。

セキュリティ比較

項目パブリックプライベート
インターネットスキャナー発見可能隠蔽
直接攻撃可能ブロック
コントロール UI アクセスブラウザプロキシ/VPN
Webhook 配信直接トンネル経由

注意事項

  • Fly.io は x86 アーキテクチャを使用(ARM ではない)
  • Dockerfile は両アーキテクチャに対応
  • WhatsApp/Telegram のオンボーディングには fly ssh console を使用
  • 永続データはボリュームの /data に保存
  • Signal には Java + signal-cli が必要。カスタムイメージを使用し、メモリは 2GB 以上を確保してください。

コスト

推奨設定(shared-cpu-2x、2GB RAM)の場合:

  • 使用状況によって約 $10〜15/月
  • Free Tier に一定の無料枠あり

詳細は Fly.io の料金を参照してください。