Lchiki-Lab
arrow_backBack to Archive

Google Colab×​Ollama×​Cloudflareで構築する「完全無料・URL固定型」AIフェイルオーバー環境

calendar_today2026.07.26folderTechnology
Cookie Cat

Claude Code や ChatGPT Pro でノリノリで作業している最中、突然「Usage Limit(利用制限)」で手が止まったことはないかな?

今回は、Google Colab×​Ollama×​Cloudflare Tunnelを組み合わせた、完全無料&URL固定型のAIフェイルオーバー(予備機)環境の構築手順を解説するよ!


1. 開発の​壁と​従来の​無料代替案の​限界

メインAIを活用した開発・執筆現場では、本来抱えていた開発上の課題と、無料代替環境を構築・運用しようとした際に直面する技術的課題の2つのレイヤーが存在します。

本来の​課題​(開発現場での​ボトルネック)

① 利用制限​(Usage Limit)に​よる​作業の​強制中断

Claude CodeやChatGPT Proなどの最高峰モデルは極めて強力ですが、高頻度で試行錯誤を繰り返すとすぐにトークン上限に達し、作業が強制ストップしてしまいます。

② 追加コストへの​心理的ハードル

制限を回避するために有料APIを従量課金で追加利用すると、思わぬ出費に繋がります。できれば 「完全無料の範囲」 で同等の代替環境を作りたいところです。

従来の​無料代替案で​直面する​課題​(技術・運用上の​ボトルネック)

③ 毎回​URLを​更新する​手間​(Quick Tunnelの​限界)

無料の代替環境としてGoogle ColabとOllamaを組み合わせる際、ランダムURLを発行する Quick Tunnel(trycloudflare.com)を使うと、Colabを再起動するたびに VS Code(Roo Code等)や Aider, Cherry Studio の Base URL を設定し直す必要がありました。


2. 全体​像:登場する​3つの​要素

これらの課題を解決するため、独自ドメインを活用した 固定URL(例: https://ai.example.com/v1 によるバックアップ環境を定義します。

laptop_mac
ローカルPC
VS Code / Aider CLI / Cherry Studio 等

https://ai.example.com/v1 (固定URL)

arrow_downward
cloud_sync
Cloudflare Named Tunnel
固定アドレスの窓口(URL固定化)
arrow_downward
memory
Google Colab (無料T4 GPU)
Ollama + Qwen3.5 9B (推論処理)
  • Cloudflare:変わらない「固定の看板(URL)」を出してくれる窓口
  • Google Colab:バックグラウンドでQwen3.5 9Bを動かす「計算機」
  • ローカルPC:実際に指示を出す「手元のアプリ(VS Code, Aider, Cherry Studio等)」
本アプローチの3大メリット
  1. Colab再起動時のURL貼り替え作業が不要(0回): Base URLはずっと https://ai.example.com/v1 のまま固定。
  2. Cloudflareの403エラーでブロックされない: 権限のある正規のNamed Tunnelとして通信。
  3. 自分専用の固定サブドメインでAPI化: 普段使っているクライアント(VS Code / Aider / Cherry Studio等)の接続設定を二度と変更する必要がありません。

3. 最適な​テクノロジー選定

検証を重ねた結果、最も手軽で強力な組み合わせとして以下の構成を導き出しました。

要素最適な選定選定の理由
実行基盤Google Colab (無料T4 GPU)VRAM 15GBが無料で使え、「制限時だけ起動する」オンデマンド利用と相性抜群。
推論エンジンOllamaOpenAI互換(/v1)やAnthropic互換APIを提供。モデル管理が圧倒的に楽。
モデルQwen3.5シリーズ (qwen3.5:9b 等)高い日本語精度とコード生成能力を誇り、用途に応じてモデル切り替えも自由自在。
接続方式Cloudflare Named Tunnel独自ドメインに紐づけた固定URLを提供し、Colab再起動時もクライアント側の設定変更が不要。

4. Phase 1:初回のみの​完全セットアップ​(全4​ステップ)

初期構築時は、「Cloudflare」と「Google Colab」の画面を交互に操作して進める(約3分・初回のみ) 点が最大のポイントです。

【Step 1】 Cloudflare: トンネル新規作成 ➔ Debianを選択して Token(eyJ...)をコピー
     ↓ (Cloudflareの画面を開いたまま維持)
【Step 2】 Google Colab: コード実行 ➔ コピーしたTokenを貼り付けてコネクタ起動!
     ↓
【Step 3】 Cloudflare: タブに戻り「Next」をクリック ➔ ドメイン(公開アプリケーション)を設定して保存
     ↓
【Step 4】 ローカルPC: 手元アプリ(VS Code / Aider CLI / Web UI)に固定URLを設定!

Step 1. Cloudflare側:トンネルの​「枠組み」を​作成する

  1. Cloudflare Dashboard にログインし、左メニューから 「ネットワーク」 ➔ 「Tunnels」 を開きます。
  2. 「トンネルを作成」 をクリックします。 CloudflareのTunnels画面から「トンネルを作成」をクリック
  3. トンネル名(例: colab-qwen など自分が識別できる名前)を入力し、青色の 「トンネル作成」 ボタンをクリックします。 トンネル作成画面でトンネル名を入力しトンネル作成を押す
  4. トンネル作成後の「環境設定(Install connector)」画面で、OSに 「Debian」(アーキテクチャ: 64-bit)を選択します。(※Colabの実行環境であるLinux/Debianに合わせて選択します) 環境設定でDebianを選択してトークンを取得
  5. 画面に表示されたコマンドの中から eyJ... から始まる非常に長い英数字の文字列(トークン)だけ をコピーして手元にメモします。
なぜここで一度止まるの?

Cloudflareは「トンネルの口」を用意しただけで、まだ向こう側(Colab)から誰も接続しに来ていないため、「接続待機中」のまま右下の「Next」ボタンが押せなくなります。そのため、一旦Cloudflareのタブを開いたままColabへ移動します。


Step 2. Colab側:コードを​実行して​トンネルを​一時起動する

Google Colab側でGPU環境を用意し、先ほど取得したTokenを渡してコネクタ(cloudflared)を立ち上げます。

  1. Google Colabで新しいノートブックを作成し、「ランタイム」 ➔ 「ランタイムのタイプを変更」「T4 GPU」 を選択して保存します。 Google Colabの新規ノートブック作成 ランタイムのタイプ変更でT4 GPUを選択
  2. セルに以下の統合Pythonスクリプトを貼り付け、コード先頭の PUBLIC_URL をご自身のドメインURL(例: https://ai.example.com)に書き換えて再生ボタンを押します。
  3. 実行が進み、セクション9で Cloudflare Tunnel Token: の入力ボックスが表示されたら、Step 1でメモした eyJ... のトークンを貼り付けてEnterを押します。 Colabのトークン入力画面でコピーしたトークンを貼り付けて実行
  4. ログに [OK] Cloudflare Named Tunnelプロセス起動 と表示されればOKです!
これで何が起きた?

Colab側からCloudflareに向けて「繋がったよ!」と合図が送られました。

code 統合Pythonスクリプトを表示(1セルで実行可能)

expand_more
# ============================================================
# Google Colab: Ollama + Qwen3.5 9B + Cloudflare Named Tunnel
#
# 事前準備 (Cloudflare Dashboard):
# 1. ネットワーク -> Tunnels で Tunnel を作成
# 2. Public Hostname 設定 (例: ai.example.com -> http://127.0.0.1:11434)
# 3. Tunnel Token をコピー
# ============================================================

# 0. 設定 (※ご自身のドメイン・使いたいモデルに変更してください)
MODEL = "qwen3.5:9b"
OLLAMA_HOST = "0.0.0.0:11434"
OLLAMA_LOCAL_URL = "http://127.0.0.1:11434"
PUBLIC_URL = "https://ai.example.com"  # ご自身のドメインURLに書き換え

# 1. GPU確認
print("=" * 70 + "\n1. GPU確認\n" + "=" * 70)
!nvidia-smi

# 2. 必要なパッケージ・ツールのインストール
print("\n" + "=" * 70 + "\n2. 必要なツールをインストール\n" + "=" * 70)
!apt-get update -qq && apt-get install -y -qq zstd > /dev/null
print("Ollamaをインストール中...")
!curl -fsSL https://ollama.com/install.sh | sh
print("\ncloudflaredをインストール中...")
!curl -L -s https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
!chmod +x /usr/local/bin/cloudflared
print("[OK] インストール完了")

# 3. バージョン確認
print("\n" + "=" * 70 + "\n3. バージョン確認\n" + "=" * 70)
!ollama --version
print()
!cloudflared --version

# 4. 既存プロセス整理
print("\n" + "=" * 70 + "\n4. 既存プロセスを整理\n" + "=" * 70)
import subprocess, time, requests, json, os, getpass
subprocess.run(["pkill", "-f", "ollama serve"], capture_output=True)
subprocess.run(["pkill", "-f", "cloudflared"], capture_output=True)
time.sleep(2)
print("[OK] 既存プロセス整理完了")

# 5. Ollama起動
print("\n" + "=" * 70 + "\n5. Ollama起動\n" + "=" * 70)
ollama_env = os.environ.copy()
ollama_env["OLLAMA_HOST"] = OLLAMA_HOST
ollama_env["OLLAMA_ORIGINS"] = "*"
ollama_process = subprocess.Popen(["ollama", "serve"], env=ollama_env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)

print("Ollama API起動を待っています...")
ollama_ready = False
for i in range(60):
    try:
        if requests.get(f"{OLLAMA_LOCAL_URL}/api/tags", timeout=2).status_code == 200:
            ollama_ready = True
            print("[OK] Ollama API起動成功")
            break
    except Exception:
        pass
    time.sleep(1)

if not ollama_ready:
    raise RuntimeError("Ollama APIを起動できませんでした")

# 6. モデル確認・ダウンロード
print("\n" + "=" * 70 + f"\n6. モデル確認・ダウンロード\n" + "=" * 70)
print(f"使用モデル: {MODEL}")
res = requests.get(f"{OLLAMA_LOCAL_URL}/api/tags", timeout=10)
existing_models = [m["name"] for m in res.json().get("models", [])]
if any(m == MODEL for m in existing_models):
    print(f"[OK] {MODEL} は既に存在します")
else:
    print(f"[ダウンロード] {MODEL} をダウンロードします (初回は数分かかります)...")
    res_pull = subprocess.run(["ollama", "pull", MODEL], capture_output=False)
    if res_pull.returncode != 0:
        raise RuntimeError(f"{MODEL} のダウンロードに失敗しました")
    print(f"[OK] {MODEL} ダウンロード完了")

# 7. モデル一覧
print("\n" + "=" * 70 + "\n7. モデル一覧\n" + "=" * 70)
res = requests.get(f"{OLLAMA_LOCAL_URL}/api/tags", timeout=10)
available_models = [m["name"] for m in res.json().get("models", [])]
for m in available_models:
    print(" -", m)
if MODEL not in available_models:
    raise RuntimeError(f"モデル {MODEL} が見つかりません")
print(f"\n[OK] 使用モデル確認: {MODEL}")

# 8. ローカル推論テスト (ウォームアップ & タイムアウト5分)
print("\n" + "=" * 70 + "\n8. ローカル推論テスト\n" + "=" * 70)
print("モデルをGPUへロードしています...")
def test_local_model():
    try:
        payload = {"model": MODEL, "messages": [{"role": "user", "content": "こんにちは。日本語で短く自己紹介してください。"}], "stream": False}
        res = requests.post(f"{OLLAMA_LOCAL_URL}/api/chat", json=payload, timeout=300)
        print("HTTP Status:", res.status_code)
        if res.status_code != 200:
            print(res.text[:2000])
            return False
        msg = res.json().get("message", {}).get("content", "")
        print("\n[モデル応答]\n" + "-" * 50 + f"\n{msg}\n" + "-" * 50)
        return True
    except Exception as e:
        print("[エラー]:", e)
        return False

if not test_local_model():
    raise RuntimeError("ローカルモデル推論に失敗しました")
print("\n[OK] ローカル推論成功")

# 9. Cloudflare Tunnel Token入力
print("\n" + "=" * 70 + "\n9. Cloudflare Named Tunnel設定\n" + "=" * 70)
TUNNEL_TOKEN = None
try:
    from google.colab import userdata
    TUNNEL_TOKEN = userdata.get('CLOUDFLARE_TUNNEL_TOKEN')
    if TUNNEL_TOKEN:
        print("[OK] ColabシークレットからTunnel Tokenを自動読み込みしました")
except Exception:
    pass

if not TUNNEL_TOKEN:
    print("""
Cloudflare Dashboardで作成した Named Tunnel の Token を入力してください。
※Tokenは入力時に非表示になります。
""")
    TUNNEL_TOKEN = getpass.getpass("Cloudflare Tunnel Token: ")

if not TUNNEL_TOKEN:
    raise ValueError("Cloudflare Tunnel Tokenが入力されていません")
print("\n[OK] Tunnel Token取得完了")

# 10. Cloudflare Named Tunnel起動
print("\n" + "=" * 70 + "\n10. Cloudflare Named Tunnel起動\n" + "=" * 70)
print("Cloudflare Tunnelを起動しています...")
tunnel_process = subprocess.Popen(["cloudflared", "tunnel", "run", "--token", TUNNEL_TOKEN], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
time.sleep(10)
if tunnel_process.poll() is not None:
    print("[エラー] Cloudflare Tunnelが終了しました")
    raise RuntimeError("Cloudflare Named Tunnelの起動に失敗しました")
print("[OK] Cloudflare Named Tunnelプロセス起動")

# 11. 外部API接続診断
print("\n" + "=" * 70 + "\n11. 外部API接続診断\n" + "=" * 70)
print("接続先:", PUBLIC_URL)

def check_endpoint(name, method, endpoint, **kwargs):
    print(f"\n[{name}]")
    try:
        if method == "GET":
            res = requests.get(endpoint, timeout=60, **kwargs)
        else:
            res = requests.post(endpoint, timeout=300, **kwargs)
        print("HTTP Status:", res.status_code)
        print("Server:", res.headers.get("server"))
        if res.status_code != 200:
            print("Response:", res.text[:1000])
            return False
        print(f"[OK] {name}")
        return True
    except Exception as e:
        print(f"[エラー] {name}:", e)
        return False

local_ok = check_endpoint("1. Colab内 Ollama API", "GET", f"{OLLAMA_LOCAL_URL}/api/tags")
local_v1_ok = check_endpoint("2. Colab内 OpenAI互換API", "GET", f"{OLLAMA_LOCAL_URL}/v1/models")
external_models_ok = check_endpoint("3. Cloudflare経由 OpenAI /v1/models", "GET", f"{PUBLIC_URL}/v1/models")
external_chat_ok = check_endpoint("4. Cloudflare経由 Chat Completion", "POST", f"{PUBLIC_URL}/v1/chat/completions", json={"model": MODEL, "messages": [{"role": "user", "content": "こんにちは。日本語で一言だけ返してください。"}], "stream": False})

# 12. 最終結果
print("\n" + "=" * 70 + "\n■ 最終診断結果\n" + "=" * 70)
print("Local Ollama API:", "OK" if local_ok else "FAIL")
print("Local OpenAI API:", "OK" if local_v1_ok else "FAIL")
print("Cloudflare /v1/models:", "OK" if external_models_ok else "FAIL")
print("Cloudflare Chat API:", "OK" if external_chat_ok else "FAIL")

# 13. 接続情報
if local_ok and local_v1_ok and external_models_ok and external_chat_ok:
    print("\n" + "=" * 70 + "\n[成功] 全ての診断に成功しました\n" + "=" * 70)
    print(f"\n【OpenAI互換API】\nBase URL: {PUBLIC_URL}/v1\nModel: {MODEL}\nAPI Key: ollama")
    print(f"\n【Ollama API】\nBase URL: {PUBLIC_URL}")
    print(f"\n【Claude Code / Anthropic互換】\nBase URL: {PUBLIC_URL}\nAuth Token: ollama")
else:
    print("\n" + "=" * 70 + "\n[注意] 一部の診断に失敗しました\n" + "=" * 70)
    print("""
確認項目:
1. Cloudflare Named TunnelがRunningになっているか
2. Public Hostnameが設定されているか (Service: http://127.0.0.1:11434)
3. PUBLIC_URLが正しいドメインになっているか
4. Cloudflare Tunnel Tokenが正しいか
""")

# 14. Colab終了防止用メッセージ
print("\n" + "=" * 70 + "\n[重要]\n" + "=" * 70)
print("""
このColabセッションを終了すると、Ollama -> Qwen3.5 9B -> Cloudflare Tunnel の全てが停止します。
バックアップAIとして使用中は、このColabセッションを実行したままにしてください。
""")

Step 3. Cloudflare側に​戻る​:固定ドメインを​紐付ける

Cloudflare Dashboardのタブに戻ると、コネクタの接続が検知されて右下の 「Next(次へ)」 ボタンが押せるようになっています(※またはTunnels一覧画面から作成したトンネルの 「+ ルートを追加」 をクリックします)。

  1. ルートのタイプ選択ダイアログで 「公開アプリケーション」(パブリックホスト名を介してローカルアプリケーションをインターネットに公開する)を選択します。 ルートを追加ダイアログで公開アプリケーションを選択
  2. パブリックホスト名(Public Hostname)の設定画面で以下を入力して保存します:
    • Subdomain: ai (※ご自由にお好みのサブドメイン名を入力。空欄でルートドメインのままでもOK)
    • Domain: (※ご自身の所有・管理するドメインを選択)
    • Path: (空欄のまま)
    • Type: HTTP
    • URL: localhost:11434 (または 127.0.0.1:11434)
  3. 右下の 「Save tunnel」(またはルート保存)をクリックします。
これで設定完了!

指定した固定ドメイン(例: https://ai.example.com)に来たリクエストが、自動的にColabのOllamaへと繋がる永久的な仕組みが完成しました!


Step 4. ローカルPC側:手元アプリに​固定設定を​入れる

手元のアプリ(VS Code / Aider CLI / Cherry Studio 等)に、永久固定の接続設定を登録します。

① VS Code​(開発・コーディング用)

VS Code拡張機能(Roo Code, Cline, Continue 等)のプロバイダ設定で以下を登録:

  • Provider: OpenAI Compatible (または Ollama)
  • Base URL: https://ai.example.com/v1 (※ご自身の固定URL)
  • Model Name: qwen3.5:9b (またはColabで指定したモデル名)
  • API Key: ollama (ダミーでOK)

② CLI​(Aider ターミナルAIコーディングツール)

# 1. pipx で Aider をインストール (初回のみ)
pipx install aider-chat

# 2. 固定ドメインを指定して Aider を起動
aider --openai-api-base https://ai.example.com/v1 --openai-api-key ollama --model openai/qwen3.5:9b
環境変数で設定しておく場合

~/.zshrc 等に export OPENAI_API_BASE="https://ai.example.com/v1"export OPENAI_API_KEY="ollama" を記述しておけば、aider --model openai/qwen3.5:9b だけでいつでも即座に接続できます!

③ ブラウザUI​(文章執筆・雑談用)

Cherry Studio や Page Assist 等に登録:

  • Base URL: https://ai.example.com/v1
  • Model Name: qwen3.5:9b を選択

5. Phase 2:2回目以降の​日常運用​(制限が​来た​時)

明日以降、ChatGPT ProやClaude Codeで利用制限がかかった時は、行ったり来たりの作業は一切不要 です!

わずか​3ステップで​作業再開!

  1. Google Colabを開いて「セルを実行」する
  2. トークン(eyJ...)を貼り付けて Enter を押す
  3. 手元のアプリ(AiderやVS Code)でそのまま会話・コーディングを再開する!

※手元アプリのURL設定やCloudflareの画面を操作する必要は今後一切ありません。

さらに爆速化!Colabシークレット機能の活用

Google Colabの左サイドバーにある「シークレット(鍵アイコン)」に、名前 CLOUDFLARE_TUNNEL_TOKEN でトークン文字列を保存し「ノートブックからのアクセス」をONにしておくと、スクリプト実行時に自動でトークンが読み込まれます。

これを設定しておけば、Step 2のトークン手貼りすら不要になり、「Colabを開いてセルを再生するだけ(実質1ステップ・ワンクリック)」で即座に予備機を起動できるようになります!


6. 動作テスト&導通確認

実際に接続をテストし、動作確認を行います。

テスト1: Colab側の​導通確認

Colabのセルを再実行すると、外部API接続診断で4項目すべてが [OK] になり、無事に開通したことが確認できます。

Colabで再実行し全ての診断に成功した画面

テスト2: CLI / Aider での​コーディング・チャットテスト

ターミナルやVS Codeからリクエストを送り、Qwen3.5から正常に日本語でコードや回答が返ってくるか確認します。

Aider CLIでColab上のQwen3.5から正常に日本語応答が得られた画面

7. まとめ

Cookie Cat

メインAIの利用制限に悩まされている方は、ぜひ「Google Colab × Cloudflare Named Tunnel」による固定ドメインの予備機システムを試してみてね!

完全無料で構築できて、作業の手を止めない最強のバックアップ環境が手に入るよ!

関連記事